Version 2.7.0-dev.2.0
Merge commit '16cbabec3a00e715173c68e8f761a8e1296cc9e5' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6707c5a..eb17626 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -85,15 +85,15 @@
#### Linter
-The Linter was updated to `0.1.103`, which includes:
+The Linter was updated to `0.1.104`, which includes:
-* updates to `prefer_relative_imports` to use a faster and more robust way to check for self-package references
-* updates to our approach to checking for `lib` dir contents (speeding up `avoid_renaming_method_parameters` and
- making `prefer_relative_imports` and `public_member_api_docs` amenable to internal package formats -- w/o pubspecs)
+* updated `unnecessary_overrides` to allow overrides when annotations (besides `@override` are specified)
+* updated `file_names` to allow names w/ leading `_`'s (and improved performance)
+* new lint: `unnecessary_final`
#### Pub
-* `pub get` generates [`.dart_tools/package_config.json`](https://github.com/dart-lang/language/blob/62c036cc41b10fb543102d2f73ee132d1e2b2a0e/accepted/future-releases/language-versioning/package-config-file-v2.md)
+* `pub get` generates [`.dart_tool/package_config.json`](https://github.com/dart-lang/language/blob/62c036cc41b10fb543102d2f73ee132d1e2b2a0e/accepted/future-releases/language-versioning/package-config-file-v2.md)
in addition to `.packages` to support language versioning.
* `pub publish` now warns about the old flutter plugin registration format.
@@ -194,6 +194,12 @@
* Added optional `parent` parameter to `TimelineTask` constructor to allow for
linking of asynchronous timeline events in the DevTools timeline view.
+#### `dart:io`
+
+* Added `enableTimelineLogging` property to `HttpClient` which, when enabled,
+ will post HTTP connection and request information to the developer timeline
+ for all `HttpClient` instances.
+
### Dart VM
* Added a new tool for AOT compiling Dart programs to native, self-contained
diff --git a/DEPS b/DEPS
index 4c62d63..8583d7a 100644
--- a/DEPS
+++ b/DEPS
@@ -100,7 +100,7 @@
"intl_tag": "0.15.7",
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_tag": "2.0.9",
- "linter_tag": "0.1.103",
+ "linter_tag": "0.1.104",
"logging_tag": "0.11.3+2",
"markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
"markdown_tag": "2.1.1",
@@ -143,7 +143,7 @@
"typed_data_tag": "1.1.6",
"unittest_rev": "2b8375bc98bb9dc81c539c91aaea6adce12e1072",
"usage_tag": "3.4.0",
- "watcher_rev": "0.9.7+12-pub",
+ "watcher_rev": "0.9.7+13",
"web_components_rev": "8f57dac273412a7172c8ade6f361b407e2e4ed02",
"web_socket_channel_tag": "1.0.9",
"WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index db31ad4..4457f43 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -133,6 +133,9 @@
# Compile for Undefined Behavior Sanitizer to find reliance on undefined behavior.
is_ubsan = false
+
+ # Compile for execution in user-mode QEMU.
+ is_qemu = false
}
# =============================================================================
diff --git a/build/config/linux/BUILD.gn b/build/config/linux/BUILD.gn
index 70bb890..9e23651 100644
--- a/build/config/linux/BUILD.gn
+++ b/build/config/linux/BUILD.gn
@@ -6,6 +6,7 @@
config("sdk") {
ldflags = []
+ cflags = []
if (is_asan || is_lsan || is_msan || is_tsan || is_ubsan) {
ldflags += [ "-lrt" ]
@@ -23,7 +24,7 @@
}
if (sysroot != "") {
- cflags = [ "--sysroot=" + sysroot ]
+ cflags += [ "--sysroot=" + sysroot ]
ldflags += [ "--sysroot=" + sysroot ]
# Need to get some linker flags out of the sysroot.
@@ -44,10 +45,18 @@
]
}
}
+
+ if (is_qemu) {
+ cflags += ["-DDART_RUN_IN_QEMU_ARMv7"]
+ }
}
config("executable_config") {
- if (current_cpu != "x86") {
+ # GDB cannot find the executable's mapping in QEMU when PIE is enabled.
+ if (is_qemu) {
+ cflags = [ "-fno-pie" ]
+ ldflags = [ "-no-pie" ]
+ } else if (current_cpu != "x86") {
cflags = [ "-fPIE" ]
ldflags = [ "-pie" ]
}
diff --git a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
index 7bc4b9d9..a3e66b0 100644
--- a/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
+++ b/pkg/_fe_analyzer_shared/analysis_options_no_lints.yaml
@@ -12,3 +12,4 @@
- test/flow_analysis/nullability/data/**
- test/flow_analysis/reachability/data/**
- test/flow_analysis/type_promotion/data/**
+ - test/inheritance/data/**
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index 3e51f3c..891df0b 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -808,10 +808,9 @@
@override
void finish() {
if (_exceptionOccurred) {
- print('finish() (skipped)');
+ _wrap('finish() (skipped)', () {}, isPure: true);
} else {
- print('finish()');
- _wrapped.finish();
+ _wrap('finish()', () => _wrapped.finish(), isPure: true);
}
}
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 29f32d1..75251f5 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -1358,8 +1358,9 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageConstructorWithTypeParameters = const MessageCode(
"ConstructorWithTypeParameters",
- analyzerCodes: <String>["TYPE_PARAMETER_ON_CONSTRUCTOR"],
- message: r"""Constructors can't have type parameters.""");
+ index: 99,
+ message: r"""Constructors can't have type parameters.""",
+ tip: r"""Try removing the type parameters.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeConstructorWithWrongName = messageConstructorWithWrongName;
@@ -7888,6 +7889,14 @@
message: r"""Can't create typedef from non-function type.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeTypedefNotType = messageTypedefNotType;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageTypedefNotType = const MessageCode("TypedefNotType",
+ analyzerCodes: <String>["INVALID_TYPE_IN_TYPEDEF"],
+ message: r"""Can't create typedef from non-type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeUnexpectedDollarInString = messageUnexpectedDollarInString;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
index a9b9681..3442fe0 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart
@@ -71,7 +71,8 @@
}
abstract class StackListener extends Listener {
- final Stack stack = new Stack();
+ static const bool debugStack = false;
+ final Stack stack = debugStack ? new DebugStack() : new StackImpl();
/// Used to report an internal error encountered in the stack listener.
dynamic internalProblem(Message message, int charOffset, Uri uri);
@@ -112,10 +113,9 @@
bool checkState(Token token, List<ValueKind> kinds) {
bool success = true;
for (int kindIndex = 0; kindIndex < kinds.length; kindIndex++) {
- int stackIndex = stack.arrayLength - kindIndex - 1;
ValueKind kind = kinds[kindIndex];
- if (stackIndex >= 0) {
- Object value = stack.array[stackIndex];
+ if (kindIndex < stack.length) {
+ Object value = stack[kindIndex];
if (!kind.check(value)) {
success = false;
}
@@ -154,8 +154,7 @@
// Compute kind/stack frame information for all expected values plus 3 more
// stack elements if available.
for (int kindIndex = 0; kindIndex < kinds.length + 3; kindIndex++) {
- int stackIndex = stack.arrayLength - kindIndex - 1;
- if (stackIndex < 0 && kindIndex >= kinds.length) {
+ if (kindIndex >= stack.length && kindIndex >= kinds.length) {
// No more stack elements nor kinds to display.
break;
}
@@ -168,8 +167,8 @@
} else {
sb.write(padRight('---', 60));
}
- if (stackIndex >= 0) {
- Object value = stack.array[stackIndex];
+ if (kindIndex < stack.length) {
+ Object value = stack[kindIndex];
if (kind == null || kind.check(value)) {
sb.write(' ');
} else {
@@ -496,7 +495,29 @@
{bool wasHandled: false, List<LocatedMessage> context});
}
-class Stack {
+abstract class Stack {
+ /// Pops [count] elements from the stack and puts it into [list].
+ /// Returns [null] if a [ParserRecovery] value is found, or [list] otherwise.
+ List<Object> popList(int count, List<Object> list, NullValue nullValue);
+
+ void push(Object value);
+
+ /// Will return [null] instead of [NullValue].
+ Object get last;
+
+ bool get isNotEmpty;
+
+ List<Object> get values;
+
+ Object pop(NullValue nullValue);
+
+ int get length;
+
+ /// Raw, i.e. [NullValue]s will be returned instead of [null].
+ Object operator [](int index);
+}
+
+class StackImpl implements Stack {
List<Object> array = new List<Object>(8);
int arrayLength = 0;
@@ -509,6 +530,10 @@
return value is NullValue ? null : value;
}
+ Object operator [](int index) {
+ return array[arrayLength - 1 - index];
+ }
+
void push(Object value) {
array[arrayLength++] = value;
if (array.length == arrayLength) {
@@ -545,9 +570,7 @@
} else if (value is ParserRecovery) {
isParserRecovery = true;
} else {
- if (value is NullValue) {
- print(value);
- }
+ assert(value is! NullValue);
list[i] = value;
}
}
@@ -571,6 +594,54 @@
}
}
+class DebugStack implements Stack {
+ Stack realStack = new StackImpl();
+ Stack stackTraceStack = new StackImpl();
+ List<StackTrace> latestStacktraces = new List<StackTrace>();
+
+ @override
+ Object operator [](int index) {
+ Object result = realStack[index];
+ latestStacktraces.clear();
+ latestStacktraces.add(stackTraceStack[index]);
+ return result;
+ }
+
+ @override
+ bool get isNotEmpty => realStack.isNotEmpty;
+
+ @override
+ Object get last => this[0];
+
+ @override
+ int get length => realStack.length;
+
+ @override
+ Object pop(NullValue nullValue) {
+ Object result = realStack.pop(nullValue);
+ latestStacktraces.clear();
+ latestStacktraces.add(stackTraceStack.pop(null));
+ return result;
+ }
+
+ @override
+ List<Object> popList(int count, List<Object> list, NullValue nullValue) {
+ List<Object> result = realStack.popList(count, list, nullValue);
+ latestStacktraces.length = count;
+ stackTraceStack.popList(count, latestStacktraces, null);
+ return result;
+ }
+
+ @override
+ void push(Object value) {
+ realStack.push(value);
+ stackTraceStack.push(StackTrace.current);
+ }
+
+ @override
+ List<Object> get values => realStack.values;
+}
+
/// Helper constant for popping a list of the top of a [Stack]. This helper
/// returns null instead of empty lists, and the lists returned are of fixed
/// length.
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
index 58acca5..4b7dd09 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart
@@ -214,7 +214,9 @@
} else if (testFile is Directory) {
testName = testFileUri.pathSegments[testFileUri.pathSegments.length - 2];
additionalFiles = new Map<String, File>();
- for (FileSystemEntity entry in testFile.listSync(recursive: true)) {
+ for (FileSystemEntity entry in testFile
+ .listSync(recursive: true)
+ .where((entity) => !entity.path.endsWith('~'))) {
if (entry is! File) continue;
if (entry.uri.pathSegments.last == "main.dart") {
mainTestFile = entry;
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/from_opt_out/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/from_opt_out/main.dart
index 9a0cf4f..39c3c5f 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/from_opt_out/main.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/from_opt_out/main.dart
@@ -9,13 +9,13 @@
/*class: Class1:Class1,LegacyClass1,Object*/
class Class1 extends LegacyClass1 {}
-/*class: Class2:Class2<T*>,LegacyClass2<T>,Object*/
+/*class: Class2:Class2<T>,LegacyClass2<T>,Object*/
class Class2<T> extends LegacyClass2<T> {}
-/*class: Class3a:Class3a<T*>,GenericInterface<T*>,LegacyClass3<T>,Object*/
+/*class: Class3a:Class3a<T>,GenericInterface<T*>,LegacyClass3<T>,Object*/
class Class3a<T> extends LegacyClass3<T> {}
-/*class: Class3b:Class3b<T*>,GenericInterface<T*>,LegacyClass3<T>,Object*/
+/*class: Class3b:Class3b<T>,GenericInterface<T*>,LegacyClass3<T>,Object*/
class
// TODO(johnniwinther): Avoid this error.
/*error: AmbiguousSupertypes*/
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 75207a9..6b68d27 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -257,7 +257,7 @@
<p><a href="#domain_completion">Completion</a></p><ul><li><a href="#request_completion.getSuggestions">completion.getSuggestions</a></li>
<li><a href="#request_completion.setSubscriptions">completion.setSubscriptions</a></li>
-<li><a href="#request_completion.registerLibraryPaths">completion.registerLibraryPaths</a></li>
+<li><a class="deprecated" href="#request_completion.registerLibraryPaths">completion.registerLibraryPaths</a></li>
<li><a href="#request_completion.getSuggestionDetails">completion.getSuggestionDetails</a></li>
</ul>
@@ -1518,7 +1518,7 @@
<h4>parameters:</h4><dl><dt class="field"><b>subscriptions: List<<a href="#type_CompletionService">CompletionService</a>></b></dt><dd>
<p>A list of the services being subscribed to.</p>
- </dd></dl></dd><dt class="request"><a name="request_completion.registerLibraryPaths">completion.registerLibraryPaths</a></dt><dd><div class="box"><pre>request: {
+ </dd></dl></dd><dt class="request deprecated"><a name="request_completion.registerLibraryPaths">completion.registerLibraryPaths</a></dt><dd><div class="box"><pre>request: {
"id": String
"method": "completion.registerLibraryPaths"
"params": {
@@ -5131,6 +5131,11 @@
<p>
The given location does not have a supported widget.
</p>
+ </dd><dt class="value">FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION</dt><dd>
+
+ <p>
+ The given property expression is invalid, e.g. has a syntax error.
+ </p>
</dd><dt class="value">FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID</dt><dd>
<p>
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 9e8e335..a712f60 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -15780,6 +15780,9 @@
* corresponds to an optional parameter, the corresponding named argument is
* removed. If the property isRequired is true,
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED error is generated.
+ *
+ * If the expression is not a syntactically valid Dart code, then
+ * FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION is reported.
*/
FlutterWidgetPropertyValue get value => _value;
@@ -15790,6 +15793,9 @@
* corresponds to an optional parameter, the corresponding named argument is
* removed. If the property isRequired is true,
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED error is generated.
+ *
+ * If the expression is not a syntactically valid Dart code, then
+ * FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION is reported.
*/
void set value(FlutterWidgetPropertyValue value) {
this._value = value;
@@ -19717,6 +19723,7 @@
* DEBUG_PORT_COULD_NOT_BE_OPENED
* FILE_NOT_ANALYZED
* FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET
+ * FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED
* FORMAT_INVALID_FILE
@@ -19778,6 +19785,14 @@
const RequestErrorCode._("FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET");
/**
+ * The given property expression is invalid, e.g. has a syntax error.
+ */
+ static const RequestErrorCode
+ FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION =
+ const RequestErrorCode._(
+ "FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION");
+
+ /**
* The given property identifier is not valid. It might have never been
* valid, or a change to code invalidated it, or its TTL was exceeded.
*/
@@ -19985,6 +20000,7 @@
DEBUG_PORT_COULD_NOT_BE_OPENED,
FILE_NOT_ANALYZED,
FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET,
+ FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION,
FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID,
FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED,
FORMAT_INVALID_FILE,
@@ -20030,6 +20046,8 @@
return FILE_NOT_ANALYZED;
case "FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET":
return FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET;
+ case "FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION":
+ return FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION;
case "FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID":
return FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID;
case "FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED":
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 66a68e8..5da8cbf 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -786,8 +786,8 @@
bool isManaged = rootInfo._managesOrHasChildThatManages(includedPath);
if (!isManaged) {
ContextInfo parent = _getParentForNewContext(includedPath);
- changeSubscriptions[includedFolder] =
- includedFolder.changes.listen(_handleWatchEvent);
+ changeSubscriptions[includedFolder] = includedFolder.changes
+ .listen(_handleWatchEvent, onError: _handleWatchInterruption);
_createContexts(parent, includedFolder, excludedPaths, false);
}
}
@@ -1407,6 +1407,15 @@
callbacks.afterWatchEvent(event);
}
+ /// On windows, the directory watcher may overflow, and we must recover.
+ void _handleWatchInterruption(dynamic error, StackTrace stackTrace) {
+ // We've handled the error, so we only have to log it.
+ AnalysisEngine.instance.instrumentationService
+ .logError('Watcher error; refreshing contexts.\n$error\n$stackTrace');
+ // TODO(mfairhurst): Optimize this, or perhaps be less complete.
+ refresh(null);
+ }
+
void _handleWatchEventImpl(WatchEvent event) {
// Figure out which context this event applies to.
// TODO(brianwilkerson) If a file is explicitly included in one context
diff --git a/pkg/analysis_server/lib/src/domain_kythe.dart b/pkg/analysis_server/lib/src/domain_kythe.dart
index 4e7cffb..8acf1e6 100644
--- a/pkg/analysis_server/lib/src/domain_kythe.dart
+++ b/pkg/analysis_server/lib/src/domain_kythe.dart
@@ -16,7 +16,6 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
@@ -58,16 +57,11 @@
<KytheGetKytheEntriesResult>[];
ResolvedUnitResult result = await server.getResolvedUnit(file);
if (result?.state == ResultState.VALID) {
- TypeSystem typeSystem = await result.libraryElement.session.typeSystem;
List<KytheEntry> entries = <KytheEntry>[];
// TODO(brianwilkerson) Figure out how to get the list of files.
List<String> files = <String>[];
- result.unit.accept(new KytheDartVisitor(
- server.resourceProvider,
- entries,
- file,
- new InheritanceManager3(typeSystem),
- result.content));
+ result.unit.accept(new KytheDartVisitor(server.resourceProvider,
+ entries, file, new InheritanceManager3(), result.content));
allResults.add(new KytheGetKytheEntriesResult(entries, files));
}
//
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
index 267a8c9..4fc9eb5 100644
--- a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -8,6 +8,7 @@
import 'package:analysis_server/src/edit/fix/fix_code_task.dart';
import 'package:analysis_server/src/edit/nnbd_migration/highlight_css.dart';
import 'package:analysis_server/src/edit/nnbd_migration/highlight_js.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/index_renderer.dart';
import 'package:analysis_server/src/edit/nnbd_migration/info_builder.dart';
import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_listener.dart';
import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_renderer.dart';
@@ -82,7 +83,7 @@
@override
Future<void> finish() async {
migration.finish();
- if (outputDir != null && port == null) {
+ if (outputDir != null) {
OverlayResourceProvider provider = listener.server.resourceProvider;
Folder outputFolder = provider.getFolder(outputDir);
if (!outputFolder.exists) {
@@ -92,23 +93,17 @@
}
if (port != null) {
OverlayResourceProvider provider = listener.server.resourceProvider;
- InfoBuilder infoBuilder =
- InfoBuilder(instrumentationListener.data, listener);
+ InfoBuilder infoBuilder = InfoBuilder(
+ provider, includedRoot, instrumentationListener.data, listener);
Set<UnitInfo> unitInfos = await infoBuilder.explainMigration();
var pathContext = provider.pathContext;
MigrationInfo migrationInfo = MigrationInfo(
unitInfos, infoBuilder.unitMap, pathContext, includedRoot);
PathMapper pathMapper = PathMapper(provider, outputDir, includedRoot);
- // TODO(brianwilkerson) Print a URL that users can paste into the browser.
- // The code below is close to right, but computes the wrong path. We
- // don't have enough information to pick a single library inside `lib`,
- // so we might want to consider alternatives, such as a directory listing
- // page or an empty file page.
-// print(Uri(
-// scheme: 'http',
-// host: 'localhost',
-// port: 10501,
-// path: pathMapper.map('$includedRoot/lib/logging.dart')));
+
+ print(Uri(
+ scheme: 'http', host: 'localhost', port: port, path: includedRoot));
+
// TODO(brianwilkerson) Capture the server so that it can be closed
// cleanly.
HttpPreviewServer(migrationInfo, pathMapper).serveHttp(port);
@@ -250,8 +245,8 @@
// Remove any previously generated output.
folder.getChildren().forEach((resource) => resource.delete());
// Gather the data needed in order to produce the output.
- InfoBuilder infoBuilder =
- InfoBuilder(instrumentationListener.data, listener);
+ InfoBuilder infoBuilder = InfoBuilder(
+ provider, includedRoot, instrumentationListener.data, listener);
Set<UnitInfo> unitInfos = await infoBuilder.explainMigration();
var pathContext = provider.pathContext;
MigrationInfo migrationInfo = MigrationInfo(
@@ -267,11 +262,23 @@
output.writeAsStringSync(rendered);
}
+ //
+ // Generate the index file.
+ //
+ String indexPath = pathContext.join(folder.path, 'index.html');
+ File output = provider.getFile(indexPath);
+ output.parent.create();
+ String rendered = IndexRenderer(migrationInfo, writeToDisk: true).render();
+ output.writeAsStringSync(rendered);
+ //
// Generate the files in the package being migrated.
+ //
for (UnitInfo unitInfo in unitInfos) {
render(unitInfo);
}
+ //
// Generate other dart files.
+ //
for (UnitInfo unitInfo in infoBuilder.unitMap.values) {
if (!unitInfos.contains(unitInfo)) {
if (unitInfo.content == null) {
@@ -344,7 +351,9 @@
@override
void addFix(SingleNullabilityFix fix) {
- listener.addSuggestion(fix.description.appliedMessage, fix.location);
+ for (Location location in fix.locations) {
+ listener.addSuggestion(fix.description.appliedMessage, location);
+ }
}
@override
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/index_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/index_renderer.dart
new file mode 100644
index 0000000..cf34775c
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/index_renderer.dart
@@ -0,0 +1,116 @@
+// Copyright (c) 2019, 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.
+
+import 'package:analysis_server/src/edit/nnbd_migration/instrumentation_renderer.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
+import 'package:path/src/context.dart';
+
+/// The renderer used to displayed when the root of the included path is requested.
+class IndexRenderer {
+ /// Information for a whole migration, so that libraries can reference each
+ /// other.
+ final MigrationInfo migrationInfo;
+
+ /// A flag indicating whether the paths for the links should be computed for
+ /// the case where the rendered index will be written to disk.
+ final bool writeToDisk;
+
+ /// Initialize a newly index renderer.
+ IndexRenderer(this.migrationInfo, {this.writeToDisk = false});
+
+ /// Builds an HTML view of the included root directory.
+ String render() {
+ Context pathContext = migrationInfo.pathContext;
+ String includedRoot = migrationInfo.includedRoot;
+
+ StringBuffer buf = StringBuffer();
+ buf.write('''
+<html>
+ <head>
+ <title>Non-nullable fix instrumentation report</title>
+ <style>
+a:link {
+ color: inherit;
+ text-decoration-line: none;
+}
+
+a:visited {
+ color: inherit;
+ text-decoration-line: none;
+}
+
+a:hover {
+ text-decoration-line: underline;
+}
+
+body {
+ font-family: sans-serif;
+ padding: 1em;
+}
+
+.navigationHeader {
+ padding-left: 1em;
+}
+
+.navigationLinks {
+ padding-left: 2em;
+}
+
+.selectedFile {
+ font-weight: bold;
+}
+ </style>
+ </head>
+ <body>
+ <h1>Preview of NNBD migration</h1>
+ <p><b>
+ Select a migrated file to see the suggested modifications below.
+ </b></p>
+ <div class="navigationHeader">
+''');
+ buf.writeln(includedRoot);
+ buf.write('''
+ </div>
+ <div class="navigationLinks">
+''');
+ for (UnitInfo unit in migrationInfo.units) {
+ buf.write('<a href="');
+ buf.write(_pathTo(unit, pathContext, includedRoot));
+ buf.write('">');
+ buf.write(_name(unit, pathContext, includedRoot));
+ buf.write('</a> ');
+ buf.write(_modificationCount(unit));
+ buf.write('<br/>');
+ }
+ buf.write('''
+ </div>
+ </body>
+</html>
+''');
+ return buf.toString();
+ }
+
+ /// Return the number of modifications made to the [unit].
+ String _modificationCount(UnitInfo unit) {
+ int count = unit.fixRegions.length;
+ return count == 1 ? '(1 modification)' : '($count modifications)';
+ }
+
+ /// Return the path to [unit] from [includedRoot], to be used as a display
+ /// name for a library.
+ String _name(UnitInfo unit, Context pathContext, String includedRoot) =>
+ pathContext.relative(unit.path, from: includedRoot);
+
+ /// The path to [target], relative to [includedRoot].
+ String _pathTo(UnitInfo target, Context pathContext, String includedRoot) {
+ String targetPath;
+ if (writeToDisk) {
+ targetPath = pathContext.setExtension(target.path, '.html');
+ } else {
+ targetPath = target.path;
+ }
+ String sourceDir = pathContext.dirname(includedRoot);
+ return pathContext.relative(targetPath, from: sourceDir);
+ }
+}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
index c5592b5..611c890 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/info_builder.dart
@@ -15,6 +15,7 @@
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
show Location, SourceEdit, SourceFileEdit;
@@ -36,6 +37,11 @@
/// A builder used to build the migration information for a library.
class InfoBuilder {
+ /// The resource provider used to access the file system.
+ ResourceProvider provider;
+
+ String includedPath;
+
/// The instrumentation information gathered while the migration engine was
/// running.
final InstrumentationInformation info;
@@ -52,7 +58,8 @@
final Map<String, UnitInfo> unitMap = {};
/// Initialize a newly created builder.
- InfoBuilder(this.info, this.listener, {this.explainNonNullableTypes = false});
+ InfoBuilder(this.provider, this.includedPath, this.info, this.listener,
+ {this.explainNonNullableTypes = false});
/// The analysis server used to get information about libraries.
AnalysisServer get server => listener.server;
@@ -74,48 +81,94 @@
for (ResolvedUnitResult unitResult in result.units) {
SourceFileEdit edit =
listener.sourceChange.getFileEdit(unitResult.path);
- units.add(_explainUnit(sourceInfo, unitResult, edit));
+ UnitInfo unit = _explainUnit(sourceInfo, unitResult, edit);
+ if (provider.pathContext.isWithin(includedPath, unitResult.path)) {
+ units.add(unit);
+ }
}
}
}
return units;
}
+ Iterable<EdgeInfo> upstreamTriggeredEdges(NullabilityNodeInfo node,
+ [List<RegionDetail> details]) {
+ var edges = <EdgeInfo>[];
+ for (EdgeInfo edge in node.upstreamEdges) {
+ if (node.isExactNullable && edge.sourceNode.isExactNullable) {
+ // When an exact nullable points here, the nullability propagated
+ // in the other direction.
+ continue;
+ }
+ if (edge.isTriggered) {
+ edges.add(edge);
+ }
+ }
+ for (final containerNode in node.outerCompoundNodes) {
+ edges.addAll(upstreamTriggeredEdges(containerNode, details));
+ }
+
+ return edges;
+ }
+
/// Return detail text for a fix built from an edge with [node] as a
/// destination.
- String _baseDescriptionForOrigin(EdgeOriginInfo origin) {
+ String _baseDescriptionForOrigin(
+ EdgeOriginInfo origin, NullabilityFixKind fixKind) {
AstNode node = origin.node;
AstNode parent = node.parent;
- if (node is DefaultFormalParameter) {
+ String aNullableDefault(DefaultFormalParameter node) {
Expression defaultValue = node.defaultValue;
if (defaultValue == null) {
- return "This parameter has an implicit default value of 'null'";
+ return "an implicit default value of 'null'";
} else if (defaultValue is NullLiteral) {
- return "This parameter has an explicit default value of 'null'";
+ return "an explicit default value of 'null'";
}
- return "This parameter has a nullable default value";
+ return "a nullable default value";
+ }
+
+ if (node is DefaultFormalParameter) {
+ if (fixKind == NullabilityFixKind.addRequired) {
+ return "This parameter is non-nullable, so cannot have "
+ "${aNullableDefault(node)}";
+ } else {
+ return "This parameter has ${aNullableDefault(node)}";
+ }
} else if (node is FieldFormalParameter) {
AstNode parent = node.parent;
if (parent is DefaultFormalParameter) {
- Expression defaultValue = parent.defaultValue;
- if (defaultValue == null) {
- return "This field is initialized by an optional field formal "
- "parameter that has an implicit default value of 'null'";
- } else if (defaultValue is NullLiteral) {
- return "This field is initialized by an optional field formal "
- "parameter that has an explicit default value of 'null'";
- }
return "This field is initialized by an optional field formal "
- "parameter that has a nullable default value";
+ "parameter that has ${aNullableDefault(parent)}";
}
return "This field is initialized by a field formal parameter and a "
"nullable value is passed as an argument";
} else if (parent is AsExpression) {
return "The value of the expression is nullable";
}
- String nullableValue =
- node is NullLiteral ? "an explicit 'null'" : "a nullable value";
+
+ // Text indicating the type of nullable value found.
+ String nullableValue;
+ if (node is NullLiteral) {
+ nullableValue = "an explicit 'null'";
+ } else if (origin.kind == EdgeOriginKind.dynamicAssignment) {
+ nullableValue = "a dynamic value, which is nullable";
+ } else {
+ nullableValue = "a nullable value";
+ }
+
+ CompilationUnit unit = node.thisOrAncestorOfType<CompilationUnit>();
+ int lineNumber = unit.lineInfo.getLocation(node.offset).lineNumber;
+
+ if (origin.kind == EdgeOriginKind.parameterInheritance) {
+ return "The corresponding parameter in the overridden method is "
+ "nullable";
+ } else if (origin.kind == EdgeOriginKind.returnTypeInheritance) {
+ return "An overridding method has a nullable return value";
+ } else if (origin.kind == EdgeOriginKind.uninitializedRead) {
+ return "Used on line $lineNumber, when it is possibly uninitialized";
+ }
+
if (parent is ArgumentList) {
return capitalize("$nullableValue is passed as an argument");
}
@@ -145,8 +198,6 @@
return (ancestor is TypedLiteral) ? ancestor : null;
}
- CompilationUnit unit = node.thisOrAncestorOfType<CompilationUnit>();
- int lineNumber = unit.lineInfo.getLocation(node.offset).lineNumber;
FunctionBody functionBody = findFunctionBody();
if (functionBody != null) {
AstNode function = functionBody.parent;
@@ -178,13 +229,24 @@
return "This field is initialized to $nullableValue";
}
return "This variable is initialized to $nullableValue";
+ } else if (node is ConstructorDeclaration &&
+ origin.kind == EdgeOriginKind.fieldNotInitialized) {
+ String constructorName =
+ node.declaredElement.enclosingElement.displayName;
+ if (node.declaredElement.displayName.isNotEmpty) {
+ constructorName =
+ "$constructorName.${node.declaredElement.displayName}";
+ }
+ return "The constructor '$constructorName' does not initialize this "
+ "field in its initializer list";
}
return capitalize("$nullableValue is assigned");
}
/// Return a description of the given [origin].
- String _buildDescriptionForOrigin(EdgeOriginInfo origin) {
- String description = _baseDescriptionForOrigin(origin);
+ String _buildDescriptionForOrigin(
+ EdgeOriginInfo origin, NullabilityFixKind fixKind) {
+ String description = _baseDescriptionForOrigin(origin, fixKind);
if (_inTestCode(origin.node)) {
// TODO(brianwilkerson) Don't add this if the graph node with which the
// origin is associated is also in test code.
@@ -194,7 +256,8 @@
}
/// Return a description of the given [origin] associated with the [edge].
- RegionDetail _buildDetailForOrigin(EdgeOriginInfo origin, EdgeInfo edge) {
+ RegionDetail _buildDetailForOrigin(
+ EdgeOriginInfo origin, EdgeInfo edge, NullabilityFixKind fixKind) {
AstNode node = origin.node;
NavigationTarget target;
// Some nodes don't need a target; default formal parameters
@@ -202,27 +265,22 @@
if (node is DefaultFormalParameter && node.defaultValue == null) {
target = null;
} else {
- if (origin.kind == EdgeOriginKind.inheritance) {
+ if (origin.kind == EdgeOriginKind.parameterInheritance ||
+ origin.kind == EdgeOriginKind.returnTypeInheritance) {
// The node is the method declaration in the subclass and we want to
- // link to the corresponding parameter in the declaration in the
- // superclass.
+ // link to the either the corresponding parameter in the declaration in
+ // the superclass, or the return type in the declaration in that
+ // subclass.
TypeAnnotation type = info.typeAnnotationForNode(edge.sourceNode);
if (type != null) {
CompilationUnit unit = type.thisOrAncestorOfType<CompilationUnit>();
target = _targetForNode(unit.declaredElement.source.fullName, type);
- return RegionDetail(
- "The corresponding parameter in the overridden method is "
- "nullable",
- target);
- // TODO(srawlins): Also, this could be where a return type in an
- // overridden method is made nullable because an overriding method
- // was found with a nullable return type. Figure out how to tell
- // which situation we are in.
}
+ } else {
+ target = _targetForNode(origin.source.fullName, node);
}
- target = _targetForNode(origin.source.fullName, node);
}
- return RegionDetail(_buildDescriptionForOrigin(origin), target);
+ return RegionDetail(_buildDescriptionForOrigin(origin, fixKind), target);
}
/// Compute the details for the fix with the given [fixInfo].
@@ -230,23 +288,48 @@
List<RegionDetail> details = [];
for (FixReasonInfo reason in fixInfo.reasons) {
if (reason is NullabilityNodeInfo) {
- for (EdgeInfo edge in reason.upstreamEdges) {
- if (edge.isTriggered) {
- EdgeOriginInfo origin = info.edgeOrigin[edge];
- if (origin != null) {
- details.add(_buildDetailForOrigin(origin, edge));
- } else {
- details.add(
- RegionDetail('upstream edge with no origin ($edge)', null));
+ if (reason.isExactNullable) {
+ // When the node is exact nullable, that nullability propagated from
+ // downstream.
+ for (EdgeInfo edge in reason.downstreamEdges) {
+ final exactNullableDownstream = edge.destinationNode;
+ if (!exactNullableDownstream.isExactNullable) {
+ // This wasn't the source of the nullability.
+ continue;
}
+
+ var nodeInfo = info.nodeInfoFor(exactNullableDownstream);
+ if (nodeInfo != null) {
+ // TODO(mfairhurst): Give a better text description.
+ details.add(RegionDetail('This is later required to accept null.',
+ _targetForNode(nodeInfo.filePath, nodeInfo.astNode)));
+ } else {
+ details.add(RegionDetail(
+ 'exact nullable node with no info ($exactNullableDownstream)',
+ null));
+ }
+ }
+ }
+
+ for (EdgeInfo edge in upstreamTriggeredEdges(reason)) {
+ EdgeOriginInfo origin = info.edgeOrigin[edge];
+ if (origin != null) {
+ details.add(_buildDetailForOrigin(
+ origin, edge, fixInfo.fix.description.kind));
+ } else {
+ details.add(
+ RegionDetail('upstream edge with no origin ($edge)', null));
}
}
} else if (reason is EdgeInfo) {
NullabilityNodeInfo destination = reason.destinationNode;
- var nodeInfo = info.nodeInfoFor(destination);
- if (nodeInfo != null) {
- details.add(RegionDetail(nodeInfo.descriptionForDestination,
- _targetForNode(nodeInfo.filePath, nodeInfo.astNode)));
+ NodeInformation nodeInfo = info.nodeInfoFor(destination);
+ if (nodeInfo != null && nodeInfo.astNode != null) {
+ NavigationTarget target;
+ if (destination != info.never && destination != info.always) {
+ target = _targetForNode(nodeInfo.filePath, nodeInfo.astNode);
+ }
+ details.add(RegionDetail(nodeInfo.descriptionForDestination, target));
} else {
details.add(RegionDetail('node with no info ($destination)', null));
}
@@ -258,6 +341,20 @@
return details;
}
+ /// Return a list of edits that can be applied.
+ List<EditDetail> _computeEdits(FixInfo fixInfo) {
+ // TODO(brianwilkerson) Add other kinds of edits, such as adding an assert.
+ List<EditDetail> edits = [];
+ SingleNullabilityFix fix = fixInfo.fix;
+ if (fix.description.kind == NullabilityFixKind.makeTypeNullable) {
+ for (Location location in fix.locations) {
+ edits.add(EditDetail(
+ 'Force type to be non-nullable.', location.offset, 0, '/*!*/'));
+ }
+ }
+ return edits;
+ }
+
/// Return the navigation sources for the unit associated with the [result].
List<NavigationSource> _computeNavigationSources(ResolvedUnitResult result) {
NavigationCollectorImpl collector = new NavigationCollectorImpl();
@@ -302,13 +399,6 @@
details.add(RegionDetail(
'This value is unconditionally used in a non-nullable context',
target));
- } else if (origin.kind == EdgeOriginKind.inheritance) {
- // TODO(srawlins): Figure out why this EdgeOriginKind is used.
- details.add(RegionDetail('Something about inheritance', target));
- } else if (origin.kind == EdgeOriginKind.initializerInference) {
- // TODO(srawlins): Figure out why this EdgeOriginKind is used.
- details.add(
- RegionDetail('Something about initializer inheritance', target));
} else if (origin.kind == EdgeOriginKind.nonNullAssertion) {
details
.add(RegionDetail('This value is asserted to be non-null', target));
@@ -340,11 +430,11 @@
_computeUpstreamTriggeredDetails(upstreamTriggeredEdgeInfos);
TypeAnnotation node = nonNullableType.key;
regions.add(RegionInfo(
+ RegionType.nonNullableType,
mapper.map(node.offset),
node.length,
"This type is not changed; it is determined to be non-nullable",
- details,
- RegionType.nonNullableType));
+ details));
}
}
}
@@ -377,12 +467,15 @@
if (fixInfo != null) {
String explanation = '${fixInfo.fix.description.appliedMessage}.';
List<RegionDetail> details = _computeDetails(fixInfo);
+ List<EditDetail> edits = _computeEdits(fixInfo);
if (length > 0) {
- regions.add(RegionInfo(mapper.map(offset), length, explanation,
- details, RegionType.fix));
+ regions.add(RegionInfo(
+ RegionType.fix, mapper.map(offset), length, explanation, details,
+ edits: edits));
}
- regions.add(RegionInfo(mapper.map(end), replacement.length, explanation,
- details, RegionType.fix));
+ regions.add(RegionInfo(RegionType.fix, mapper.map(end),
+ replacement.length, explanation, details,
+ edits: edits));
}
}
if (explainNonNullableTypes) {
@@ -400,9 +493,10 @@
FixInfo _findFixInfo(SourceInformation sourceInfo, int offset) {
for (MapEntry<SingleNullabilityFix, List<FixReasonInfo>> entry
in sourceInfo.fixes.entries) {
- Location location = entry.key.location;
- if (location.offset == offset) {
- return FixInfo(entry.key, entry.value);
+ for (Location location in entry.key.locations) {
+ if (location.offset == offset) {
+ return FixInfo(entry.key, entry.value);
+ }
}
}
return null;
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart
index 6510931..0176e1e 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_information.dart
@@ -63,17 +63,13 @@
final Element element;
- final String descriptionPrefix;
-
- NodeInformation(
- this.filePath, this.astNode, this.element, this.descriptionPrefix);
+ NodeInformation(this.filePath, this.astNode, this.element);
/// Return detail text for a fix built from an edge with this node as a
/// destination.
String get descriptionForDestination {
- // TODO(paulberry): describe AST nodes
- var description = (element ?? '???').toString();
- return "A nullable value can't be used as $descriptionPrefix$description";
+ // TODO(paulberry): describe AST nodes.
+ return "A nullable value can't be used here";
}
}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
index 0f977ed..db35c5e 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_listener.dart
@@ -22,21 +22,21 @@
@override
void explicitTypeNullability(
Source source, TypeAnnotation typeAnnotation, NullabilityNodeInfo node) {
- data.nodeInformation[node] = NodeInformation(
- _filePathForSource(source), typeAnnotation, null, 'the explicit type ');
+ data.nodeInformation[node] =
+ NodeInformation(_filePathForSource(source), typeAnnotation, null);
_sourceInfo(source).explicitTypeNullability[typeAnnotation] = node;
}
@override
void externalDecoratedType(Element element, DecoratedTypeInfo decoratedType) {
- _storeNodeInformation(decoratedType, element.source, null, element, '');
+ _storeNodeInformation(decoratedType, element.source, null, element);
}
@override
void externalDecoratedTypeParameterBound(
TypeParameterElement typeParameter, DecoratedTypeInfo decoratedType) {
_storeNodeInformation(
- decoratedType, typeParameter.source, null, typeParameter, 'bound of ');
+ decoratedType, typeParameter.source, null, typeParameter);
}
@override
@@ -59,24 +59,20 @@
@override
void implicitReturnType(
Source source, AstNode node, DecoratedTypeInfo decoratedReturnType) {
- _storeNodeInformation(
- decoratedReturnType, source, node, null, 'return type of ');
+ _storeNodeInformation(decoratedReturnType, source, node, null);
}
@override
void implicitType(
Source source, AstNode node, DecoratedTypeInfo decoratedType) {
- _storeNodeInformation(decoratedType, source, node, null, 'type of ');
+ _storeNodeInformation(decoratedType, source, node, null);
}
@override
void implicitTypeArguments(
Source source, AstNode node, Iterable<DecoratedTypeInfo> types) {
- int i = 0;
for (var type in types) {
- _storeNodeInformation(
- type, source, node, null, 'implicit type argument $i of ');
- i++;
+ _storeNodeInformation(type, source, node, null);
}
}
@@ -94,30 +90,35 @@
SourceInformation _sourceInfo(Source source) =>
data.sourceInformation.putIfAbsent(source, () => SourceInformation());
+ // TODO(srawlins): This code is completely untested.
void _storeNodeInformation(DecoratedTypeInfo decoratedType, Source source,
- AstNode astNode, Element element, String description) {
+ AstNode astNode, Element element) {
// Make sure source info exists for the given source.
_sourceInfo(source);
- data.nodeInformation[decoratedType.node] = NodeInformation(
- _filePathForSource(source), astNode, element, description);
+ data.nodeInformation[decoratedType.node] =
+ NodeInformation(_filePathForSource(source), astNode, element);
var dartType = decoratedType.type;
if (dartType is InterfaceType) {
for (int i = 0; i < dartType.typeArguments.length; i++) {
- _storeNodeInformation(decoratedType.typeArgument(i), source, astNode,
- element, 'type argument $i of $description');
+ _storeNodeInformation(
+ decoratedType.typeArgument(i), source, astNode, element);
}
} else if (dartType is FunctionType) {
- _storeNodeInformation(decoratedType.returnType, source, astNode, element,
- 'return type of $description');
+ _storeNodeInformation(
+ decoratedType.returnType,
+ source,
+ astNode,
+ element,
+ );
int i = 0;
for (var parameter in dartType.parameters) {
if (parameter.isNamed) {
var name = parameter.name;
- _storeNodeInformation(decoratedType.namedParameter(name), source,
- astNode, element, 'named parameter $name of $description');
+ _storeNodeInformation(
+ decoratedType.namedParameter(name), source, astNode, element);
} else {
- _storeNodeInformation(decoratedType.positionalParameter(i), source,
- astNode, element, 'positional parameter $i of $description');
+ _storeNodeInformation(
+ decoratedType.positionalParameter(i), source, astNode, element);
i++;
}
}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
index cb4ae0c..e3070f9 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/instrumentation_renderer.dart
@@ -77,6 +77,16 @@
font-weight: bold;
}
+.content {
+ font-family: monospace;
+ /* Vertical margin around content. */
+ margin: 1em 0;
+ /* Offset the margin introduced by the absolutely positioned child div. */
+ margin-left: -0.5em;
+ position: relative;
+ white-space: pre;
+}
+
.code {
left: 0.5em;
/* Increase line height to make room for borders in non-nullable type
@@ -84,14 +94,16 @@
*/
line-height: 1.3;
padding-left: 60px;
- position: absolute;
+ position: inherit;
top: 0.5em;
}
-.content {
- font-family: monospace;
- position: relative;
- white-space: pre;
+.navigationHeader {
+ padding-left: 1em;
+}
+
+.navigationLinks {
+ padding-left: 2em;
}
.regions {
@@ -176,6 +188,10 @@
visibility: visible;
}
+.selectedFile {
+ font-weight: bold;
+}
+
.target {
background-color: #FFFF99;
position: relative;
@@ -184,17 +200,25 @@
</style>
</head>
<body>
- <h1>Non-nullable fix instrumentation report</h1>
- <p>Migrated files:</p>
- <div class="navigation">
+ <h1>Preview of NNBD migration</h1>
+ <p><b>
+ Select a migrated file to see the suggested modifications below.
+ </b></p>
+ <div class="navigationHeader">
+ {{ root }}
+ </div>
+ <div class="navigationLinks">
{{# links }}
{{# isLink }}<a href="{{ href }}">{{ name }}</a>{{/ isLink }}
- {{^ isLink }}{{ name }}{{/ isLink }}
- <br />
+ {{^ isLink }}<span class="selectedFile">{{ name }}</span>{{/ isLink }}
+ {{ modificationCount }}
+ <br/>
{{/ links }}
</div>
- {{# units }}'''
- '<h2>{{{ path }}}</h2>'
+ {{# units }}
+ <p><b>
+ Hover over modified regions to see why the modification is suggested.
+ </b></p>'''
'<div class="content">'
'<div class="code">'
'{{! Write the file content, modified to include navigation information, }}'
@@ -206,6 +230,9 @@
'{{! the content, to provide tooltips for modified regions. }}'
'{{{ regionContent }}}'
'</div></div>'
+ '<div>'
+ '<i>Generated on {{ generationDate }}</i>'
+ '</div>'
r'''
{{/ units }}
<script lang="javascript">
@@ -221,6 +248,9 @@
/// Instrumentation display output for a library that was migrated to use
/// non-nullable types.
class InstrumentationRenderer {
+ /// A flag indicating whether the incremental workflow is currently supported.
+ static const bool supportsIncrementalWorkflow = false;
+
/// Display information for a compilation unit.
final UnitInfo unitInfo;
@@ -241,11 +271,13 @@
/// Builds an HTML view of the instrumentation information in [unitInfo].
String render() {
Map<String, dynamic> mustacheContext = {
+ 'root': migrationInfo.includedRoot,
'units': <Map<String, dynamic>>[],
'links': migrationInfo.unitLinks(unitInfo),
'highlightJsPath': migrationInfo.highlightJsPath(unitInfo),
'highlightStylePath': migrationInfo.highlightStylePath(unitInfo),
'navContent': _computeNavigationContent(unitInfo),
+ 'generationDate': migrationInfo.migrationDate,
};
mustacheContext['units'].add({
'path': unitInfo.path,
@@ -269,12 +301,12 @@
if (regionLength > 0) {
int openOffset = mapper.map(region.offset);
String openInsertion = openInsertions[openOffset] ?? '';
- openInsertion = '<a id="o${region.offset}">$openInsertion';
+ openInsertion = '<span id="o${region.offset}">$openInsertion';
openInsertions[openOffset] = openInsertion;
int closeOffset = openOffset + regionLength;
String closeInsertion = closeInsertions[closeOffset] ?? '';
- closeInsertion = '$closeInsertion</a>';
+ closeInsertion = '$closeInsertion</span>';
closeInsertions[closeOffset] = closeInsertion;
}
}
@@ -367,24 +399,46 @@
'${content.substring(offset, offset + length)}'
'<span class="tooltip">'
'<p>${region.explanation}</p>');
+ //
+ // Write out any details.
+ //
if (region.details.isNotEmpty) {
regions.write('<ul>');
- }
- for (var detail in region.details) {
- regions.write('<li>');
-
- if (detail.target != null) {
- regions.write('<a href="${_uriForTarget(detail.target, unitDir)}">');
+ for (var detail in region.details) {
+ regions.write('<li>');
+ if (detail.target != null) {
+ String targetUri = _uriForTarget(detail.target, unitDir);
+ regions.write('<a href="$targetUri">');
+ }
+ writeSplitLines(detail.description);
+ if (detail.target != null) {
+ regions.write('</a>');
+ }
+ regions.write('</li>');
}
- writeSplitLines(detail.description);
- if (detail.target != null) {
- regions.write('</a>');
- }
- regions.write('</li>');
- }
- if (region.details.isNotEmpty) {
regions.write('</ul>');
}
+ //
+ // Write out any edits.
+ //
+ if (supportsIncrementalWorkflow && region.edits.isNotEmpty) {
+ for (EditDetail edit in region.edits) {
+ int offset = edit.offset;
+ String targetUri = Uri(
+ scheme: 'http',
+ path: pathContext.basename(unitInfo.path),
+ queryParameters: {
+ 'offset': offset.toString(),
+ 'end': (offset + edit.length).toString(),
+ 'replacement': edit.replacement
+ }).toString();
+ regions.write('<p>');
+ regions.write('<a href="$targetUri">');
+ regions.write(edit.description);
+ regions.write('</a>');
+ regions.write('</p>');
+ }
+ }
regions.write('</span></span>');
}
if (previousOffset < content.length) {
@@ -433,7 +487,10 @@
/// The filesystem root used to create relative paths for each unit.
final String includedRoot;
- MigrationInfo(this.units, this.unitMap, this.pathContext, this.includedRoot);
+ final String migrationDate;
+
+ MigrationInfo(this.units, this.unitMap, this.pathContext, this.includedRoot)
+ : migrationDate = DateTime.now().toString();
/// The path to the highlight.js script, relative to [unitInfo].
String highlightJsPath(UnitInfo unitInfo) {
@@ -460,16 +517,22 @@
}
/// Generate mustache context for unit links, for navigation in the
- /// instrumentation document for [thisUnit].
- List<Map<String, Object>> unitLinks(UnitInfo thisUnit) {
- return [
- for (var unit in units)
- {
- 'name': _computeName(unit),
- 'isLink': unit != thisUnit,
- if (unit != thisUnit) 'href': _pathTo(target: unit, source: thisUnit)
- }
- ];
+ /// instrumentation document for [currentUnit].
+ List<Map<String, Object>> unitLinks(UnitInfo currentUnit) {
+ List<Map<String, Object>> links = [];
+ for (UnitInfo unit in units) {
+ int count = unit.fixRegions.length;
+ String modificationCount =
+ count == 1 ? '(1 modification)' : '($count modifications)';
+ bool isNotCurrent = unit != currentUnit;
+ links.add({
+ 'name': _computeName(unit),
+ 'modificationCount': modificationCount,
+ 'isLink': isNotCurrent,
+ if (isNotCurrent) 'href': _pathTo(target: unit, source: currentUnit)
+ });
+ }
+ return links;
}
/// Return the path to [unit] from [includedRoot], to be used as a display
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
index 3738015..d608c07 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
@@ -5,6 +5,25 @@
import 'package:analysis_server/src/edit/nnbd_migration/offset_mapper.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
+/// A description of an edit that can be applied before rerunning the migration
+/// in order to improve the migration results.
+class EditDetail {
+ /// A description of the edit that will be performed.
+ final String description;
+
+ /// The offset of the range to be replaced.
+ final int offset;
+
+ /// The length of the range to be replaced.
+ final int length;
+
+ /// The string with which the range will be replaced.
+ final String replacement;
+
+ /// Initialize a newly created detail.
+ EditDetail(this.description, this.offset, this.length, this.replacement);
+}
+
/// The migration information associated with a single library.
class LibraryInfo {
/// The information about the units in the library. The information about the
@@ -76,6 +95,9 @@
/// A description of an explanation associated with a region of code that was
/// modified.
class RegionInfo {
+ /// Type type of region.
+ final RegionType regionType;
+
/// The offset to the beginning of the region.
final int offset;
@@ -88,16 +110,20 @@
/// Details that further explain why a change was made.
final List<RegionDetail> details;
- /// Type type of region.
- final RegionType regionType;
+ /// A list of the edits that are related to this range.
+ List<EditDetail> edits;
/// Initialize a newly created region.
- RegionInfo(this.offset, this.length, this.explanation, this.details,
- this.regionType);
+ RegionInfo(
+ this.regionType, this.offset, this.length, this.explanation, this.details,
+ {this.edits = const []});
}
/// Different types of regions that are called out.
enum RegionType {
+ // TODO(brianwilkerson) 'fix' indicates whether the code was modified, while
+ // 'nonNullableType' indicates why the code wasn't modified. It would be good
+ // to be consistent between the "whether" and "why" descriptions.
/// This is a region of code that was fixed (changed) in migration.
fix,
diff --git a/pkg/analysis_server/lib/src/edit/preview/dart_file_page.dart b/pkg/analysis_server/lib/src/edit/preview/dart_file_page.dart
index 84df2c7..bf099ba 100644
--- a/pkg/analysis_server/lib/src/edit/preview/dart_file_page.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/dart_file_page.dart
@@ -51,6 +51,9 @@
String get includedRoot => wrappedInfo.includedRoot;
@override
+ String get migrationDate => wrappedInfo.migrationDate;
+
+ @override
Context get pathContext => wrappedInfo.pathContext;
@override
@@ -70,15 +73,21 @@
}
@override
- List<Map<String, Object>> unitLinks(UnitInfo thisUnit) {
- return [
- for (var unit in units)
- {
- 'name': _computeName(unit),
- 'isLink': unit != thisUnit,
- if (unit != thisUnit) 'href': _pathTo(target: unit, source: thisUnit)
- }
- ];
+ List<Map<String, Object>> unitLinks(UnitInfo currentUnit) {
+ List<Map<String, Object>> links = [];
+ for (UnitInfo unit in units) {
+ int count = unit.fixRegions.length;
+ String modificationCount =
+ count == 1 ? '(1 modification)' : '($count modifications)';
+ bool isNotCurrent = unit != currentUnit;
+ links.add({
+ 'name': _computeName(unit),
+ 'modificationCount': modificationCount,
+ 'isLink': isNotCurrent,
+ if (isNotCurrent) 'href': _pathTo(target: unit, source: currentUnit)
+ });
+ }
+ return links;
}
/// Return the path to [unit] from [includedRoot], to be used as a display
diff --git a/pkg/analysis_server/lib/src/edit/preview/index_file_page.dart b/pkg/analysis_server/lib/src/edit/preview/index_file_page.dart
new file mode 100644
index 0000000..d3e8fa6
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/preview/index_file_page.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, 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.
+
+import 'package:analysis_server/src/edit/nnbd_migration/index_renderer.dart';
+import 'package:analysis_server/src/edit/preview/preview_page.dart';
+import 'package:analysis_server/src/edit/preview/preview_site.dart';
+
+/// The page that is displayed when the root of the included path is requested.
+class IndexFilePage extends PreviewPage {
+ /// Initialize a newly created index file page within the given [site].
+ IndexFilePage(PreviewSite site)
+ : super(site, site.migrationInfo.includedRoot);
+
+ @override
+ void generateBody(Map<String, String> params) {
+ throw UnsupportedError('generateBody');
+ }
+
+ @override
+ Future<void> generatePage(Map<String, String> params) async {
+ IndexRenderer renderer = IndexRenderer(site.migrationInfo);
+ buf.write(renderer.render());
+ }
+}
diff --git a/pkg/analysis_server/lib/src/edit/preview/preview_site.dart b/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
index 2f3f778..dfee4ac 100644
--- a/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
@@ -13,6 +13,7 @@
import 'package:analysis_server/src/edit/preview/highlight_css_page.dart';
import 'package:analysis_server/src/edit/preview/highlight_js_page.dart';
import 'package:analysis_server/src/edit/preview/http_preview_server.dart';
+import 'package:analysis_server/src/edit/preview/index_file_page.dart';
import 'package:analysis_server/src/edit/preview/not_found_page.dart';
import 'package:analysis_server/src/status/pages.dart';
import 'package:analyzer/file_system/file_system.dart';
@@ -83,12 +84,19 @@
@override
Future<void> handleGetRequest(HttpRequest request) async {
- String path = request.uri.path;
+ Uri uri = request.uri;
+ if (uri.query.isNotEmpty) {
+ performEdit(uri);
+ performMigration();
+ }
+ String path = uri.path;
try {
if (path == highlightCssPagePath) {
return respond(request, HighlightCssPage(this));
} else if (path == highlightJSPagePath) {
return respond(request, HighlightJSPage(this));
+ } else if (path == migrationInfo.includedRoot) {
+ return respond(request, IndexFilePage(this));
}
UnitInfo unitInfo = unitInfoMap[path];
if (unitInfo != null) {
@@ -111,6 +119,28 @@
}
}
+ /// Perform the edit indicated by the [uri].
+ void performEdit(Uri uri) {
+ // We might want to allow edits to files other than the file to be displayed
+ // after the edit is performed, in which case we'll need to encode the file
+ // path as a query parameter.
+ Map<String, String> params = uri.queryParameters;
+ String path = uri.path;
+ int offset = int.parse(params['offset']);
+ int end = int.parse(params['end']);
+ String replacement = params['replacement'];
+ File file = pathMapper.provider.getFile(path);
+ String oldContent = file.readAsStringSync();
+ String newContent = oldContent.replaceRange(offset, end, replacement);
+ file.writeAsStringSync(newContent);
+ }
+
+ /// Perform the migration again and update this site to serve up the results
+ /// of the new migration.
+ void performMigration() {
+ // TODO(brianwilkerson) Implement this.
+ }
+
@override
Future<void> respond(HttpRequest request, Page page,
[int code = HttpStatus.ok]) async {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index f7af4f1..f2e16e3 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -136,15 +136,18 @@
new CompletionRequestImpl(unit, offset, performance);
Set<ElementKind> includedElementKinds;
+ Set<String> includedElementNames;
List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;
if (includeSuggestionSets) {
includedElementKinds = Set<ElementKind>();
+ includedElementNames = Set<String>();
includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
}
try {
CompletionContributor contributor = new DartCompletionManager(
includedElementKinds: includedElementKinds,
+ includedElementNames: includedElementNames,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
);
final suggestions =
@@ -167,7 +170,6 @@
// Now compute items in suggestion sets.
List<IncludedSuggestionSet> includedSuggestionSets = [];
- Set<String> includedElementNames = Set<String>();
if (includedElementKinds != null && unit != null) {
computeIncludedSetList(
server.declarationsTracker,
diff --git a/pkg/analysis_server/lib/src/server/crash_reporting.dart b/pkg/analysis_server/lib/src/server/crash_reporting.dart
index 498a45b..44e4c66 100644
--- a/pkg/analysis_server/lib/src/server/crash_reporting.dart
+++ b/pkg/analysis_server/lib/src/server/crash_reporting.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 'package:analyzer/exception/exception.dart';
import 'package:analyzer/instrumentation/noop_service.dart';
import 'package:analyzer/instrumentation/plugin_data.dart';
import 'package:telemetry/crash_reporting.dart';
@@ -13,6 +14,14 @@
@override
void logException(dynamic exception, [StackTrace stackTrace]) {
+ if (exception is CaughtException) {
+ // Get the root CaughtException, which matters most for debugging.
+ exception = exception.rootCaughtException;
+ // Report the root exception stack trace.
+ stackTrace = exception.stackTrace;
+ // Report the dynamic exception object that the CaughtException holds.
+ exception = exception.exception;
+ }
reporter
.sendReport(exception, stackTrace: stackTrace ?? StackTrace.current)
.catchError((error) {
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 4714d6e..85cddcd 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -653,13 +653,15 @@
// server was configured to load a language model on disk.
CompletionRanking.instance =
CompletionRanking(analysisServerOptions.completionModelFolder);
- CompletionRanking.instance.start().catchError((error, stackTrace) {
+ CompletionRanking.instance.start().catchError((exception, stackTrace) {
// Disable smart ranking if model startup fails.
analysisServerOptions.completionModelFolder = null;
+ // TODO(brianwilkerson) Shutdown the isolates that have already been
+ // started.
CompletionRanking.instance = null;
AnalysisEngine.instance.instrumentationService.logException(
CaughtException.withMessage(
- 'Failed to start ranking model isolate', error, stackTrace));
+ 'Failed to start ranking model isolate', exception, stackTrace));
});
}
diff --git a/pkg/analysis_server/lib/src/server/error_notifier.dart b/pkg/analysis_server/lib/src/server/error_notifier.dart
index 57bd646..0547cd4 100644
--- a/pkg/analysis_server/lib/src/server/error_notifier.dart
+++ b/pkg/analysis_server/lib/src/server/error_notifier.dart
@@ -16,7 +16,12 @@
var message = 'Internal error';
if (exception is CaughtException && exception.message != null) {
- message = exception.message;
+ // TODO(mfairhurst): Use the outermost exception once crash reporting is
+ // fixed and this becomes purely user-facing.
+ exception = exception.rootCaughtException;
+ // TODO(mfairhurst): Use the outermost message rather than the innermost
+ // exception as its own message.
+ message = exception.exception;
}
server.sendServerErrorNotification(message, exception, stackTrace,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 626caf1..11b9e48 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -39,6 +39,7 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -84,8 +85,6 @@
@override
Future<List<CompletionSuggestion>> computeSuggestions(
CompletionRequest request) async {
- // TODO(brianwilkerson) Determine whether this await is necessary.
- await null;
request.checkAborted();
if (!AnalysisEngine.isDartFileName(request.result.path)) {
return const <CompletionSuggestion>[];
@@ -185,16 +184,30 @@
List<CompletionSuggestion> suggestions = suggestionMap.values.toList();
const SORT_TAG = 'DartCompletionManager - sort';
performance.logStartTime(SORT_TAG);
- await contributionSorter.sort(dartRequest, suggestions);
if (ranking != null) {
request.checkAborted();
- suggestions = await ranking.rerank(
- probabilityFuture,
- suggestions,
- includedElementNames,
- includedSuggestionRelevanceTags,
- dartRequest,
- request.result.unit.featureSet);
+ try {
+ suggestions = await ranking.rerank(
+ probabilityFuture,
+ suggestions,
+ includedElementNames,
+ includedSuggestionRelevanceTags,
+ dartRequest,
+ request.result.unit.featureSet);
+ } catch (exception, stackTrace) {
+ // TODO(brianwilkerson) Shutdown the isolates that have already been
+ // started.
+ // Disable smart ranking if prediction fails.
+ CompletionRanking.instance = null;
+ AnalysisEngine.instance.instrumentationService.logException(
+ CaughtException.withMessage(
+ 'Failed to rerank completion suggestions',
+ exception,
+ stackTrace));
+ await contributionSorter.sort(dartRequest, suggestions);
+ }
+ } else {
+ await contributionSorter.sort(dartRequest, suggestions);
}
performance.logElapseTime(SORT_TAG);
request.checkAborted();
@@ -450,8 +463,6 @@
* if the completion request has been aborted.
*/
static Future<DartCompletionRequest> from(CompletionRequest request) async {
- // TODO(brianwilkerson) Determine whether this await is necessary.
- await null;
request.checkAborted();
CompletionPerformance performance =
(request as CompletionRequestImpl).performance;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index f2815f2..4b21997 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -9,10 +9,12 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/src/generated/resolver.dart'
+ show GenericInferrer, LibraryScope, TypeProvider;
+import 'package:analyzer/src/generated/type_system.dart' show GenericInferrer;
import '../../../protocol_server.dart' show CompletionSuggestion;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
index 2b1de7a..cc3878a 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
@@ -25,17 +25,14 @@
return const <CompletionSuggestion>[];
}
- // If this is a constructor declaration
- // then compute fields already referenced
- ConstructorDeclaration constructorDecl =
- node.thisOrAncestorOfType<ConstructorDeclaration>();
- if (constructorDecl == null) {
+ ConstructorDeclaration constructor = node.thisOrAncestorOfType();
+ if (constructor == null) {
return const <CompletionSuggestion>[];
}
// Compute the list of fields already referenced in the constructor
List<String> referencedFields = new List<String>();
- for (FormalParameter param in constructorDecl.parameters.parameters) {
+ for (FormalParameter param in constructor.parameters.parameters) {
if (param is DefaultFormalParameter &&
param.parameter is FieldFormalParameter) {
param = (param as DefaultFormalParameter).parameter;
@@ -51,11 +48,14 @@
}
}
+ ClassDeclaration class_ = constructor.thisOrAncestorOfType();
+ if (class_ == null) {
+ return const <CompletionSuggestion>[];
+ }
+
// Add suggestions for fields that are not already referenced
- ClassDeclaration classDecl =
- constructorDecl.thisOrAncestorOfType<ClassDeclaration>();
List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
- for (ClassMember member in classDecl.members) {
+ for (ClassMember member in class_.members) {
if (member is FieldDeclaration && !member.isStatic) {
for (VariableDeclaration varDecl in member.fields.variables) {
SimpleIdentifier fieldId = varDecl.name;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
index ae865b9..01c9e0e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
@@ -39,7 +39,7 @@
return const <CompletionSuggestion>[];
}
- var inheritance = new InheritanceManager3(request.result.typeSystem);
+ var inheritance = new InheritanceManager3();
// Generate a collection of inherited members
var classElem = classDecl.declaredElement;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index 9b4e58a..7f0ace0 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -184,7 +184,7 @@
@override
void declaredGenericTypeAlias(GenericTypeAlias declaration) {
if (declaration.name.name == targetName) {
- TypeAnnotation typeName = declaration.functionType.returnType;
+ TypeAnnotation typeName = declaration.functionType?.returnType;
if (typeName != null) {
typeFound = typeName.type;
}
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
index c93417d..3657667 100644
--- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -11,9 +11,10 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 1f5f28c..b2f83d2 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -26,6 +26,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
@@ -39,7 +40,7 @@
import 'package:analyzer/src/generated/error_verifier.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/hint/sdk_constraint_extractor.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
@@ -2796,6 +2797,10 @@
if (alreadyImportedWithPrefix.contains(declaration.path)) {
continue;
}
+ // Check that the import doesn't end with '.template.dart'
+ if (declaration.uri.path.endsWith('.template.dart')) {
+ continue;
+ }
// Compute the fix kind.
FixKind fixKind;
if (declaration.uri.isScheme('dart')) {
diff --git a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
index 85a0e5e..35bcdd0 100644
--- a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
@@ -13,6 +13,7 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:dart_style/dart_style.dart';
/// The result of [WidgetDescriptions.setPropertyValue] invocation.
class SetPropertyValueResult {
@@ -77,8 +78,15 @@
var change = await property.removeValue();
return SetPropertyValueResult._(change: change);
} else {
- var change = await property.changeValue(value);
- return SetPropertyValueResult._(change: change);
+ try {
+ var change = await property.changeValue(value);
+ return SetPropertyValueResult._(change: change);
+ } on FormatterException {
+ return SetPropertyValueResult._(
+ errorCode: protocol.RequestErrorCode
+ .FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION,
+ );
+ }
}
}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index 74d6eb3..dc4ebf4 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -24,13 +24,13 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/resolver.dart' show ExitDetector;
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/resolver.dart'
+ show ExitDetector, TypeProvider;
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
const String _TOKEN_SEPARATOR = '\uFFFF';
@@ -1375,7 +1375,7 @@
if (returnType is InterfaceType && type is InterfaceType) {
returnType = InterfaceType.getSmartLeastUpperBound(returnType, type);
} else {
- returnType = typeSystem.getLeastUpperBound(returnType, type);
+ returnType = typeSystem.leastUpperBound(returnType, type);
}
}
}
diff --git a/pkg/analysis_server/lib/src/utilities/mocks.dart b/pkg/analysis_server/lib/src/utilities/mocks.dart
new file mode 100644
index 0000000..ccc91a6
--- /dev/null
+++ b/pkg/analysis_server/lib/src/utilities/mocks.dart
@@ -0,0 +1,248 @@
+// Copyright (c) 2017, 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.
+
+import 'dart:async';
+
+import 'package:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/channel/channel.dart';
+import 'package:analysis_server/src/plugin/notification_manager.dart';
+import 'package:analysis_server/src/plugin/plugin_manager.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/src/context/context_root.dart' as analyzer;
+import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
+import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
+import 'package:test/test.dart';
+import 'package:watcher/watcher.dart';
+
+/// A mock [ServerCommunicationChannel] for testing [AnalysisServer].
+class MockServerChannel implements ServerCommunicationChannel {
+ StreamController<Request> requestController = new StreamController<Request>();
+ StreamController<Response> responseController =
+ new StreamController<Response>.broadcast();
+ StreamController<Notification> notificationController =
+ new StreamController<Notification>(sync: true);
+ Completer<Response> errorCompleter;
+
+ List<Response> responsesReceived = [];
+ List<Notification> notificationsReceived = [];
+
+ bool _closed = false;
+
+ String name;
+
+ MockServerChannel();
+
+ @override
+ void close() {
+ _closed = true;
+ }
+
+ void expectMsgCount({responseCount = 0, notificationCount = 0}) {
+ expect(responsesReceived, hasLength(responseCount));
+ expect(notificationsReceived, hasLength(notificationCount));
+ }
+
+ @override
+ void listen(void onRequest(Request request),
+ {Function onError, void onDone()}) {
+ requestController.stream
+ .listen(onRequest, onError: onError, onDone: onDone);
+ }
+
+ @override
+ void sendNotification(Notification notification) {
+ // Don't deliver notifications after the connection is closed.
+ if (_closed) {
+ return;
+ }
+ notificationsReceived.add(notification);
+ if (errorCompleter != null && notification.event == 'server.error') {
+ print(
+ '[server.error] test: $name message: ${notification.params['message']}');
+ errorCompleter.completeError(
+ new ServerError(notification.params['message']),
+ new StackTrace.fromString(notification.params['stackTrace']));
+ }
+ // Wrap send notification in future to simulate websocket
+ // TODO(scheglov) ask Dan why and decide what to do
+// new Future(() => notificationController.add(notification));
+ notificationController.add(notification);
+ }
+
+ /// Send the given [request] to the server and return a future that will
+ /// complete when a response associated with the [request] has been received.
+ /// The value of the future will be the received response. If [throwOnError] is
+ /// `true` (the default) then the returned future will throw an exception if a
+ /// server error is reported before the response has been received.
+ Future<Response> sendRequest(Request request, {bool throwOnError = true}) {
+ // TODO(brianwilkerson) Attempt to remove the `throwOnError` parameter and
+ // have the default behavior be the only behavior.
+ // No further requests should be sent after the connection is closed.
+ if (_closed) {
+ throw new Exception('sendRequest after connection closed');
+ }
+ // Wrap send request in future to simulate WebSocket.
+ new Future(() => requestController.add(request));
+ return waitForResponse(request, throwOnError: throwOnError);
+ }
+
+ @override
+ void sendResponse(Response response) {
+ // Don't deliver responses after the connection is closed.
+ if (_closed) {
+ return;
+ }
+ responsesReceived.add(response);
+ // Wrap send response in future to simulate WebSocket.
+ new Future(() => responseController.add(response));
+ }
+
+ /// Return a future that will complete when a response associated with the
+ /// given [request] has been received. The value of the future will be the
+ /// received response. If [throwOnError] is `true` (the default) then the
+ /// returned future will throw an exception if a server error is reported
+ /// before the response has been received.
+ ///
+ /// Unlike [sendRequest], this method assumes that the [request] has already
+ /// been sent to the server.
+ Future<Response> waitForResponse(Request request,
+ {bool throwOnError = true}) {
+ // TODO(brianwilkerson) Attempt to remove the `throwOnError` parameter and
+ // have the default behavior be the only behavior.
+ String id = request.id;
+ Future<Response> response =
+ responseController.stream.firstWhere((response) => response.id == id);
+ if (throwOnError) {
+ errorCompleter = new Completer<Response>();
+ try {
+ return Future.any([response, errorCompleter.future]);
+ } finally {
+ errorCompleter = null;
+ }
+ }
+ return response;
+ }
+}
+
+class ServerError implements Exception {
+ final message;
+
+ ServerError(this.message);
+
+ String toString() {
+ return "Server Error: $message";
+ }
+}
+
+/// A plugin manager that simulates broadcasting requests to plugins by
+/// hard-coding the responses.
+class TestPluginManager implements PluginManager {
+ plugin.AnalysisSetPriorityFilesParams analysisSetPriorityFilesParams;
+ plugin.AnalysisSetSubscriptionsParams analysisSetSubscriptionsParams;
+ plugin.AnalysisUpdateContentParams analysisUpdateContentParams;
+ plugin.RequestParams broadcastedRequest;
+ Map<PluginInfo, Future<plugin.Response>> broadcastResults;
+
+ @override
+ String get byteStorePath {
+ fail('Unexpected invocation of byteStorePath');
+ }
+
+ @override
+ InstrumentationService get instrumentationService {
+ fail('Unexpected invocation of instrumentationService');
+ }
+
+ @override
+ NotificationManager get notificationManager {
+ fail('Unexpected invocation of notificationManager');
+ }
+
+ @override
+ List<PluginInfo> get plugins {
+ fail('Unexpected invocation of plugins');
+ }
+
+ @override
+ ResourceProvider get resourceProvider {
+ fail('Unexpected invocation of resourceProvider');
+ }
+
+ @override
+ String get sdkPath {
+ fail('Unexpected invocation of sdkPath');
+ }
+
+ @override
+ Future<void> addPluginToContextRoot(
+ analyzer.ContextRoot contextRoot, String path) async {
+ fail('Unexpected invocation of addPluginToContextRoot');
+ }
+
+ @override
+ Map<PluginInfo, Future<plugin.Response>> broadcastRequest(
+ plugin.RequestParams params,
+ {analyzer.ContextRoot contextRoot}) {
+ broadcastedRequest = params;
+ return broadcastResults ?? <PluginInfo, Future<plugin.Response>>{};
+ }
+
+ @override
+ Future<List<Future<plugin.Response>>> broadcastWatchEvent(
+ WatchEvent watchEvent) async {
+ return <Future<plugin.Response>>[];
+ }
+
+ @override
+ List<String> pathsFor(String pluginPath) {
+ fail('Unexpected invocation of pathsFor');
+ }
+
+ @override
+ List<PluginInfo> pluginsForContextRoot(analyzer.ContextRoot contextRoot) {
+ fail('Unexpected invocation of pluginsForContextRoot');
+ }
+
+ @override
+ void recordPluginFailure(String hostPackageName, String message) {
+ fail('Unexpected invocation of recordPluginFailure');
+ }
+
+ @override
+ void removedContextRoot(analyzer.ContextRoot contextRoot) {
+ fail('Unexpected invocation of removedContextRoot');
+ }
+
+ @override
+ Future<void> restartPlugins() async {
+ // Nothing to restart.
+ return null;
+ }
+
+ @override
+ void setAnalysisSetPriorityFilesParams(
+ plugin.AnalysisSetPriorityFilesParams params) {
+ analysisSetPriorityFilesParams = params;
+ }
+
+ @override
+ void setAnalysisSetSubscriptionsParams(
+ plugin.AnalysisSetSubscriptionsParams params) {
+ analysisSetSubscriptionsParams = params;
+ }
+
+ @override
+ void setAnalysisUpdateContentParams(
+ plugin.AnalysisUpdateContentParams params) {
+ analysisUpdateContentParams = params;
+ }
+
+ @override
+ Future<List<void>> stopAll() async {
+ fail('Unexpected invocation of stopAll');
+ }
+}
diff --git a/pkg/analysis_server/lib/src/utilities/request_statistics.dart b/pkg/analysis_server/lib/src/utilities/request_statistics.dart
index b9e3b4b..d76c1bb 100644
--- a/pkg/analysis_server/lib/src/utilities/request_statistics.dart
+++ b/pkg/analysis_server/lib/src/utilities/request_statistics.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
+import 'dart:io';
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
@@ -12,6 +13,8 @@
///
/// All [DateTime] are local, not UTC.
class RequestStatisticsHelper {
+ final String _sdkVersion = Platform.version.split(' ').first;
+
final Map<String, _RequestStatistics> _statisticsMap = {};
/// The [StringSink] to which performance logger should copy its output.
@@ -167,6 +170,7 @@
'time': DateTime.now().millisecondsSinceEpoch,
'kind': kind.toJson(),
'data': data,
+ 'sdkVersion': _sdkVersion,
},
),
);
diff --git a/pkg/analysis_server/lib/src/watch_manager.dart b/pkg/analysis_server/lib/src/watch_manager.dart
deleted file mode 100644
index f7bd8c9..0000000
--- a/pkg/analysis_server/lib/src/watch_manager.dart
+++ /dev/null
@@ -1,285 +0,0 @@
-// Copyright (c) 2015, 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.
-
-import 'dart:async';
-import 'dart:collection';
-import 'dart:core';
-
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:watcher/watcher.dart';
-
-/**
- * A function called when a watch [event] associated with a watched resource is
- * received. The list of [tokens] will contain all of the tokens associated with
- * folders containing (or the same as) the watched resource.
- */
-typedef void HandleWatchEvent<T>(WatchEvent event, List<T> tokens);
-
-/**
- * An object that manages a collections of folders that need to be watched in
- * order to ensure that we are watching the minimum number of folders.
- *
- * Each folder can be watched multiple times. In order to differentiate between
- * the watch requests, each watch request has a *token* associated with it. The
- * tokens that are used must correctly implement both [==] and [hashCode].
- */
-class WatchManager<T> {
- /**
- * The resource provider used to convert paths to resources.
- */
- final ResourceProvider provider;
-
- /**
- * The function that is invoked when a watch event is received.
- */
- final HandleWatchEvent<T> handleWatchEvent;
-
- /**
- * A node representing the (conceptual) root of all other folders.
- */
- final WatchNode<T> rootNode = new WatchNode<T>(null);
-
- /**
- * A table mapping the folders that are being watched to the nodes
- * representing those folders.
- */
- final Map<Folder, WatchNode<T>> _watchedFolders =
- new HashMap<Folder, WatchNode<T>>();
-
- /**
- * Initialize a newly created watch manager to use the resource [provider] to
- * convert file paths to resources and to call the [handleWatchEvent] function
- * to notify the owner of the manager when resources have been changed.
- */
- WatchManager(this.provider, this.handleWatchEvent);
-
- /**
- * Record the fact that we are now watching the given [folder], and associate
- * that folder with the given [token]. If the folder is already being watched
- * and is already associated with the token, then this request is effectively
- * ignored.
- */
- void addFolder(Folder folder, T token) {
- WatchNode<T> folderNode = _watchedFolders[folder];
- //
- // If the folder was already being watched, just record the new token.
- //
- if (folderNode != null) {
- folderNode.tokens.add(token);
- return;
- }
- //
- // Otherwise, add the folder to the tree.
- //
- folderNode = new WatchNode<T>(folder);
- _watchedFolders[folder] = folderNode;
- folderNode.tokens.add(token);
- WatchNode<T> parentNode = rootNode.insert(folderNode);
- //
- // If we are not watching a folder that contains the folder, then create a
- // subscription for it.
- //
- if (parentNode == rootNode) {
- folderNode.subscription = folder.changes.listen(_handleWatchEvent);
- //
- // Any nodes that became children of the newly added folder would have
- // been top-level folders and would have been watched. We need to cancel
- // their subscriptions.
- //
- for (WatchNode<T> childNode in folderNode.children) {
- assert(childNode.subscription != null);
- if (childNode.subscription != null) {
- childNode.subscription.cancel();
- childNode.subscription = null;
- }
- }
- }
- }
-
- /**
- * Record that we are no longer watching the given [folder] with the given
- * [token].
- *
- * Throws a [StateError] if the folder is not be watched or is not associated
- * with the given token.
- */
- void removeFolder(Folder folder, T token) {
- WatchNode<T> folderNode = _watchedFolders[folder];
- if (folderNode == null) {
- assert(false);
- return;
- }
- Set<T> tokens = folderNode.tokens;
- if (!tokens.remove(token)) {
- assert(false);
- }
- //
- // If this was the last token associated with this folder, then remove the
- // folder from the tree.
- //
- if (tokens.isEmpty) {
- //
- // If the folder was a top-level folder, then we need to create
- // subscriptions for all of its children and cancel its subscription.
- //
- if (folderNode.subscription != null) {
- for (WatchNode<T> childNode in folderNode.children) {
- assert(childNode.subscription == null);
- childNode.subscription =
- childNode.folder.changes.listen(_handleWatchEvent);
- }
- folderNode.subscription.cancel();
- folderNode.subscription = null;
- }
- folderNode.delete();
- _watchedFolders.remove(folder);
- }
- }
-
- /**
- * Dispatch the given event by finding all of the tokens that contain the
- * resource and invoke the [handleWatchEvent] function.
- */
- void _handleWatchEvent(WatchEvent event) {
- String path = event.path;
- List<T> tokens = <T>[];
- WatchNode<T> parent = rootNode.findParent(path);
- while (parent != rootNode) {
- tokens.addAll(parent.tokens);
- parent = parent.parent;
- }
- if (tokens.isNotEmpty) {
- handleWatchEvent(event, tokens);
- }
- }
-}
-
-/**
- * The information kept by a [WatchManager] about a single folder that is being
- * watched.
- *
- * Watch nodes form a tree in which one node is a child of another node if the
- * child's folder is contained in the parent's folder and none of the folders
- * between the parent's folder and the child's folder are being watched.
- */
-class WatchNode<T> {
- /**
- * The folder for which information is being maintained. This is `null` for
- * the unique "root" node that maintains references to all of the top-level
- * folders being watched.
- */
- final Folder folder;
-
- /**
- * The parent of this node.
- */
- WatchNode<T> parent;
-
- /**
- * The information for the children of this node.
- */
- final List<WatchNode<T>> _children = <WatchNode<T>>[];
-
- /**
- * The tokens that were used to register interest in watching this folder.
- */
- final Set<T> tokens = new HashSet<T>();
-
- /**
- * The subscription being used to watch the folder, or `null` if the folder
- * is being watched as part of a containing folder (in other words, if the
- * parent is not the special "root").
- */
- StreamSubscription<WatchEvent> subscription;
-
- /**
- * Initialize a newly created node to represent the given [folder].
- */
- WatchNode(this.folder);
-
- /**
- * Return a list containing the children of this node.
- */
- Iterable<WatchNode<T>> get children => _children;
-
- /**
- * Remove this node from the tree of watched folders.
- */
- void delete() {
- if (parent != null) {
- parent._removeChild(this);
- parent = null;
- }
- }
-
- /**
- * Return the highest node reachable from this node that contains the given
- * [filePath]. If no other node is found, return this node, even if this node
- * does not contain the path.
- */
- WatchNode<T> findParent(String filePath) {
- if (_children == null) {
- return this;
- }
- for (WatchNode<T> childNode in _children) {
- if (childNode.folder.isOrContains(filePath)) {
- return childNode.findParent(filePath);
- }
- }
- return this;
- }
-
- /**
- * Insert the given [node] into the tree of watched folders, either as a child
- * of this node or as a descendent of one of this node's children. Return the
- * immediate parent of the newly added node.
- */
- WatchNode<T> insert(WatchNode<T> node) {
- WatchNode<T> parentNode = findParent(node.folder.path);
- parentNode._addChild(node, true);
- return parentNode;
- }
-
- @override
- String toString() => 'WatchNode ('
- 'folder = ${folder == null ? '<root>' : folder.path}, '
- 'tokens = $tokens, '
- 'subscription = ${subscription == null ? 'null' : 'non-null'})';
-
- /**
- * Add the given [newChild] as an immediate child of this node.
- *
- * If [checkChildren] is `true`, check to see whether any of the previously
- * existing children of this node should now be children of the new child, and
- * if so, move them.
- */
- void _addChild(WatchNode<T> newChild, bool checkChildren) {
- if (checkChildren) {
- Folder folder = newChild.folder;
- for (int i = _children.length - 1; i >= 0; i--) {
- WatchNode<T> existingChild = _children[i];
- if (folder.contains(existingChild.folder.path)) {
- newChild._addChild(existingChild, false);
- _children.removeAt(i);
- }
- }
- }
- newChild.parent = this;
- _children.add(newChild);
- }
-
- /**
- * Remove the given [node] from the list of children of this node. Any
- * children of the [node] will become children of this node.
- */
- void _removeChild(WatchNode<T> child) {
- _children.remove(child);
- Iterable<WatchNode<T>> grandchildren = child.children;
- for (WatchNode<T> grandchild in grandchildren) {
- grandchild.parent = this;
- _children.add(grandchild);
- }
- child._children.clear();
- }
-}
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index c6b6de9..1562690 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -10,21 +10,15 @@
hide AnalysisOptions;
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_analysis.dart';
-import 'package:analysis_server/src/plugin/notification_manager.dart';
-import 'package:analysis_server/src/plugin/plugin_manager.dart';
+import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
-import 'package:analyzer/src/context/context_root.dart' as analyzer;
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
-import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
-import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
import 'package:test/test.dart';
-import 'package:watcher/watcher.dart';
import 'mocks.dart';
@@ -249,114 +243,3 @@
return serverChannel.sendRequest(request, throwOnError: throwOnError);
}
}
-
-/**
- * A plugin manager that simulates broadcasting requests to plugins by
- * hard-coding the responses.
- */
-class TestPluginManager implements PluginManager {
- plugin.AnalysisSetPriorityFilesParams analysisSetPriorityFilesParams;
- plugin.AnalysisSetSubscriptionsParams analysisSetSubscriptionsParams;
- plugin.AnalysisUpdateContentParams analysisUpdateContentParams;
- plugin.RequestParams broadcastedRequest;
- Map<PluginInfo, Future<plugin.Response>> broadcastResults;
-
- @override
- String get byteStorePath {
- fail('Unexpected invocation of byteStorePath');
- }
-
- @override
- InstrumentationService get instrumentationService {
- fail('Unexpected invocation of instrumentationService');
- }
-
- @override
- NotificationManager get notificationManager {
- fail('Unexpected invocation of notificationManager');
- }
-
- @override
- List<PluginInfo> get plugins {
- fail('Unexpected invocation of plugins');
- }
-
- @override
- ResourceProvider get resourceProvider {
- fail('Unexpected invocation of resourceProvider');
- }
-
- @override
- String get sdkPath {
- fail('Unexpected invocation of sdkPath');
- }
-
- @override
- Future<void> addPluginToContextRoot(
- analyzer.ContextRoot contextRoot, String path) async {
- fail('Unexpected invocation of addPluginToContextRoot');
- }
-
- @override
- Map<PluginInfo, Future<plugin.Response>> broadcastRequest(
- plugin.RequestParams params,
- {analyzer.ContextRoot contextRoot}) {
- broadcastedRequest = params;
- return broadcastResults ?? <PluginInfo, Future<plugin.Response>>{};
- }
-
- @override
- Future<List<Future<plugin.Response>>> broadcastWatchEvent(
- WatchEvent watchEvent) async {
- return <Future<plugin.Response>>[];
- }
-
- @override
- List<String> pathsFor(String pluginPath) {
- fail('Unexpected invocation of pathsFor');
- }
-
- @override
- List<PluginInfo> pluginsForContextRoot(analyzer.ContextRoot contextRoot) {
- fail('Unexpected invocation of pluginsForContextRoot');
- }
-
- @override
- void recordPluginFailure(String hostPackageName, String message) {
- fail('Unexpected invocation of recordPluginFailure');
- }
-
- @override
- void removedContextRoot(analyzer.ContextRoot contextRoot) {
- fail('Unexpected invocation of removedContextRoot');
- }
-
- @override
- Future<void> restartPlugins() async {
- // Nothing to restart.
- return null;
- }
-
- @override
- void setAnalysisSetPriorityFilesParams(
- plugin.AnalysisSetPriorityFilesParams params) {
- analysisSetPriorityFilesParams = params;
- }
-
- @override
- void setAnalysisSetSubscriptionsParams(
- plugin.AnalysisSetSubscriptionsParams params) {
- analysisSetSubscriptionsParams = params;
- }
-
- @override
- void setAnalysisUpdateContentParams(
- plugin.AnalysisUpdateContentParams params) {
- analysisUpdateContentParams = params;
- }
-
- @override
- Future<List<void>> stopAll() async {
- fail('Unexpected invocation of stopAll');
- }
-}
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 8a9ea74..04e0f45 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -9,6 +9,7 @@
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_server.dart';
+import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/generated/sdk.dart';
@@ -18,8 +19,6 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'mocks.dart';
-
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisServerTest);
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index e8ac58f..1af2b10 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -13,12 +13,12 @@
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/source/error_processor.dart';
import 'package:analyzer/src/context/builder.dart';
+import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/context/context_root.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -1750,20 +1750,6 @@
manager.callbacks = callbacks;
}
- /**
- * Verify that package URI's for source files in [path] will be resolved
- * using a package root matching [expectation].
- */
- void _checkPackageRoot(String path, expectation) {
- // TODO(brianwilkerson) Figure out how to test this. Possibly by comparing
- // the contents of the package map (although that approach doesn't work at
- // the moment).
-// FolderDisposition disposition = callbacks.currentContextDispositions[path];
-// expect(disposition.packageRoot, expectation);
- // TODO(paulberry): we should also verify that the package map itself is
- // correct. See dartbug.com/23909.
- }
-
Map<String, List<Folder>> _packageMap(String contextPath) {
Folder folder = resourceProvider.getFolder(contextPath);
ContextInfo info = manager.getContextInfoFor(folder);
@@ -1981,9 +1967,9 @@
newFile('$projPath/test', content: 'test.dart');
newFile('$sdkExtPath/entry.dart');
var synchronousSession = SynchronousSession(analysisOptions, null);
- List<int> bytes = new SummaryBuilder(
- [], RestrictedAnalysisContext(synchronousSession, null))
- .build();
+ List<int> bytes =
+ new SummaryBuilder([], AnalysisContextImpl(synchronousSession, null))
+ .build();
newFileWithBytes('$projPath/sdk.ds', bytes);
// Setup _embedder.yaml.
newFile('$libPath/_embedder.yaml', content: r'''
diff --git a/pkg/analysis_server/test/domain_analysis_test.dart b/pkg/analysis_server/test/domain_analysis_test.dart
index ae88bc8..10f0d83 100644
--- a/pkg/analysis_server/test/domain_analysis_test.dart
+++ b/pkg/analysis_server/test/domain_analysis_test.dart
@@ -9,6 +9,7 @@
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_analysis.dart';
+import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
diff --git a/pkg/analysis_server/test/domain_execution_test.dart b/pkg/analysis_server/test/domain_execution_test.dart
index d3d2908..6a7e774 100644
--- a/pkg/analysis_server/test/domain_execution_test.dart
+++ b/pkg/analysis_server/test/domain_execution_test.dart
@@ -7,6 +7,7 @@
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_execution.dart';
import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/generated/sdk.dart';
diff --git a/pkg/analysis_server/test/domain_server_test.dart b/pkg/analysis_server/test/domain_server_test.dart
index 120b2de..554eba5 100644
--- a/pkg/analysis_server/test/domain_server_test.dart
+++ b/pkg/analysis_server/test/domain_server_test.dart
@@ -7,6 +7,7 @@
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_server.dart';
+import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/generated/sdk.dart';
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index efdb5d0..07c1026 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -147,6 +147,8 @@
bbb:${toUri('/bbb/lib')}
''');
newFile('/bbb/lib/target.dart', content: 'class Foo() {}');
+ newFile('/bbb/lib/target.generated.dart', content: 'class Foo() {}');
+ newFile('/bbb/lib/target.template.dart', content: 'class Foo() {}');
handleSuccessfulRequest(
new AnalysisSetAnalysisRootsParams(
@@ -167,6 +169,12 @@
.map((f) => f.message)
.toList();
expect(fixes, contains("Import library 'package:bbb/target.dart'"));
+ expect(
+ fixes, contains("Import library 'package:bbb/target.generated.dart'"));
+
+ // Context: http://dartbug.com/39401
+ expect(fixes.contains("Import library 'package:bbb/target.template.dart'"),
+ isFalse);
}
void _addOverlay(String name, String contents) {
diff --git a/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
index e4e9f2d..59c2b7d 100644
--- a/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
+++ b/pkg/analysis_server/test/edit/nnbd_migration/instrumentation_output_test.dart
@@ -23,8 +23,8 @@
// TODO(srawlins): Add tests for navigation links, which use multiple
// libraries.
List<String> renderLibrary(LibraryInfo libraryInfo) {
- String packageRoot = resourceProvider.convertPath('/package');
- String outputDir = resourceProvider.convertPath('/output');
+ String packageRoot = convertPath('/package');
+ String outputDir = convertPath('/output');
MigrationInfo migrationInfo = MigrationInfo(
libraryInfo.units, {}, resourceProvider.pathContext, packageRoot);
List<String> contents = [];
@@ -37,26 +37,26 @@
}
test_outputContainsEachPath() async {
+ String convert(String path) => path.replaceAll('/', '/');
+
LibraryInfo info = LibraryInfo({
unit('/package/lib/a.dart', 'int? a = null;',
- regions: [RegionInfo(3, 1, 'null was assigned', [], RegionType.fix)]),
+ regions: [RegionInfo(RegionType.fix, 3, 1, 'null was assigned', [])]),
unit('/package/lib/part1.dart', 'int? b = null;',
- regions: [RegionInfo(3, 1, 'null was assigned', [], RegionType.fix)]),
+ regions: [RegionInfo(RegionType.fix, 3, 1, 'null was assigned', [])]),
unit('/package/lib/part2.dart', 'int? c = null;',
- regions: [RegionInfo(3, 1, 'null was assigned', [], RegionType.fix)]),
+ regions: [RegionInfo(RegionType.fix, 3, 1, 'null was assigned', [])]),
});
List<String> contents = renderLibrary(info);
- expect(contents[0], contains(resourceProvider.convertPath('lib/a.dart')));
- expect(
- contents[1], contains(resourceProvider.convertPath('lib/part1.dart')));
- expect(
- contents[2], contains(resourceProvider.convertPath('lib/part2.dart')));
+ expect(contents[0], contains(convert('lib/a.dart')));
+ expect(contents[1], contains(convert('lib/part1.dart')));
+ expect(contents[2], contains(convert('lib/part2.dart')));
}
test_outputContainsEscapedHtml() async {
LibraryInfo info = LibraryInfo({
unit('/package/lib/a.dart', 'List<String>? a = null;', regions: [
- RegionInfo(12, 1, 'null was assigned', [], RegionType.fix)
+ RegionInfo(RegionType.fix, 12, 1, 'null was assigned', [])
]),
});
String output = renderLibrary(info)[0];
@@ -78,7 +78,7 @@
test_outputContainsModifiedAndUnmodifiedRegions() async {
LibraryInfo info = LibraryInfo({
unit('/package/lib/a.dart', 'int? a = null;',
- regions: [RegionInfo(3, 1, 'null was assigned', [], RegionType.fix)]),
+ regions: [RegionInfo(RegionType.fix, 3, 1, 'null was assigned', [])]),
});
String output = renderLibrary(info)[0];
expect(
@@ -89,7 +89,7 @@
}
UnitInfo unit(String path, String content, {List<RegionInfo> regions}) {
- return UnitInfo(resourceProvider.convertPath(path))
+ return UnitInfo(convertPath(path))
..content = content
..regions.addAll(regions);
}
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index 7213f72..c7ec891 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1105,6 +1105,7 @@
* If one configured path is beneath another, the descendent will override
* the ancestors' configured libraries of interest.
*/
+ @deprecated
Future sendCompletionRegisterLibraryPaths(List<LibraryPathSet> paths) async {
var params = new CompletionRegisterLibraryPathsParams(paths).toJson();
var result = await server.send("completion.registerLibraryPaths", params);
@@ -2674,6 +2675,9 @@
* argument is removed. If the property isRequired is true,
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED error is generated.
*
+ * If the expression is not a syntactically valid Dart code, then
+ * FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION is reported.
+ *
* Returns
*
* change: SourceChange
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 8b5bbf4..c24dbef 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1526,6 +1526,7 @@
* DEBUG_PORT_COULD_NOT_BE_OPENED
* FILE_NOT_ANALYZED
* FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET
+ * FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED
* FORMAT_INVALID_FILE
@@ -1561,6 +1562,7 @@
"DEBUG_PORT_COULD_NOT_BE_OPENED",
"FILE_NOT_ANALYZED",
"FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET",
+ "FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION",
"FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID",
"FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED",
"FORMAT_INVALID_FILE",
diff --git a/pkg/analysis_server/test/mock_packages/meta/lib/meta.dart b/pkg/analysis_server/test/mock_packages/meta/lib/meta.dart
index 9fd9fca..834640c 100644
--- a/pkg/analysis_server/test/mock_packages/meta/lib/meta.dart
+++ b/pkg/analysis_server/test/mock_packages/meta/lib/meta.dart
@@ -12,7 +12,7 @@
/// function's name differently.
///
/// For information on installing and importing this library, see the
-/// [meta package on pub.dartlang.org] (https://pub.dartlang.org/packages/meta).
+/// [meta package on pub.dev] (https://pub.dev/packages/meta).
/// For examples of using annotations, see
/// [Metadata](https://www.dartlang.org/docs/dart-up-and-running/ch02.html#metadata)
/// in the language tour.
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index 4756c84..c95121c 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -11,8 +11,6 @@
import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
-import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/timestamped_data.dart';
@@ -202,122 +200,6 @@
}
}
-/**
- * A mock [ServerCommunicationChannel] for testing [AnalysisServer].
- */
-class MockServerChannel implements ServerCommunicationChannel {
- StreamController<Request> requestController = new StreamController<Request>();
- StreamController<Response> responseController =
- new StreamController<Response>.broadcast();
- StreamController<Notification> notificationController =
- new StreamController<Notification>(sync: true);
- Completer<Response> errorCompleter;
-
- List<Response> responsesReceived = [];
- List<Notification> notificationsReceived = [];
-
- bool _closed = false;
-
- String name;
-
- MockServerChannel();
-
- @override
- void close() {
- _closed = true;
- }
-
- void expectMsgCount({responseCount = 0, notificationCount = 0}) {
- expect(responsesReceived, hasLength(responseCount));
- expect(notificationsReceived, hasLength(notificationCount));
- }
-
- @override
- void listen(void onRequest(Request request),
- {Function onError, void onDone()}) {
- requestController.stream
- .listen(onRequest, onError: onError, onDone: onDone);
- }
-
- @override
- void sendNotification(Notification notification) {
- // Don't deliver notifications after the connection is closed.
- if (_closed) {
- return;
- }
- notificationsReceived.add(notification);
- if (errorCompleter != null && notification.event == 'server.error') {
- print(
- '[server.error] test: $name message: ${notification.params['message']}');
- errorCompleter.completeError(
- new ServerError(notification.params['message']),
- new StackTrace.fromString(notification.params['stackTrace']));
- }
- // Wrap send notification in future to simulate websocket
- // TODO(scheglov) ask Dan why and decide what to do
-// new Future(() => notificationController.add(notification));
- notificationController.add(notification);
- }
-
- /**
- * Send the given [request] to the server and return a future that will
- * complete when a response associated with the [request] has been received.
- * The value of the future will be the received response. If [throwOnError] is
- * `true` (the default) then the returned future will throw an exception if a
- * server error is reported before the response has been received.
- */
- Future<Response> sendRequest(Request request, {bool throwOnError = true}) {
- // TODO(brianwilkerson) Attempt to remove the `throwOnError` parameter and
- // have the default behavior be the only behavior.
- // No further requests should be sent after the connection is closed.
- if (_closed) {
- throw new Exception('sendRequest after connection closed');
- }
- // Wrap send request in future to simulate WebSocket.
- new Future(() => requestController.add(request));
- return waitForResponse(request, throwOnError: throwOnError);
- }
-
- @override
- void sendResponse(Response response) {
- // Don't deliver responses after the connection is closed.
- if (_closed) {
- return;
- }
- responsesReceived.add(response);
- // Wrap send response in future to simulate WebSocket.
- new Future(() => responseController.add(response));
- }
-
- /**
- * Return a future that will complete when a response associated with the
- * given [request] has been received. The value of the future will be the
- * received response. If [throwOnError] is `true` (the default) then the
- * returned future will throw an exception if a server error is reported
- * before the response has been received.
- *
- * Unlike [sendRequest], this method assumes that the [request] has already
- * been sent to the server.
- */
- Future<Response> waitForResponse(Request request,
- {bool throwOnError = true}) {
- // TODO(brianwilkerson) Attempt to remove the `throwOnError` parameter and
- // have the default behavior be the only behavior.
- String id = request.id;
- Future<Response> response =
- responseController.stream.firstWhere((response) => response.id == id);
- if (throwOnError) {
- errorCompleter = new Completer<Response>();
- try {
- return Future.any([response, errorCompleter.future]);
- } finally {
- errorCompleter = null;
- }
- }
- return response;
- }
-}
-
class MockSource extends StringTypedMock implements Source {
@override
TimestampedData<String> contents = null;
@@ -355,16 +237,6 @@
bool exists() => null;
}
-class ServerError implements Exception {
- final message;
-
- ServerError(this.message);
-
- String toString() {
- return "Server Error: $message";
- }
-}
-
class StringTypedMock {
String _toString;
diff --git a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
index 2bdff61..5781bf8 100644
--- a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
@@ -22,6 +22,17 @@
return new FieldFormalContributor();
}
+ /// https://github.com/dart-lang/sdk/issues/39028
+ test_mixin_constructor() async {
+ addTestSource('''
+mixin M {
+ M(this.^);
+}
+''');
+ await computeSuggestions();
+ expect(suggestions, isEmpty);
+ }
+
test_ThisExpression_constructor_param() async {
// SimpleIdentifier FieldFormalParameter FormalParameterList
addTestSource('''
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index da8dc4c..93baaf3 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -2537,6 +2537,51 @@
assertNoSuggestions();
}
+ test_forEachPartsWithIdentifier_class() async {
+ addTestSource('''
+class C {}
+
+main() {
+ for(C in [0, 1, 2]) {
+ ^
+ }
+}
+''');
+ await computeSuggestions();
+ // Using `C` in for-each is invalid, but we should not crash.
+ }
+
+ test_forEachPartsWithIdentifier_localLevelVariable() async {
+ addTestSource('''
+main() {
+ int v;
+ for(v in [0, 1, 2]) {
+ ^
+ }
+}
+''');
+ await computeSuggestions();
+ // We don't actually use anything from the `for`, and `v` is suggested
+ // just because it is a visible top-level declaration.
+ assertSuggestLocalVariable('v', 'int');
+ }
+
+ test_forEachPartsWithIdentifier_topLevelVariable() async {
+ addTestSource('''
+int v;
+main() {
+ for(v in [0, 1, 2]) {
+ ^
+ }
+}
+''');
+ await computeSuggestions();
+ // We don't actually use anything from the `for`, and `v` is suggested
+ // just because it is a visible top-level declaration.
+ assertSuggestTopLevelVar('v', 'int',
+ relevance: DART_RELEVANCE_LOCAL_TOP_LEVEL_VARIABLE);
+ }
+
test_ForEachStatement() async {
// SimpleIdentifier ForEachStatement
addTestSource('main() {List<int> values; for (int index in ^)}');
@@ -2584,7 +2629,7 @@
test_ForEachStatement_body_untyped() async {
// Block ForEachStatement
- addTestSource('main(args) {for (foo in bar) {^}}');
+ addTestSource('main(args) {for (var foo in bar) {^}}');
await computeSuggestions();
expect(replacementOffset, completionOffset);
diff --git a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
index 79c7091..29d2508 100644
--- a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
@@ -2068,6 +2068,14 @@
expect(suggestion.element.parameters, '(int value)');
}
+ test_genericTypeAlias_noFunctionType() async {
+ addTestSource('''
+typedef F=;
+g(F.^
+''');
+ await computeSuggestions();
+ }
+
test_IfStatement() async {
// SimpleIdentifier IfStatement
addTestSource('''
diff --git a/pkg/analysis_server/test/socket_server_test.dart b/pkg/analysis_server/test/socket_server_test.dart
index 56119bb..b45a779 100644
--- a/pkg/analysis_server/test/socket_server_test.dart
+++ b/pkg/analysis_server/test/socket_server_test.dart
@@ -10,12 +10,11 @@
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/server/error_notifier.dart';
import 'package:analysis_server/src/socket_server.dart';
+import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:test/test.dart';
-import 'mocks.dart';
-
main() {
group('SocketServer', () {
test('createAnalysisServer_successful',
@@ -55,7 +54,7 @@
static Future createAnalysisServer_successful() {
MockServerChannel channel = new MockServerChannel();
- SocketServer server = _createSocketServer(channel);
+ _createSocketServer(channel);
channel.expectMsgCount(notificationCount: 1);
expect(
channel.notificationsReceived[0].event, SERVER_NOTIFICATION_CONNECTED);
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
index 593a8fd..7b42502 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/info_builder_test.dart
@@ -73,8 +73,8 @@
/// in [infos].
Future<void> buildInfo() async {
// Compute the analysis results.
- server.setAnalysisRoots(
- '0', [resourceProvider.pathContext.dirname(testFile)], [], {});
+ String includedRoot = resourceProvider.pathContext.dirname(testFile);
+ server.setAnalysisRoots('0', [includedRoot], [], {});
ResolvedUnitResult result = await server
.getAnalysisDriver(testFile)
.currentSession
@@ -91,8 +91,9 @@
migration.finish();
// Build the migration info.
InstrumentationInformation info = instrumentationListener.data;
- InfoBuilder builder =
- InfoBuilder(info, listener, explainNonNullableTypes: true);
+ InfoBuilder builder = InfoBuilder(
+ resourceProvider, includedRoot, info, listener,
+ explainNonNullableTypes: true);
infos = (await builder.explainMigration()).toList();
}
@@ -158,6 +159,104 @@
details: ["The value of the expression is nullable"]);
}
+ test_discardCondition() async {
+ UnitInfo unit = await buildInfoForSingleTestFile('''
+void g(int i) {
+ print(i.isEven);
+ if (i != null) print('NULL');
+}
+''', migratedContent: '''
+void g(int i) {
+ print(i.isEven);
+ /* if (i != null) */ print('NULL');
+}
+''');
+ List<RegionInfo> regions = unit.fixRegions;
+ expect(regions, hasLength(2));
+ assertRegion(region: regions[0], offset: 37, length: 3);
+ assertRegion(region: regions[1], offset: 55, length: 3);
+ }
+
+ test_discardElse() async {
+ UnitInfo unit = await buildInfoForSingleTestFile('''
+void g(int i) {
+ print(i.isEven);
+ if (i != null) print('NULL');
+ else print('NOT NULL');
+}
+''', migratedContent: '''
+void g(int i) {
+ print(i.isEven);
+ /* if (i != null) */ print('NULL'); /*
+ else print('NOT NULL'); */
+}
+''');
+ List<RegionInfo> regions = unit.fixRegions;
+ expect(regions, hasLength(4));
+ assertRegion(region: regions[0], offset: 37, length: 3);
+ assertRegion(region: regions[1], offset: 55, length: 3);
+ assertRegion(region: regions[2], offset: 72, length: 3);
+ assertRegion(region: regions[3], offset: 101, length: 3);
+ }
+
+ test_dynamicValueIsUsed() async {
+ UnitInfo unit = await buildInfoForSingleTestFile('''
+bool f(int i) {
+ if (i == null) return true;
+ else return false;
+}
+void g() {
+ dynamic i = null;
+ f(i);
+}
+''', migratedContent: '''
+bool f(int? i) {
+ if (i == null) return true;
+ else return false;
+}
+void g() {
+ dynamic i = null;
+ f(i);
+}
+''');
+ List<RegionInfo> regions = unit.regions;
+ expect(regions, hasLength(1));
+ assertRegion(region: regions[0], offset: 10, details: [
+ "A dynamic value, which is nullable is passed as an argument"
+ ]);
+ assertDetail(detail: regions[0].details[0], offset: 104, length: 1);
+ }
+
+ test_exactNullable() async {
+ UnitInfo unit = await buildInfoForSingleTestFile('''
+void f(List<int> list) {
+ list[0] = null;
+}
+
+void g() {
+ f(<int>[]);
+}
+''', migratedContent: '''
+void f(List<int?> list) {
+ list[0] = null;
+}
+
+void g() {
+ f(<int?>[]);
+}
+''');
+ List<RegionInfo> regions = unit.regions;
+ expect(regions, hasLength(3));
+ // regions[0] is the hard edge that f's parameter is non-nullable.
+ assertRegion(region: regions[1], offset: 15, details: [
+ "An explicit 'null' is assigned",
+ ]);
+ assertRegion(
+ region: regions[2],
+ offset: 66,
+ details: ["This is later required to accept null."]);
+ }
+
test_expressionFunctionReturnTarget() async {
UnitInfo unit = await buildInfoForSingleTestFile('''
String g() => 1 == 2 ? "Hello" : null;
@@ -247,81 +346,120 @@
details: ["This field is initialized to a nullable value"]);
}
- test_listAndSetLiteralTypeArgument() async {
- // TODO(srawlins): Simplify this test with `var x` once #38341 is fixed.
+ test_insertedRequired_fieldFormal() async {
UnitInfo unit = await buildInfoForSingleTestFile('''
-void f() {
- String s = null;
- List<String> x = <String>["hello", s];
- Set<String> y = <String>{"hello", s};
+class C {
+ int level;
+ int level2;
+ C({this.level}) : this.level2 = level + 1;
}
''', migratedContent: '''
-void f() {
- String? s = null;
- List<String?> x = <String?>["hello", s];
- Set<String?> y = <String?>{"hello", s};
+class C {
+ int level;
+ int level2;
+ C({required this.level}) : this.level2 = level + 1;
}
''');
List<RegionInfo> regions = unit.fixRegions;
- expect(regions, hasLength(5));
- // regions[0] is the `String? s` fix.
- // regions[1] is the `List<String?> x` fix.
- assertRegion(
- region: regions[2],
- offset: 58,
- details: ["This list is initialized with a nullable value on line 3"]);
- assertDetail(detail: regions[2].details[0], offset: 67, length: 1);
- // regions[3] is the `Set<String?> y` fix.
- assertRegion(
- region: regions[4],
- offset: 100,
- details: ["This set is initialized with a nullable value on line 4"]);
- assertDetail(detail: regions[4].details[0], offset: 107, length: 1);
+ expect(regions, hasLength(1));
+ assertRegion(region: regions[0], offset: 42, length: 9, details: [
+ "This parameter is non-nullable, so cannot have an implicit default "
+ "value of 'null'"
+ ]);
}
- test_listLiteralTypeArgument_collectionIf() async {
- // TODO(srawlins): Simplify this test with `var x` once #38341 is fixed.
+ test_insertedRequired_parameter() async {
+ UnitInfo unit = await buildInfoForSingleTestFile('''
+class C {
+ int level;
+ bool f({int lvl}) => lvl >= level;
+}
+''', migratedContent: '''
+class C {
+ int? level;
+ bool f({required int lvl}) => lvl >= level!;
+}
+''');
+ List<RegionInfo> regions = unit.fixRegions;
+ expect(regions, hasLength(3));
+ // regions[0] is the `int? s` fix.
+ assertRegion(region: regions[1], offset: 34, length: 9, details: [
+ "This parameter is non-nullable, so cannot have an implicit default "
+ "value of 'null'"
+ ]);
+ // regions[2] is the `level!` fix.
+ }
+
+ test_listAndSetLiteralTypeArgument() async {
UnitInfo unit = await buildInfoForSingleTestFile('''
void f() {
String s = null;
- List<String> x = <String>[
- "hello",
- if (1 == 2) s
- ];
+ var x = <String>["hello", s];
+ var y = <String>{"hello", s};
}
''', migratedContent: '''
void f() {
String? s = null;
- List<String?> x = <String?>[
- "hello",
- if (1 == 2) s
- ];
+ var x = <String?>["hello", s];
+ var y = <String?>{"hello", s};
}
''');
List<RegionInfo> regions = unit.fixRegions;
expect(regions, hasLength(3));
// regions[0] is the `String? s` fix.
- // regions[1] is the `List<String?> x` fix.
+ assertRegion(
+ region: regions[1],
+ offset: 48,
+ details: ["This list is initialized with a nullable value on line 3"]);
+ assertDetail(detail: regions[1].details[0], offset: 58, length: 1);
assertRegion(
region: regions[2],
- offset: 58,
+ offset: 81,
+ details: ["This set is initialized with a nullable value on line 4"]);
+ assertDetail(detail: regions[2].details[0], offset: 90, length: 1);
+ }
+
+ test_listLiteralTypeArgument_collectionIf() async {
+ UnitInfo unit = await buildInfoForSingleTestFile('''
+void f() {
+ String s = null;
+ var x = <String>[
+ "hello",
+ if (1 == 2) s
+ ];
+}
+''', migratedContent: '''
+void f() {
+ String? s = null;
+ var x = <String?>[
+ "hello",
+ if (1 == 2) s
+ ];
+}
+''');
+ List<RegionInfo> regions = unit.fixRegions;
+ expect(regions, hasLength(2));
+ // regions[0] is the `String? s` fix.
+ assertRegion(
+ region: regions[1],
+ offset: 48,
details: ["This list is initialized with a nullable value on line 5"]);
- assertDetail(detail: regions[2].details[0], offset: 88, length: 1);
+ assertDetail(detail: regions[1].details[0], offset: 79, length: 1);
}
test_localVariable() async {
UnitInfo unit = await buildInfoForSingleTestFile('''
void f() {
- int _v1 = null;
- int _v2 = _v1;
+ int v1 = null;
+ int v2 = v1;
}
''', migratedContent: '''
void f() {
- int? _v1 = null;
- int? _v2 = _v1;
+ int? v1 = null;
+ int? v2 = v1;
}
''');
- List<RegionInfo> regions = unit.regions;
+ List<RegionInfo> regions = unit.fixRegions;
expect(regions, hasLength(2));
assertRegion(
region: regions[0],
@@ -329,40 +467,37 @@
details: ["This variable is initialized to an explicit 'null'"]);
assertRegion(
region: regions[1],
- offset: 35,
+ offset: 34,
details: ["This variable is initialized to a nullable value"]);
}
test_mapLiteralTypeArgument() async {
- // TODO(srawlins): Simplify this test with `var x` once #38341 is fixed.
UnitInfo unit = await buildInfoForSingleTestFile('''
void f() {
String s = null;
- Map<String, bool> x = <String, bool>{"hello": false, s: true};
- Map<bool, String> y = <bool, String>{false: "hello", true: s};
+ var x = <String, bool>{"hello": false, s: true};
+ var y = <bool, String>{false: "hello", true: s};
}
''', migratedContent: '''
void f() {
String? s = null;
- Map<String?, bool> x = <String?, bool>{"hello": false, s: true};
- Map<bool, String?> y = <bool, String?>{false: "hello", true: s};
+ var x = <String?, bool>{"hello": false, s: true};
+ var y = <bool, String?>{false: "hello", true: s};
}
''');
List<RegionInfo> regions = unit.fixRegions;
- expect(regions, hasLength(5));
+ expect(regions, hasLength(3));
// regions[0] is the `String? s` fix.
- // regions[1] is the `Map<String?, bool> x` fix.
+ assertRegion(
+ region: regions[1],
+ offset: 48,
+ details: ["This map is initialized with a nullable value on line 3"]);
+ assertDetail(detail: regions[1].details[0], offset: 71, length: 1);
assertRegion(
region: regions[2],
- offset: 63,
- details: ["This map is initialized with a nullable value on line 3"]);
- assertDetail(detail: regions[2].details[0], offset: 85, length: 1);
- // regions[3] is the `Map<bool, String?> y` fix.
- assertRegion(
- region: regions[4],
- offset: 136,
+ offset: 106,
details: ["This map is initialized with a nullable value on line 4"]);
- assertDetail(detail: regions[4].details[0], offset: 156, length: 1);
+ assertDetail(detail: regions[2].details[0], offset: 128, length: 1);
}
test_nonNullableType_assert() async {
@@ -414,6 +549,33 @@
]);
}
+ test_nullCheck_onFunctionArgument() async {
+ UnitInfo unit = await buildInfoForSingleTestFile('''
+class C {
+ int value;
+ C([this.value]);
+ void f() {
+ value.abs();
+ }
+}
+''', migratedContent: '''
+class C {
+ int? value;
+ C([this.value]);
+ void f() {
+ value!.abs();
+ }
+}
+''');
+ List<RegionInfo> regions = unit.regions;
+ expect(regions, hasLength(2));
+ // regions[0] is `int?`.
+ assertRegion(
+ region: regions[1],
+ offset: 65,
+ details: ["A nullable value can't be used here"]);
+ }
+
test_parameter_fromInvocation_explicit() async {
UnitInfo unit = await buildInfoForSingleTestFile('''
void f(String s) {}
@@ -491,6 +653,7 @@
]);
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/39378')
test_parameter_fromOverriden_implicit() async {
UnitInfo unit = await buildInfoForSingleTestFile('''
class A {
@@ -600,7 +763,6 @@
details: ["This parameter has an implicit default value of 'null'"]);
}
- @failingTest
test_return_fromOverriden() async {
UnitInfo unit = await buildInfoForSingleTestFile('''
abstract class A {
@@ -623,6 +785,7 @@
region: regions[0],
offset: 27,
details: ["An overridding method has a nullable return value"]);
+ assertDetail(detail: regions[0].details[0], offset: 60, length: 6);
}
test_return_multipleReturns() async {
@@ -742,11 +905,10 @@
}
test_setLiteralTypeArgument_nestedList() async {
- // TODO(srawlins): Simplify this test with `var x` once #38341 is fixed.
UnitInfo unit = await buildInfoForSingleTestFile('''
void f() {
String s = null;
- Set<List<String>> x = <List<String>>{
+ var x = <List<String>>{
["hello"],
if (1 == 2) [s]
};
@@ -754,23 +916,22 @@
''', migratedContent: '''
void f() {
String? s = null;
- Set<List<String?>> x = <List<String?>>{
+ var x = <List<String?>>{
["hello"],
if (1 == 2) [s]
};
}
''');
List<RegionInfo> regions = unit.fixRegions;
- expect(regions, hasLength(3));
+ expect(regions, hasLength(2));
// regions[0] is the `String? s` fix.
- // regions[1] is the `Set<List<String?>> x` fix.
assertRegion(
- region: regions[2],
- offset: 68,
+ region: regions[1],
+ offset: 53,
details: ["This set is initialized with a nullable value on line 5"]);
// TODO(srawlins): Actually, this is marking the `[s]`, but I think only
// `s` should be marked. Minor bug for now.
- assertDetail(detail: regions[2].details[0], offset: 101, length: 3);
+ assertDetail(detail: regions[1].details[0], offset: 87, length: 3);
}
test_topLevelVariable() async {
@@ -792,4 +953,66 @@
offset: 19,
details: ["This variable is initialized to a nullable value"]);
}
+
+ test_uninitializedField() async {
+ UnitInfo unit = await buildInfoForSingleTestFile('''
+class C {
+ int value;
+ C();
+ C.one() {
+ this.value = 7;
+ }
+ C.two() {}
+}
+''', migratedContent: '''
+class C {
+ int? value;
+ C();
+ C.one() {
+ this.value = 7;
+ }
+ C.two() {}
+}
+''');
+ List<RegionInfo> regions = unit.regions;
+ expect(regions, hasLength(1));
+ RegionInfo region = regions.single;
+ assertRegion(region: region, offset: 15, details: [
+ "The constructor 'C' does not initialize this field in its initializer "
+ "list",
+ "The constructor 'C.one' does not initialize this field in its "
+ "initializer list",
+ "The constructor 'C.two' does not initialize this field in its "
+ "initializer list",
+ ]);
+
+ assertDetail(detail: region.details[0], offset: 25, length: 1);
+ assertDetail(detail: region.details[1], offset: 34, length: 3);
+ assertDetail(detail: region.details[2], offset: 70, length: 3);
+ }
+
+ test_uninitializedVariable_notLate_uninitializedUse() async {
+ UnitInfo unit = await buildInfoForSingleTestFile('''
+void f() {
+ int v1;
+ if (1 == 2) v1 = 7;
+ g(v1);
+}
+void g(int i) => print(i.isEven);
+''', migratedContent: '''
+void f() {
+ int? v1;
+ if (1 == 2) v1 = 7;
+ g(v1!);
+}
+void g(int i) => print(i.isEven);
+''');
+ List<RegionInfo> regions = unit.fixRegions;
+ expect(regions, hasLength(2));
+ assertRegion(
+ region: regions[0],
+ offset: 16,
+ details: ["Used on line 4, when it is possibly uninitialized"]);
+ // regions[1] is the `v1!` fix.
+ }
}
diff --git a/pkg/analysis_server/test/src/services/flutter/widget_descriptions_test.dart b/pkg/analysis_server/test/src/services/flutter/widget_descriptions_test.dart
index 8fe158f..980d4b4 100644
--- a/pkg/analysis_server/test/src/services/flutter/widget_descriptions_test.dart
+++ b/pkg/analysis_server/test/src/services/flutter/widget_descriptions_test.dart
@@ -321,6 +321,29 @@
''');
}
+ test_expression_formatError() async {
+ await resolveTestUnit('''
+import 'package:flutter/material.dart';
+
+void main() {
+ Text('', maxLines: 1);
+}
+''');
+ var property = await getWidgetProperty('Text(', 'maxLines');
+
+ var result = await descriptions.setPropertyValue(
+ property.id,
+ protocol.FlutterWidgetPropertyValue(expression: 'foo <'),
+ );
+
+ expect(
+ result.errorCode,
+ protocol.RequestErrorCode
+ .FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION,
+ );
+ expect(result.change, isNull);
+ }
+
test_format_dontFormatOther() async {
await resolveTestUnit('''
import 'package:flutter/material.dart';
diff --git a/pkg/analysis_server/test/src/test_all.dart b/pkg/analysis_server/test/src/test_all.dart
index 39637af..fa37c50 100644
--- a/pkg/analysis_server/test/src/test_all.dart
+++ b/pkg/analysis_server/test/src/test_all.dart
@@ -13,7 +13,6 @@
import 'plugin/test_all.dart' as plugin;
import 'services/test_all.dart' as services;
import 'utilities/test_all.dart' as utilities;
-import 'watch_manager_test.dart' as watch_manager;
/**
* Utility for manually running all tests.
@@ -29,6 +28,5 @@
plugin.main();
services.main();
utilities.main();
- watch_manager.main();
}, name: 'src');
}
diff --git a/pkg/analysis_server/test/src/watch_manager_test.dart b/pkg/analysis_server/test/src/watch_manager_test.dart
deleted file mode 100644
index a5a4a93..0000000
--- a/pkg/analysis_server/test/src/watch_manager_test.dart
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright (c) 2015, 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.
-
-import 'dart:async';
-
-import 'package:analysis_server/src/watch_manager.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'package:watcher/watcher.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(WatchManagerTest);
- defineReflectiveTests(WatchNodeTest);
- });
-}
-
-/**
- * Tokens that can be used for testing purposes.
- */
-class Token {
- /**
- * A name used for debugging.
- */
- final String name;
-
- /**
- * Initialize a newly created token to have the given name.
- */
- Token(this.name);
-
- @override
- String toString() => name;
-}
-
-/**
- * A listener that captures the state of watch events so that they can be
- * tested.
- */
-class WatchListener {
- /**
- * The event that was passed to the listener method.
- */
- WatchEvent event;
-
- /**
- * The tokens that were passed to the listener method.
- */
- List<Token> tokens;
-
- /**
- * Clear the state so that we can distinguish between not receiving an event
- * and receiving the wrong event.
- */
- void clear() {
- this.event = null;
- this.tokens = null;
- }
-
- /**
- * The listener method.
- */
- void handleWatchEvent(WatchEvent event, List<Token> tokens) {
- this.event = event;
- this.tokens = tokens;
- }
-}
-
-@reflectiveTest
-class WatchManagerTest with ResourceProviderMixin {
- WatchListener listener;
- WatchManager<Token> manager;
-
- void setUp() {
- listener = new WatchListener();
- manager =
- new WatchManager<Token>(resourceProvider, listener.handleWatchEvent);
- }
-
- Future test_addFolder_folderAndSubfolder() async {
- Folder topFolder = getFolder('/a/b');
- Folder childFolder = getFolder('/a/b/c/d');
- Token topToken = new Token('topToken');
- Token childToken = new Token('childToken');
- manager.addFolder(topFolder, topToken);
- manager.addFolder(childFolder, childToken);
-
- File newFile1 = newFile('/a/b/c/lib.dart');
- await _expectEvent(ChangeType.ADD, newFile1.path, [topToken]);
-
- File newFile2 = newFile('/a/b/c/d/lib.dart');
- return _expectEvent(ChangeType.ADD, newFile2.path, [topToken, childToken]);
- }
-
- Future test_addFolder_singleFolder_multipleTokens() {
- Folder folder = getFolder('/a/b');
- Token token1 = new Token('token1');
- Token token2 = new Token('token2');
- manager.addFolder(folder, token1);
- manager.addFolder(folder, token2);
-
- File addedFile = newFile('/a/b/lib.dart');
- return _expectEvent(ChangeType.ADD, addedFile.path, [token1, token2]);
- }
-
- Future test_addFolder_singleFolder_singleToken() async {
- Folder folder = getFolder('/a/b');
- Token token = new Token('token');
- manager.addFolder(folder, token);
-
- Folder addedFolder = newFolder('/a/b/c');
- await _expectEvent(ChangeType.ADD, addedFolder.path, [token]);
-
- File addedFile = newFile('/a/b/c/lib.dart');
- return _expectEvent(ChangeType.ADD, addedFile.path, [token]);
- }
-
- Future test_addFolder_unrelatedFolders() async {
- Folder folder1 = getFolder('/a/b');
- Folder folder2 = getFolder('/c/d');
- Token token1 = new Token('token1');
- Token token2 = new Token('token2');
- manager.addFolder(folder1, token1);
- manager.addFolder(folder2, token2);
-
- File newFile1 = newFile('/a/b/lib.dart');
- await _expectEvent(ChangeType.ADD, newFile1.path, [token1]);
-
- File newFile2 = newFile('/c/d/lib.dart');
- return _expectEvent(ChangeType.ADD, newFile2.path, [token2]);
- }
-
- void test_creation() {
- expect(manager, isNotNull);
- }
-
- Future test_removeFolder_multipleTokens() {
- Folder folder = getFolder('/a/b');
- Token token1 = new Token('token1');
- Token token2 = new Token('token2');
- manager.addFolder(folder, token1);
- manager.addFolder(folder, token2);
- manager.removeFolder(folder, token2);
-
- File addedFile = newFile('/a/b/lib.dart');
- return _expectEvent(ChangeType.ADD, addedFile.path, [token1]);
- }
-
- Future test_removeFolder_withChildren() async {
- Folder topFolder = getFolder('/a/b');
- Folder childFolder = getFolder('/a/b/c/d');
- Token topToken = new Token('topToken');
- Token childToken = new Token('childToken');
- manager.addFolder(topFolder, topToken);
- manager.addFolder(childFolder, childToken);
- manager.removeFolder(topFolder, topToken);
-
- File addedFile = newFile('/a/b/c/d/lib.dart');
- await _expectEvent(ChangeType.ADD, addedFile.path, [childToken]);
-
- newFile('/a/b/lib.dart');
- return _expectNoEvent();
- }
-
- Future test_removeFolder_withNoChildren() {
- Folder folder = getFolder('/a/b');
- Token token = new Token('token');
- manager.addFolder(folder, token);
- manager.removeFolder(folder, token);
-
- newFile('/a/b/lib.dart');
- return _expectNoEvent();
- }
-
- Future _expectEvent(ChangeType expectedType, String expectedPath,
- List<Token> expectedTokens) async {
- await pumpEventQueue();
- WatchEvent event = listener.event;
- expect(event, isNotNull);
- expect(event.type, expectedType);
- expect(event.path, expectedPath);
- expect(listener.tokens, unorderedEquals(expectedTokens));
- listener.clear();
- }
-
- Future _expectNoEvent() async {
- await pumpEventQueue();
- expect(listener.event, isNull);
- expect(listener.tokens, isNull);
- }
-}
-
-@reflectiveTest
-class WatchNodeTest with ResourceProviderMixin {
- void test_creation_folder() {
- Folder folder = getFolder('/a/b');
- WatchNode node = new WatchNode(folder);
- expect(node, isNotNull);
- expect(node.children, isEmpty);
- expect(node.folder, folder);
- expect(node.parent, isNull);
- expect(node.subscription, isNull);
- expect(node.tokens, isEmpty);
- }
-
- void test_creation_noFolder() {
- WatchNode node = new WatchNode(null);
- expect(node, isNotNull);
- expect(node.children, isEmpty);
- expect(node.folder, isNull);
- expect(node.parent, isNull);
- expect(node.subscription, isNull);
- expect(node.tokens, isEmpty);
- }
-
- void test_delete_nested_child() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
- WatchNode childNode = new WatchNode(getFolder('/a/b/c/d'));
- WatchNode grandchildNode = new WatchNode(getFolder('/a/b/c/d/e'));
- rootNode.insert(topNode);
- rootNode.insert(childNode);
- rootNode.insert(grandchildNode);
-
- childNode.delete();
- expect(rootNode.children, equals([topNode]));
- expect(topNode.children, equals([grandchildNode]));
- expect(topNode.parent, rootNode);
- expect(grandchildNode.parent, topNode);
- }
-
- void test_delete_nested_noChild() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
- WatchNode childNode = new WatchNode(getFolder('/a/b/c/d'));
- rootNode.insert(topNode);
- rootNode.insert(childNode);
-
- childNode.delete();
- expect(rootNode.children, equals([topNode]));
- expect(topNode.children, isEmpty);
- expect(topNode.parent, rootNode);
- }
-
- void test_delete_top_child() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
- WatchNode childNode = new WatchNode(getFolder('/a/b/c/d'));
- rootNode.insert(topNode);
- rootNode.insert(childNode);
-
- topNode.delete();
- expect(rootNode.children, equals([childNode]));
- expect(childNode.parent, rootNode);
- }
-
- void test_delete_top_noChild() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
- rootNode.insert(topNode);
-
- topNode.delete();
- expect(rootNode.children, isEmpty);
- }
-
- void test_findParent_childOfLeaf() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
- rootNode.insert(topNode);
-
- expect(rootNode.findParent('/a/b/c'), topNode);
- }
-
- void test_findParent_childOfNonLeaf() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
- WatchNode childNode = new WatchNode(getFolder('/a/b/c/d'));
- rootNode.insert(topNode);
- rootNode.insert(childNode);
-
- expect(rootNode.findParent('/a/b/c'), topNode);
- }
-
- void test_findParent_noMatch() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
- rootNode.insert(topNode);
-
- expect(rootNode.findParent('/c/d'), rootNode);
- }
-
- void test_insert_intermediate_afterParentAndChild() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
- WatchNode childNode = new WatchNode(getFolder('/a/b/c/d'));
- WatchNode intermediateNode = new WatchNode(getFolder('/a/b/c'));
-
- rootNode.insert(topNode);
- rootNode.insert(childNode);
- rootNode.insert(intermediateNode);
- expect(topNode.parent, rootNode);
- expect(topNode.children, equals([intermediateNode]));
- expect(intermediateNode.parent, topNode);
- expect(intermediateNode.children, equals([childNode]));
- expect(childNode.parent, intermediateNode);
- expect(childNode.children, isEmpty);
- }
-
- void test_insert_nested_afterParent() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
- WatchNode childNode = new WatchNode(getFolder('/a/b/c/d'));
-
- rootNode.insert(topNode);
- rootNode.insert(childNode);
- expect(childNode.parent, topNode);
- expect(childNode.children, isEmpty);
- expect(topNode.children, equals([childNode]));
- }
-
- void test_insert_nested_beforeParent() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
- WatchNode childNode = new WatchNode(getFolder('/a/b/c/d'));
-
- rootNode.insert(childNode);
- rootNode.insert(topNode);
- expect(childNode.parent, topNode);
- expect(childNode.children, isEmpty);
- expect(topNode.children, equals([childNode]));
- }
-
- void test_insert_top() {
- WatchNode rootNode = new WatchNode(null);
- WatchNode topNode = new WatchNode(getFolder('/a/b'));
-
- rootNode.insert(topNode);
- expect(rootNode.children, equals([topNode]));
- expect(topNode.parent, rootNode);
- expect(topNode.children, isEmpty);
- }
-}
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index ea364d4..17348dd 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -117,6 +117,6 @@
### dart/textDocument/publishClosingLabels Notification
Direction: Server -> Client
-Params: `{ uri: string, abels: { label: string, range: Range }[] }`
+Params: `{ uri: string, labels: { label: string, range: Range }[] }`
Notifies the client when closing label information is available (or updated) for a file.
diff --git a/pkg/analysis_server/tool/migration_runner.dart b/pkg/analysis_server/tool/migration_runner.dart
new file mode 100644
index 0000000..c826d61
--- /dev/null
+++ b/pkg/analysis_server/tool/migration_runner.dart
@@ -0,0 +1,176 @@
+// Copyright (c) 2019, 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.
+
+/// This executable provides the ability to run the migration tool in process
+/// on a single package. It should be invoked with two command-line arguments:
+/// a path to a configuration file and the name of a package to migrate.
+///
+/// The configuration file format is a JSON map, with the following keys:
+/// - `sdk_root`: path to the SDK source code on the user's machine (this is the
+/// directory that contains `pkg`, `third_party`, `tests`, etc.
+/// - `output_root`: if present, path to the directory on the user's machine
+/// where output HTML files should go. A subdirectory will be created for
+/// each package that is migrated.
+/// - `external_packages`: a map (name => path) of additional non-SDK packages
+/// that may need to be migrated.
+/// - `port`: if present, the port where a server should be spawned serving HTML
+/// pages.
+library migration_runner;
+
+import 'dart:convert';
+import 'dart:io' as io;
+
+import 'package:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/protocol/protocol_constants.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/utilities/mocks.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/instrumentation/instrumentation.dart';
+import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/generated/sdk.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+main(List<String> args) async {
+ if (args.length != 2) {
+ throw StateError(
+ 'Exactly two arguments are required: the path to a JSON configuration '
+ 'file, and the name of the package to migrate');
+ }
+ var testInfoJsonPath = args[0];
+ var testInfoJson = json.decode(io.File(testInfoJsonPath).readAsStringSync());
+ var packageName = args[1];
+ var testInfo = TestInfo(testInfoJson);
+ var packageRoot = testInfo.packageRoot(packageName);
+ var outputRoot = testInfo.outputRoot;
+ var port = testInfo.port;
+ String outputDir =
+ outputRoot == null ? null : path.join(outputRoot, packageName);
+ print('Preparing to migrate');
+ var migrationTest = MigrationTest();
+ migrationTest.setUp();
+ print('Migrating');
+ await migrationTest.run(packageRoot, outputDir, port);
+ if (port == null) {
+ print('Done');
+ io.exit(0);
+ } else {
+ print('Done. Please point your browser to localhost:$port/\$filePath');
+ }
+}
+
+class MigrationBase {
+ ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
+ MockServerChannel serverChannel;
+ AnalysisServer server;
+
+ AnalysisServer createAnalysisServer() {
+ //
+ // Create server
+ //
+ AnalysisServerOptions options = new AnalysisServerOptions();
+ String sdkPath = FolderBasedDartSdk.defaultSdkDirectory(
+ PhysicalResourceProvider.INSTANCE,
+ ).path;
+ return new AnalysisServer(serverChannel, resourceProvider, options,
+ new DartSdkManager(sdkPath, true), InstrumentationService.NULL_SERVICE);
+ }
+
+ void processNotification(Notification notification) {
+ if (notification.event == SERVER_NOTIFICATION_ERROR) {
+ fail('${notification.toJson()}');
+ }
+ }
+
+ Future<Response> sendAnalysisSetAnalysisRoots(List<String> directories) {
+ var request =
+ AnalysisSetAnalysisRootsParams(directories, []).toRequest('0');
+ return waitResponse(request);
+ }
+
+ Future<Response> sendEditDartfix(
+ List<String> directories, String outputDir, int port) {
+ var request = EditDartfixParams(directories,
+ includedFixes: ['non-nullable'], outputDir: outputDir, port: port)
+ .toRequest('1');
+ return waitResponse(request);
+ }
+
+ void setUp() {
+ serverChannel = new MockServerChannel();
+ server = createAnalysisServer();
+ server.pluginManager = new TestPluginManager();
+ // listen for notifications
+ Stream<Notification> notificationStream =
+ serverChannel.notificationController.stream;
+ notificationStream.listen((Notification notification) {
+ processNotification(notification);
+ });
+ }
+
+ void tearDown() {
+ server.done();
+ server = null;
+ serverChannel = null;
+ }
+
+ /// Returns a [Future] that completes when the server's analysis is complete.
+ Future waitForTasksFinished() {
+ return server.onAnalysisComplete;
+ }
+
+ /// Completes with a successful [Response] for the given [request].
+ Future<Response> waitResponse(Request request,
+ {bool throwOnError = true}) async {
+ return serverChannel.sendRequest(request, throwOnError: throwOnError);
+ }
+}
+
+class MigrationTest extends MigrationBase {
+ Future<void> run(String packageRoot, String outputDir, int port) async {
+ List<String> packageRoots = [packageRoot];
+ await sendAnalysisSetAnalysisRoots(packageRoots);
+ await sendEditDartfix(packageRoots, outputDir, port);
+ }
+}
+
+class TestInfo {
+ static const Set<String> thirdPartyPackages = {
+ 'charcode',
+ 'collection',
+ 'logging',
+ 'meta',
+ 'pedantic',
+ 'typed_data'
+ };
+
+ static const Set<String> builtInPackages = {'meta', 'path'};
+
+ final Map<String, Object> testInfoJson;
+
+ TestInfo(this.testInfoJson);
+
+ Map<String, String> get externalPackages =>
+ ((testInfoJson['external_packages'] ?? {}) as Map).cast<String, String>();
+
+ String get outputRoot => testInfoJson['output_root'];
+
+ int get port => testInfoJson['port'];
+
+ String get sdkRoot => testInfoJson['sdk_root'];
+
+ String packageRoot(String packageName) {
+ if (thirdPartyPackages.contains(packageName)) {
+ return path.join(sdkRoot, 'third_party', 'pkg', packageName);
+ } else if (builtInPackages.contains(packageName)) {
+ return path.join(sdkRoot, 'pkg', packageName);
+ } else if (externalPackages.containsKey(packageName)) {
+ return externalPackages[packageName];
+ } else {
+ throw StateError('Unrecognized package $packageName');
+ }
+ }
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index e2df2d3..c887243 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -439,6 +439,8 @@
* the client is interested in receiving completion suggestions. If one configured path is
* beneath another, the descendent will override the ancestors' configured libraries of
* interest.
+ *
+ * @deprecated
*/
public void completion_registerLibraryPaths(List<LibraryPathSet> paths);
@@ -842,7 +844,9 @@
* @param value The new value to set for the property. If absent, indicates that the property
* should be removed. If the property corresponds to an optional parameter, the
* corresponding named argument is removed. If the property isRequired is true,
- * FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED error is generated.
+ * FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED error is generated. If the expression is
+ * not a syntactically valid Dart code, then
+ * FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION is reported.
*/
public void flutter_setWidgetPropertyValue(int id, FlutterWidgetPropertyValue value, SetWidgetPropertyValueConsumer consumer);
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
index 6abbf6e..c968830 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
@@ -38,6 +38,11 @@
public static final String FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET = "FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET";
/**
+ * The given property expression is invalid, e.g. has a syntax error.
+ */
+ public static final String FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION = "FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION";
+
+ /**
* The given property identifier is not valid. It might have never been valid, or a change to code
* invalidated it, or its TTL was exceeded.
*/
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 5c210a87..360bab1 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -1437,7 +1437,7 @@
</field>
</params>
</request>
- <request method="registerLibraryPaths">
+ <request method="registerLibraryPaths" deprecated="true">
<p>
The client can make this request to express interest in certain
libraries to receive completion suggestions from based on the client path.
@@ -3245,6 +3245,11 @@
true, <tt>FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED</tt> error
is generated.
</p>
+ <p>
+ If the <tt>expression</tt> is not a syntactically valid Dart code,
+ then <tt>FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION</tt>
+ is reported.
+ </p>
</field>
</params>
<result>
@@ -4901,6 +4906,12 @@
</p>
</value>
<value>
+ <code>FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION</code>
+ <p>
+ The given property expression is invalid, e.g. has a syntax error.
+ </p>
+ </value>
+ <value>
<code>FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID</code>
<p>
The given property identifier is not valid. It might have never been
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index 6431008..f04a782 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -15780,6 +15780,9 @@
* corresponds to an optional parameter, the corresponding named argument is
* removed. If the property isRequired is true,
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED error is generated.
+ *
+ * If the expression is not a syntactically valid Dart code, then
+ * FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION is reported.
*/
FlutterWidgetPropertyValue get value => _value;
@@ -15790,6 +15793,9 @@
* corresponds to an optional parameter, the corresponding named argument is
* removed. If the property isRequired is true,
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED error is generated.
+ *
+ * If the expression is not a syntactically valid Dart code, then
+ * FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION is reported.
*/
void set value(FlutterWidgetPropertyValue value) {
this._value = value;
@@ -19717,6 +19723,7 @@
* DEBUG_PORT_COULD_NOT_BE_OPENED
* FILE_NOT_ANALYZED
* FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET
+ * FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID
* FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED
* FORMAT_INVALID_FILE
@@ -19778,6 +19785,14 @@
const RequestErrorCode._("FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET");
/**
+ * The given property expression is invalid, e.g. has a syntax error.
+ */
+ static const RequestErrorCode
+ FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION =
+ const RequestErrorCode._(
+ "FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION");
+
+ /**
* The given property identifier is not valid. It might have never been
* valid, or a change to code invalidated it, or its TTL was exceeded.
*/
@@ -19985,6 +20000,7 @@
DEBUG_PORT_COULD_NOT_BE_OPENED,
FILE_NOT_ANALYZED,
FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET,
+ FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION,
FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID,
FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED,
FORMAT_INVALID_FILE,
@@ -20030,6 +20046,8 @@
return FILE_NOT_ANALYZED;
case "FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET":
return FLUTTER_GET_WIDGET_DESCRIPTION_NO_WIDGET;
+ case "FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION":
+ return FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_EXPRESSION;
case "FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID":
return FLUTTER_SET_WIDGET_PROPERTY_VALUE_INVALID_ID;
case "FLUTTER_SET_WIDGET_PROPERTY_VALUE_IS_REQUIRED":
diff --git a/pkg/analyzer/README.md b/pkg/analyzer/README.md
index 201fcca..fb43fa4 100644
--- a/pkg/analyzer/README.md
+++ b/pkg/analyzer/README.md
@@ -100,7 +100,7 @@
[dartanalyzer]: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli#dartanalyzer
[list]: https://groups.google.com/a/dartlang.org/forum/#!forum/analyzer-discuss
[lintrules]: https://dart-lang.github.io/linter/lints/
-[glob]: https://pub.dartlang.org/packages/glob
+[glob]: https://pub.dev/packages/glob
[LICENSE]: https://github.com/dart-lang/sdk/blob/master/pkg/analyzer/LICENSE
[dartfmt]: https://github.com/dart-lang/dart_style
[dartdoc]: https://github.com/dart-lang/dartdoc
diff --git a/pkg/analyzer/lib/dart/analysis/utilities.dart b/pkg/analyzer/lib/dart/analysis/utilities.dart
index ac920d1..bddafbd 100644
--- a/pkg/analyzer/lib/dart/analysis/utilities.dart
+++ b/pkg/analyzer/lib/dart/analysis/utilities.dart
@@ -99,8 +99,13 @@
///
/// If [throwIfDiagnostics] is `true` (the default), then if any diagnostics are
/// produced because of syntactic errors in the [content] an `ArgumentError`
-/// will be thrown. If the parameter is `false`, then the caller can check the
-/// result to see whether there are any `errors`.
+/// will be thrown. This behavior is not intended as a way for the client to
+/// find out about errors--it is intended to avoid causing problems for naive
+/// clients that might not be thinking about the possibility of parse errors
+/// (and might therefore make assumptions about the returned AST that don't hold
+/// in the presence of parse errors). Clients interested in details about parse
+/// errors should pass `false` and check `result.errors` to determine what parse
+/// errors, if any, have occurred.
ParseStringResult parseString(
{@required String content,
FeatureSet featureSet,
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 29038c6..059219c 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -38,11 +38,13 @@
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/java_engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/resolver.dart'
+ show Namespace, TypeProvider;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/task/api/model.dart' show AnalysisTarget;
@@ -1312,6 +1314,12 @@
/// elements, but does not include imports, exports, or synthetic elements.
Iterable<Element> get topLevelElements;
+ /// Return the [TypeProvider] that is used in this library.
+ TypeProvider get typeProvider;
+
+ /// Return the [TypeSystem] that is used in this library.
+ TypeSystem get typeSystem;
+
/// Return a list containing all of the compilation units this library
/// consists of. This includes the defining compilation unit and units
/// included using the `part` directive.
@@ -1571,7 +1579,10 @@
/// A top-level variable.
///
/// Clients may not extend, implement or mix-in this class.
-abstract class TopLevelVariableElement implements PropertyInducingElement {}
+abstract class TopLevelVariableElement implements PropertyInducingElement {
+ @override
+ TopLevelVariableElement get declaration;
+}
/// An element that defines a type.
///
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index 6462cde..d80c7b4 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -20,6 +20,7 @@
/// type parameters. But if we declare a variable as `Pair<String, int> pair;`
/// the references to `String` and `int` are type arguments.
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/src/dart/element/type.dart' show InterfaceTypeImpl;
/// The type associated with elements in the element model.
@@ -111,6 +112,9 @@
/// such as when the type represents the type of an unnamed function.
String get name;
+ /// Return the nullability suffix of this type.
+ NullabilitySuffix get nullabilitySuffix;
+
/// If this type is a [TypeParameterType], returns its bound if it has one, or
/// [objectType] otherwise.
///
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 7313b18..8e471b0 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -302,6 +302,7 @@
CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+ // ignore: deprecated_member_use_from_same_package
CompileTimeErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR,
CompileTimeErrorCode.UNDEFINED_ANNOTATION,
CompileTimeErrorCode.UNDEFINED_CLASS,
@@ -320,6 +321,8 @@
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_POSITION,
+ CompileTimeErrorCode.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR,
CompileTimeErrorCode.YIELD_IN_NON_GENERATOR,
FfiCode.ANNOTATION_ON_POINTER_FIELD,
@@ -627,6 +630,7 @@
ParserErrorCode.TYPEDEF_IN_CLASS,
ParserErrorCode.TYPE_ARGUMENTS_ON_TYPE_VARIABLE,
ParserErrorCode.TYPE_BEFORE_FACTORY,
+ ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR,
ParserErrorCode.UNEXPECTED_TERMINATOR_FOR_PARAMETER_GROUP,
ParserErrorCode.UNEXPECTED_TOKEN,
ParserErrorCode.VAR_AND_TYPE,
@@ -669,8 +673,11 @@
StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION,
StaticTypeWarningCode.NON_BOOL_OPERAND,
StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT,
+ // ignore: deprecated_member_use_from_same_package
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
+ StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION,
+ StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_METHOD,
StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
StaticTypeWarningCode.UNDEFINED_ENUM_CONSTANT,
StaticTypeWarningCode.UNDEFINED_FUNCTION,
diff --git a/pkg/analyzer/lib/error/listener.dart b/pkg/analyzer/lib/error/listener.dart
index 124d667..19235f8 100644
--- a/pkg/analyzer/lib/error/listener.dart
+++ b/pkg/analyzer/lib/error/listener.dart
@@ -202,7 +202,7 @@
if (name != null && name.isNotEmpty) {
StringBuffer buffer = new StringBuffer();
buffer.write(name);
- (type as TypeImpl).appendTo(buffer, new Set.identity());
+ (type as TypeImpl).appendTo(buffer);
return buffer.toString();
}
}
diff --git a/pkg/analyzer/lib/exception/exception.dart b/pkg/analyzer/lib/exception/exception.dart
index e5f6335..779f27a 100644
--- a/pkg/analyzer/lib/exception/exception.dart
+++ b/pkg/analyzer/lib/exception/exception.dart
@@ -68,6 +68,19 @@
CaughtException.withMessage(this.message, this.exception, stackTrace)
: this.stackTrace = stackTrace ?? StackTrace.current;
+ /**
+ * Recursively unwrap this [CaughtException] if it itself contains a
+ * [CaughtException].
+ *
+ * If it does not contain a [CaughtException], simply return this instance.
+ */
+ CaughtException get rootCaughtException {
+ if (exception is CaughtException) {
+ return (exception as CaughtException).rootCaughtException;
+ }
+ return this;
+ }
+
@override
String toString() {
StringBuffer buffer = new StringBuffer();
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index 83a34de..fa9ce48 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -262,7 +262,12 @@
@override
Stream<WatchEvent> get changes =>
new DirectoryWatcher(_entry.path).events.handleError((error) {},
- test: (error) => error is io.FileSystemException);
+ test: (error) =>
+ error is io.FileSystemException &&
+ // Don't suppress "Directory watcher closed," so the outer
+ // listener can see the interruption & act on it.
+ !error.message
+ .startsWith("Directory watcher closed unexpectedly"));
/**
* Return the underlying file being represented by this wrapper.
diff --git a/pkg/analyzer/lib/source/line_info.dart b/pkg/analyzer/lib/source/line_info.dart
index 631029f..457f38e 100644
--- a/pkg/analyzer/lib/source/line_info.dart
+++ b/pkg/analyzer/lib/source/line_info.dart
@@ -86,7 +86,7 @@
}
}
- // Binary search to fine the line containing this offset.
+ // Binary search to find the line containing this offset.
while (min < max) {
var midpoint = (max - min + 1) ~/ 2 + min;
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index eb36757..bb0b380 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -15,7 +15,6 @@
applyAnalysisOptionFlags,
bazelAnalysisOptionsPath,
flutterAnalysisOptionsPath;
-import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/context/context_root.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/context_root.dart' as api;
@@ -151,23 +150,6 @@
: builderOptions = options ?? new ContextBuilderOptions();
/**
- * Return an analysis context that is configured correctly to analyze code in
- * the directory with the given [path].
- *
- * *Note:* This method is not yet fully implemented and should not be used.
- */
- AnalysisContext buildContext(String path) {
- InternalAnalysisContext context =
- AnalysisEngine.instance.createAnalysisContext();
- AnalysisOptionsImpl options = getAnalysisOptions(path);
- context.sourceFactory = createSourceFactory(path, options);
- context.analysisOptions = options;
- //_processAnalysisOptions(context, optionMap);
- declareVariables(context);
- return context;
- }
-
- /**
* Return an analysis driver that is configured correctly to analyze code in
* the directory with the given [path].
*/
@@ -292,17 +274,6 @@
/**
* Add any [declaredVariables] to the list of declared variables used by the
- * given [context].
- */
- void declareVariables(AnalysisContextImpl context) {
- Map<String, String> variables = builderOptions.declaredVariables;
- if (variables != null && variables.isNotEmpty) {
- context.declaredVariables = new DeclaredVariables.fromMap(variables);
- }
- }
-
- /**
- * Add any [declaredVariables] to the list of declared variables used by the
* given analysis [driver].
*/
void declareVariablesInDriver(AnalysisDriver driver) {
@@ -647,23 +618,6 @@
return null;
}
- /**
- * Return `true` if either the directory at [rootPath] or a parent of that
- * directory contains a `.packages` file.
- */
- static bool _hasPackageFileInPath(
- ResourceProvider resourceProvider, String rootPath) {
- Folder folder = resourceProvider.getFolder(rootPath);
- while (folder != null) {
- File file = folder.getChildAssumingFile('.packages');
- if (file.exists) {
- return true;
- }
- folder = folder.parent;
- }
- return false;
- }
-
static Workspace createWorkspace(ResourceProvider resourceProvider,
String rootPath, ContextBuilder contextBuilder) {
if (_hasPackageFileInPath(resourceProvider, rootPath)) {
@@ -683,6 +637,23 @@
return workspace ??
BasicWorkspace.find(resourceProvider, rootPath, contextBuilder);
}
+
+ /**
+ * Return `true` if either the directory at [rootPath] or a parent of that
+ * directory contains a `.packages` file.
+ */
+ static bool _hasPackageFileInPath(
+ ResourceProvider resourceProvider, String rootPath) {
+ Folder folder = resourceProvider.getFolder(rootPath);
+ while (folder != null) {
+ File file = folder.getChildAssumingFile('.packages');
+ if (file.exists) {
+ return true;
+ }
+ folder = folder.parent;
+ }
+ return false;
+ }
}
/**
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index e1cdfc4..405869e 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -2,88 +2,85 @@
// 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:analyzer/src/dart/analysis/session.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
+import 'package:meta/meta.dart';
/**
* An [AnalysisContext] in which analysis can be performed.
*/
class AnalysisContextImpl implements InternalAnalysisContext {
- /**
- * The set of analysis options controlling the behavior of this context.
- */
- AnalysisOptionsImpl _options = new AnalysisOptionsImpl();
-
- /**
- * The source factory used to create the sources that can be analyzed in this
- * context.
- */
- SourceFactory _sourceFactory;
-
- /**
- * The set of declared variables used when computing constant values.
- */
- DeclaredVariables _declaredVariables = new DeclaredVariables();
-
- /**
- * The [TypeProvider] for this context, `null` if not yet created.
- */
- TypeProvider _typeProvider;
-
- /**
- * The [TypeSystem] for this context, `null` if not yet created.
- */
- TypeSystem _typeSystem;
-
- /**
- * Initialize a newly created analysis context.
- */
- AnalysisContextImpl();
+ final SynchronousSession _synchronousSession;
@override
- AnalysisOptions get analysisOptions => _options;
+ final SourceFactory sourceFactory;
+
+ AnalysisContextImpl(this._synchronousSession, this.sourceFactory);
+
+ @override
+ AnalysisOptionsImpl get analysisOptions {
+ return _synchronousSession.analysisOptions;
+ }
@override
void set analysisOptions(AnalysisOptions options) {
- this._options = options;
+ throw StateError('Cannot be changed.');
}
@override
- DeclaredVariables get declaredVariables => _declaredVariables;
-
- /**
- * Set the declared variables to the give collection of declared [variables].
- */
- void set declaredVariables(DeclaredVariables variables) {
- _declaredVariables = variables;
+ DeclaredVariables get declaredVariables {
+ return _synchronousSession.declaredVariables;
}
@override
- SourceFactory get sourceFactory => _sourceFactory;
-
- @override
void set sourceFactory(SourceFactory factory) {
- _sourceFactory = factory;
+ throw StateError('Cannot be changed.');
}
@override
TypeProvider get typeProvider {
- return _typeProvider;
+ return _synchronousSession.typeProvider;
}
- /**
- * Sets the [TypeProvider] for this context.
- */
- @override
- void set typeProvider(TypeProvider typeProvider) {
- _typeProvider = typeProvider;
+ TypeProviderImpl get typeProviderLegacy {
+ return _synchronousSession.typeProviderLegacy;
+ }
+
+ TypeProviderImpl get typeProviderNonNullableByDefault {
+ return _synchronousSession.typeProviderNonNullableByDefault;
}
@override
- TypeSystem get typeSystem {
- return _typeSystem ??= Dart2TypeSystem(typeProvider);
+ TypeSystemImpl get typeSystem {
+ return _synchronousSession.typeSystem;
+ }
+
+ TypeSystemImpl get typeSystemLegacy {
+ return _synchronousSession.typeSystemLegacy;
+ }
+
+ TypeSystemImpl get typeSystemNonNullableByDefault {
+ return _synchronousSession.typeSystemNonNullableByDefault;
+ }
+
+ void clearTypeProvider() {
+ _synchronousSession.clearTypeProvider();
+ }
+
+ @override
+ void setTypeProviders({
+ @required TypeProvider legacy,
+ @required TypeProvider nonNullableByDefault,
+ }) {
+ _synchronousSession.setTypeProviders(
+ legacy: legacy,
+ nonNullableByDefault: nonNullableByDefault,
+ );
}
}
@@ -96,14 +93,6 @@
* Analysis options cannot be changed afterwards. If the given [options] are
* `null`, then default options are used.
*/
- SdkAnalysisContext(AnalysisOptions options) {
- if (options != null) {
- super.analysisOptions = options;
- }
- }
-
- @override
- void set analysisOptions(AnalysisOptions options) {
- throw new StateError('AnalysisOptions of SDK context cannot be changed.');
- }
+ SdkAnalysisContext(AnalysisOptions options, SourceFactory sourceFactory)
+ : super(SynchronousSession(options, DeclaredVariables()), sourceFactory);
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/ddc.dart b/pkg/analyzer/lib/src/dart/analysis/ddc.dart
index c86790c..03670cb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/ddc.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/ddc.dart
@@ -6,10 +6,9 @@
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
-import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
-import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -38,7 +37,7 @@
final PackageBundleAssembler _assembler;
List<int> summaryBytes;
- RestrictedAnalysisContext context;
+ AnalysisContextImpl context;
summary2.LinkedElementFactory elementFactory;
DevCompilerResynthesizerBuilder({
@@ -80,7 +79,7 @@
_analysisOptions,
_declaredVariables,
);
- context = RestrictedAnalysisContext(synchronousSession, _sourceFactory);
+ context = AnalysisContextImpl(synchronousSession, _sourceFactory);
_createElementFactory(bundle);
}
@@ -157,7 +156,7 @@
);
}
- var analysisContext = RestrictedAnalysisContext(
+ var analysisContext = AnalysisContextImpl(
SynchronousSession(_analysisOptions, _declaredVariables),
_sourceFactory,
);
@@ -203,11 +202,7 @@
var dartCore = elementFactory.libraryOfUri('dart:core');
var dartAsync = elementFactory.libraryOfUri('dart:async');
- var typeProvider = TypeProviderImpl(dartCore, dartAsync);
- context.typeProvider = typeProvider;
-
- dartCore.createLoadLibraryFunction(typeProvider);
- dartAsync.createLoadLibraryFunction(typeProvider);
+ elementFactory.createTypeProviders(dartCore, dartAsync);
}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index bdbcc87..709e2acf 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -89,7 +89,7 @@
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
- static const int DATA_VERSION = 89;
+ static const int DATA_VERSION = 90;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
@@ -946,6 +946,7 @@
_requestedFiles.remove(path).forEach((completer) {
completer.completeError(exception, stackTrace);
});
+ _clearLibraryContextAfterException();
}
return;
}
@@ -962,6 +963,7 @@
_requestedLibraries.remove(path).forEach((completer) {
completer.completeError(exception, stackTrace);
});
+ _clearLibraryContextAfterException();
}
return;
}
@@ -1052,6 +1054,7 @@
}
} catch (exception, stackTrace) {
_reportException(path, exception, stackTrace);
+ _clearLibraryContextAfterException();
} finally {
_fileTracker.fileWasAnalyzed(path);
}
@@ -1077,6 +1080,7 @@
}
} catch (exception, stackTrace) {
_reportException(path, exception, stackTrace);
+ _clearLibraryContextAfterException();
} finally {
_fileTracker.fileWasAnalyzed(path);
}
@@ -1101,6 +1105,7 @@
_requestedParts.remove(path).forEach((completer) {
completer.completeError(exception, stackTrace);
});
+ _clearLibraryContextAfterException();
}
return;
}
@@ -1116,6 +1121,7 @@
_resultController.add(result);
} catch (exception, stackTrace) {
_reportException(path, exception, stackTrace);
+ _clearLibraryContextAfterException();
}
return;
}
@@ -1182,6 +1188,14 @@
_scheduler.notify(this);
}
+ /// There was an exception during a file analysis, we don't know why.
+ /// But it might have been caused by an inconsistency of files state, and
+ /// the library context state. Reset the library context, and hope that
+ /// we will solve the inconsistency while loading / building summaries.
+ void _clearLibraryContextAfterException() {
+ _libraryContext = null;
+ }
+
/// Return the cached or newly computed analysis result of the file with the
/// given [path].
///
@@ -2008,7 +2022,7 @@
TypeProvider get typeProvider => unit.declaredElement.context.typeProvider;
@override
- TypeSystem get typeSystem => unit.declaredElement.context.typeSystem;
+ TypeSystemImpl get typeSystem => unit.declaredElement.context.typeSystem;
}
class DriverPerformance {
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index d4c2171..714dc6b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -13,6 +13,8 @@
ExperimentalFeatures.control_flow_collections,
EnableString.extension_methods: ExperimentalFeatures.extension_methods,
EnableString.non_nullable: ExperimentalFeatures.non_nullable,
+ EnableString.nonfunction_type_aliases:
+ ExperimentalFeatures.nonfunction_type_aliases,
EnableString.set_literals: ExperimentalFeatures.set_literals,
EnableString.spread_collections: ExperimentalFeatures.spread_collections,
EnableString.triple_shift: ExperimentalFeatures.triple_shift,
@@ -29,6 +31,7 @@
true, // control-flow-collections
true, // extension-methods
IsEnabledByDefault.non_nullable,
+ IsEnabledByDefault.nonfunction_type_aliases,
true, // set-literals
true, // spread-collections
IsEnabledByDefault.triple_shift,
@@ -52,6 +55,9 @@
/// String to enable the experiment "non-nullable"
static const String non_nullable = 'non-nullable';
+ /// String to enable the experiment "nonfunction-type-aliases"
+ static const String nonfunction_type_aliases = 'nonfunction-type-aliases';
+
/// String to enable the experiment "set-literals"
static const String set_literals = 'set-literals';
@@ -105,8 +111,15 @@
IsExpired.non_nullable,
'Non Nullable by default');
- static const set_literals = const ExperimentalFeature(
+ static const nonfunction_type_aliases = const ExperimentalFeature(
4,
+ EnableString.nonfunction_type_aliases,
+ IsEnabledByDefault.nonfunction_type_aliases,
+ IsExpired.nonfunction_type_aliases,
+ 'Type aliases define a <type>, not just a <functionType>.');
+
+ static const set_literals = const ExperimentalFeature(
+ 5,
EnableString.set_literals,
IsEnabledByDefault.set_literals,
IsExpired.set_literals,
@@ -114,7 +127,7 @@
firstSupportedVersion: '2.2.0');
static const spread_collections = const ExperimentalFeature(
- 5,
+ 6,
EnableString.spread_collections,
IsEnabledByDefault.spread_collections,
IsExpired.spread_collections,
@@ -122,18 +135,18 @@
firstSupportedVersion: '2.2.2');
static const triple_shift = const ExperimentalFeature(
- 6,
+ 7,
EnableString.triple_shift,
IsEnabledByDefault.triple_shift,
IsExpired.triple_shift,
'Triple-shift operator');
- static const variance = const ExperimentalFeature(7, EnableString.variance,
+ static const variance = const ExperimentalFeature(8, EnableString.variance,
IsEnabledByDefault.variance, IsExpired.variance, 'Sound variance.');
@deprecated
static const bogus_disabled = const ExperimentalFeature(
- 8,
+ 9,
// ignore: deprecated_member_use_from_same_package
EnableString.bogus_disabled,
IsEnabledByDefault.bogus_disabled,
@@ -142,7 +155,7 @@
@deprecated
static const bogus_enabled = const ExperimentalFeature(
- 9,
+ 10,
// ignore: deprecated_member_use_from_same_package
EnableString.bogus_enabled,
IsEnabledByDefault.bogus_enabled,
@@ -166,6 +179,9 @@
/// Default state of the experiment "non-nullable"
static const bool non_nullable = false;
+ /// Default state of the experiment "nonfunction-type-aliases"
+ static const bool nonfunction_type_aliases = false;
+
/// Default state of the experiment "set-literals"
static const bool set_literals = true;
@@ -203,6 +219,9 @@
/// Expiration status of the experiment "non-nullable"
static const bool non_nullable = false;
+ /// Expiration status of the experiment "nonfunction-type-aliases"
+ static const bool nonfunction_type_aliases = false;
+
/// Expiration status of the experiment "set-literals"
static const bool set_literals = true;
@@ -246,6 +265,10 @@
/// Current state for the flag "non-nullable"
bool get non_nullable => isEnabled(ExperimentalFeatures.non_nullable);
+ /// Current state for the flag "nonfunction-type-aliases"
+ bool get nonfunction_type_aliases =>
+ isEnabled(ExperimentalFeatures.nonfunction_type_aliases);
+
/// Current state for the flag "set-literals"
bool get set_literals => isEnabled(ExperimentalFeatures.set_literals);
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 527a5a2..10b10fb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -7,7 +7,6 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
@@ -72,7 +71,7 @@
final LinkedElementFactory _elementFactory;
TypeProviderImpl _typeProvider;
- final TypeSystem _typeSystem;
+ final TypeSystemImpl _typeSystem;
LibraryElement _libraryElement;
LibraryScope _libraryScope;
@@ -135,9 +134,9 @@
FeatureSet featureSet = units[_library].featureSet;
_typeProvider = _context.typeProvider;
if (featureSet.isEnabled(Feature.non_nullable)) {
- _typeProvider = _typeProvider.withNullability(NullabilitySuffix.none);
+ _typeProvider = _typeProvider.asNonNullableByDefault;
} else {
- _typeProvider = _typeProvider.withNullability(NullabilitySuffix.star);
+ _typeProvider = _typeProvider.asLegacy;
}
units.forEach((file, unit) {
_validateFeatureSet(unit, featureSet);
@@ -295,8 +294,8 @@
{
UsedLocalElements usedElements =
new UsedLocalElements.merge(_usedLocalElementsList);
- UnusedLocalElementsVerifier visitor =
- new UnusedLocalElementsVerifier(errorListener, usedElements);
+ UnusedLocalElementsVerifier visitor = new UnusedLocalElementsVerifier(
+ errorListener, usedElements, _inheritance, _libraryElement);
unit.accept(visitor);
}
@@ -430,8 +429,17 @@
bool isIgnored(AnalysisError error) {
int errorLine = lineInfo.getLocation(error.offset).lineNumber;
- String errorCode = error.errorCode.name.toLowerCase();
- return ignoreInfo.ignoredAt(errorCode, errorLine);
+ String name = error.errorCode.name.toLowerCase();
+ if (ignoreInfo.ignoredAt(name, errorLine)) {
+ return true;
+ }
+ String uniqueName = error.errorCode.uniqueName;
+ int period = uniqueName.indexOf('.');
+ if (period >= 0) {
+ uniqueName = uniqueName.substring(period + 1);
+ }
+ return uniqueName != name &&
+ ignoreInfo.ignoredAt(uniqueName.toLowerCase(), errorLine);
}
return errors.where((AnalysisError e) => !isIgnored(e)).toList();
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 6998356..4bb8489 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -6,15 +6,14 @@
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/element/element.dart'
show CompilationUnitElement, LibraryElement;
+import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/library_graph.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/generated/engine.dart'
show AnalysisContext, AnalysisOptions;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
@@ -54,7 +53,7 @@
/// We use it as an approximation for the heap size of elements.
int _linkedDataInBytes = 0;
- RestrictedAnalysisContext analysisContext;
+ AnalysisContextImpl analysisContext;
LinkedElementFactory elementFactory;
InheritanceManager3 inheritanceManager;
@@ -75,15 +74,12 @@
this.analysisSession = session {
var synchronousSession =
SynchronousSession(analysisOptions, declaredVariables);
- analysisContext = new RestrictedAnalysisContext(
- synchronousSession,
- sourceFactory,
- );
+ analysisContext = AnalysisContextImpl(synchronousSession, sourceFactory);
_createElementFactory();
load2(targetLibrary);
- inheritanceManager = new InheritanceManager3(analysisContext.typeSystem);
+ inheritanceManager = new InheritanceManager3();
}
/**
@@ -281,10 +277,6 @@
var dartCore = elementFactory.libraryOfUri('dart:core');
var dartAsync = elementFactory.libraryOfUri('dart:async');
- var typeProvider = TypeProviderImpl(dartCore, dartAsync);
- analysisContext.typeProvider = typeProvider;
-
- dartCore.createLoadLibraryFunction(typeProvider);
- dartAsync.createLoadLibraryFunction(typeProvider);
+ elementFactory.createTypeProviders(dartCore, dartAsync);
}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/restricted_analysis_context.dart b/pkg/analyzer/lib/src/dart/analysis/restricted_analysis_context.dart
deleted file mode 100644
index 60b7db7..0000000
--- a/pkg/analyzer/lib/src/dart/analysis/restricted_analysis_context.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2018, 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.
-
-import 'package:analyzer/dart/analysis/declared_variables.dart';
-import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/dart/analysis/session.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/type_system.dart';
-
-/// This class is a temporary step toward migrating Analyzer clients to the
-/// new API. It guards against attempts to use any [AnalysisContext]
-/// functionality (which is task based), except what we intend to expose
-/// through the new API.
-class RestrictedAnalysisContext implements AnalysisContextImpl {
- final SynchronousSession synchronousSession;
-
- @override
- final SourceFactory sourceFactory;
-
- RestrictedAnalysisContext(this.synchronousSession, this.sourceFactory);
-
- @override
- AnalysisOptionsImpl get analysisOptions => synchronousSession.analysisOptions;
-
- @override
- DeclaredVariables get declaredVariables =>
- synchronousSession.declaredVariables;
-
- @override
- TypeProvider get typeProvider => synchronousSession.typeProvider;
-
- @override
- set typeProvider(TypeProvider typeProvider) {
- synchronousSession.typeProvider = typeProvider;
- }
-
- @override
- TypeSystem get typeSystem => synchronousSession.typeSystem;
-
- noSuchMethod(Invocation invocation) {
- return super.noSuchMethod(invocation);
- }
-
- void clearTypeProvider() {
- synchronousSession.clearTypeProvider();
- }
-}
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
index da2e4d0..0011291 100644
--- a/pkg/analyzer/lib/src/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -235,7 +235,7 @@
TypeProvider get typeProvider => unit.declaredElement.context.typeProvider;
@override
- TypeSystem get typeSystem => unit.declaredElement.context.typeSystem;
+ TypeSystemImpl get typeSystem => unit.declaredElement.context.typeSystem;
}
class UnitElementResultImpl extends AnalysisResultImpl
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index f090722..f4139fe 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -17,6 +17,7 @@
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:meta/meta.dart';
/// A concrete implementation of an analysis session.
class AnalysisSessionImpl implements AnalysisSession {
@@ -27,7 +28,7 @@
TypeProvider _typeProvider;
/// The type system being used by the analysis driver.
- TypeSystem _typeSystem;
+ TypeSystemImpl _typeSystem;
/// The URI converter used to convert between URI's and file paths.
UriConverter _uriConverter;
@@ -58,18 +59,28 @@
if (_typeProvider == null) {
LibraryElement coreLibrary = await _driver.getLibraryByUri('dart:core');
LibraryElement asyncLibrary = await _driver.getLibraryByUri('dart:async');
- _typeProvider = new TypeProviderImpl(coreLibrary, asyncLibrary);
+ _typeProvider = new TypeProviderImpl(
+ coreLibrary: coreLibrary,
+ asyncLibrary: asyncLibrary,
+ isNonNullableByDefault: false,
+ );
}
return _typeProvider;
}
@override
- Future<TypeSystem> get typeSystem async {
+ Future<TypeSystemImpl> get typeSystem async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
_checkConsistency();
if (_typeSystem == null) {
- _typeSystem = new Dart2TypeSystem(await typeProvider);
+ var typeProvider = await this.typeProvider;
+ _typeSystem = TypeSystemImpl(
+ implicitCasts: true,
+ isNonNullableByDefault: false,
+ strictInference: false,
+ typeProvider: typeProvider,
+ );
}
return _typeSystem;
}
@@ -200,31 +211,68 @@
final DeclaredVariables declaredVariables;
- TypeProvider _typeProvider;
+ TypeProvider _typeProviderLegacy;
+ TypeProvider _typeProviderNonNullableByDefault;
- TypeSystem _typeSystem;
+ TypeSystemImpl _typeSystemLegacy;
+ TypeSystemImpl _typeSystemNonNullableByDefault;
SynchronousSession(this.analysisOptions, this.declaredVariables);
- TypeProvider get typeProvider => _typeProvider;
+ TypeProvider get typeProvider => _typeProviderLegacy;
- set typeProvider(TypeProvider typeProvider) {
- if (_typeProvider != null) {
- throw StateError('TypeProvider can be set only once.');
- }
- _typeProvider = typeProvider;
+ TypeProvider get typeProviderLegacy {
+ return _typeProviderLegacy;
}
- TypeSystem get typeSystem {
- return _typeSystem ??= Dart2TypeSystem(
- typeProvider,
- implicitCasts: analysisOptions.implicitCasts,
- strictInference: analysisOptions.strictInference,
- );
+ TypeProvider get typeProviderNonNullableByDefault {
+ return _typeProviderNonNullableByDefault;
+ }
+
+ TypeSystemImpl get typeSystem {
+ return typeSystemLegacy;
+ }
+
+ TypeSystemImpl get typeSystemLegacy {
+ return _typeSystemLegacy;
+ }
+
+ TypeSystemImpl get typeSystemNonNullableByDefault {
+ return _typeSystemNonNullableByDefault;
}
void clearTypeProvider() {
- _typeProvider = null;
- _typeSystem = null;
+ _typeProviderLegacy = null;
+ _typeProviderNonNullableByDefault = null;
+
+ _typeSystemLegacy = null;
+ _typeSystemNonNullableByDefault = null;
+ }
+
+ void setTypeProviders({
+ @required TypeProvider legacy,
+ @required TypeProvider nonNullableByDefault,
+ }) {
+ if (_typeProviderLegacy != null ||
+ _typeProviderNonNullableByDefault != null) {
+ throw StateError('TypeProvider(s) can be set only once.');
+ }
+
+ _typeProviderLegacy = legacy;
+ _typeProviderNonNullableByDefault = nonNullableByDefault;
+
+ _typeSystemLegacy = TypeSystemImpl(
+ implicitCasts: analysisOptions.implicitCasts,
+ isNonNullableByDefault: false,
+ strictInference: analysisOptions.strictInference,
+ typeProvider: _typeProviderLegacy,
+ );
+
+ _typeSystemNonNullableByDefault = TypeSystemImpl(
+ implicitCasts: analysisOptions.implicitCasts,
+ isNonNullableByDefault: true,
+ strictInference: analysisOptions.strictInference,
+ typeProvider: _typeProviderNonNullableByDefault,
+ );
}
}
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index 9b2cc48..a4aba0d 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -1030,6 +1030,16 @@
SimpleIdentifier name, Token extendsKeyword, TypeAnnotation bound) =>
new TypeParameterImpl(comment, metadata, name, extendsKeyword, bound);
+ TypeParameter typeParameter2(
+ {Comment comment,
+ List<Annotation> metadata,
+ SimpleIdentifier name,
+ Token extendsKeyword,
+ TypeAnnotation bound,
+ Token varianceKeyword}) =>
+ new TypeParameterImpl(comment, metadata, name, extendsKeyword, bound)
+ ..varianceKeyword = varianceKeyword;
+
@override
TypeParameterList typeParameterList(Token leftBracket,
List<TypeParameter> typeParameters, Token rightBracket) =>
diff --git a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
index 7cd5a86..1f5145f 100644
--- a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
@@ -4,6 +4,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:meta/meta.dart';
/**
@@ -1127,6 +1128,11 @@
@override
void visitTypeParameter(TypeParameter node) {
safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+ // TODO (kallentu) : Clean up TypeParameterImpl casting once variance is
+ // added to the interface.
+ if ((node as TypeParameterImpl).varianceKeyword != null) {
+ sink.write((node as TypeParameterImpl).varianceKeyword.lexeme + ' ');
+ }
safelyVisitNode(node.name);
safelyVisitNodeWithPrefix(" extends ", node.bound);
}
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 95d8752..284ccb1 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -10,6 +10,7 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/to_source_visitor.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
@@ -1019,12 +1020,16 @@
@override
TypeParameter visitTypeParameter(TypeParameter node) =>
- astFactory.typeParameter(
- cloneNode(node.documentationComment),
- cloneNodeList(node.metadata),
- cloneNode(node.name),
- cloneToken(node.extendsKeyword),
- cloneNode(node.bound));
+ // TODO (kallentu) : Clean up TypeParameterImpl and AstFactoryImpl casting
+ // once variance is added to the interface.
+ (astFactory as AstFactoryImpl).typeParameter2(
+ comment: cloneNode(node.documentationComment),
+ metadata: cloneNodeList(node.metadata),
+ name: cloneNode(node.name),
+ extendsKeyword: cloneToken(node.extendsKeyword),
+ bound: cloneNode(node.bound),
+ varianceKeyword:
+ cloneToken((node as TypeParameterImpl).varianceKeyword));
@override
TypeParameterList visitTypeParameterList(TypeParameterList node) =>
@@ -2269,10 +2274,14 @@
@override
bool visitTypeParameter(TypeParameter node) {
TypeParameter other = _other as TypeParameter;
+ // TODO (kallentu) : Clean up TypeParameterImpl casting once variance is
+ // added to the interface.
return isEqualNodes(
node.documentationComment, other.documentationComment) &&
_isEqualNodeLists(node.metadata, other.metadata) &&
isEqualNodes(node.name, other.name) &&
+ isEqualTokens((node as TypeParameterImpl).varianceKeyword,
+ (other as TypeParameterImpl).varianceKeyword) &&
isEqualTokens(node.extendsKeyword, other.extendsKeyword) &&
isEqualNodes(node.bound, other.bound);
}
@@ -5413,10 +5422,14 @@
@override
bool visitTypeParameter(TypeParameter node) {
TypeParameter toNode = this._toNode as TypeParameter;
+ // TODO (kallentu) : Clean up TypeParameterImpl casting once variance is
+ // added to the interface.
return _and(
_isEqualNodes(node.documentationComment, toNode.documentationComment),
_isEqualNodeLists(node.metadata, toNode.metadata),
_isEqualNodes(node.name, toNode.name),
+ _isEqualTokens((node as TypeParameterImpl).varianceKeyword,
+ (toNode as TypeParameterImpl).varianceKeyword),
_isEqualTokens(node.extendsKeyword, toNode.extendsKeyword),
_isEqualNodes(node.bound, toNode.bound));
}
diff --git a/pkg/analyzer/lib/src/dart/constant/compute.dart b/pkg/analyzer/lib/src/dart/constant/compute.dart
index 3fc6ca9..cfef338 100644
--- a/pkg/analyzer/lib/src/dart/constant/compute.dart
+++ b/pkg/analyzer/lib/src/dart/constant/compute.dart
@@ -6,15 +6,15 @@
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/generated/resolver.dart'
- show TypeProvider, TypeSystem;
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
import 'package:analyzer/src/summary/link.dart' as graph
show DependencyWalker, Node;
/// Compute values of the given [constants] with correct ordering.
void computeConstants(
TypeProvider typeProvider,
- TypeSystem typeSystem,
+ TypeSystemImpl typeSystem,
DeclaredVariables declaredVariables,
List<ConstantEvaluationTarget> constants,
ExperimentStatus experimentStatus) {
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 0d81332..7b91b96 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -10,6 +10,7 @@
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -20,7 +21,7 @@
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
/// Instances of the class `ConstantVerifier` traverse an AST structure looking
/// for additional errors and warnings not covered by the parser and resolver.
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index dda42f3..ffae190 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -13,6 +13,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
@@ -26,8 +27,7 @@
import 'package:analyzer/src/generated/engine.dart'
show AnalysisEngine, RecordingErrorListener;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/type_system.dart'
- show Dart2TypeSystem, TypeSystem;
+import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
import 'package:analyzer/src/task/api/model.dart';
/// Helper class encapsulating the methods for evaluating constants and
@@ -90,7 +90,13 @@
: typeProvider = typeProvider,
validator =
validator ?? new ConstantEvaluationValidator_ForProduction(),
- typeSystem = typeSystem ?? new Dart2TypeSystem(typeProvider),
+ typeSystem = typeSystem ??
+ TypeSystemImpl(
+ implicitCasts: true,
+ isNonNullableByDefault: false,
+ strictInference: false,
+ typeProvider: typeProvider,
+ ),
experimentStatus = experimentStatus ?? new ExperimentStatus();
/// Check that the arguments to a call to fromEnvironment() are correct. The
@@ -1127,7 +1133,7 @@
ParameterizedType thenType = thenResult.type;
ParameterizedType elseType = elseResult.type;
return new DartObjectImpl.validWithUnknownValue(
- typeSystem.getLeastUpperBound(thenType, elseType) as ParameterizedType);
+ typeSystem.leastUpperBound(thenType, elseType) as ParameterizedType);
}
@override
@@ -1260,14 +1266,16 @@
SimpleIdentifier prefixNode = node.prefix;
Element prefixElement = prefixNode.staticElement;
// String.length
- if (prefixElement is! PrefixElement && prefixElement is! ClassElement) {
+ if (prefixElement is! PrefixElement &&
+ prefixElement is! ClassElement &&
+ prefixElement is! ExtensionElement) {
DartObjectImpl prefixResult = prefixNode.accept(this);
if (_isStringLength(prefixResult, node.identifier)) {
return prefixResult.stringLength(_typeProvider);
}
}
// importPrefix.CONST
- if (prefixElement is! PrefixElement) {
+ if (prefixElement is! PrefixElement && prefixElement is! ExtensionElement) {
DartObjectImpl prefixResult = prefixNode.accept(this);
if (prefixResult == null) {
// The error has already been reported.
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index 6658568..c3bbde2 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -8,10 +8,10 @@
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
/// The state of an object representing a boolean value.
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index da91d96..3de7141 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -17,6 +17,7 @@
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
import 'package:analyzer/src/generated/engine.dart'
@@ -58,9 +59,6 @@
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created class element to have the given [name].
- AbstractClassElementImpl.forNode(Identifier name) : super.forNode(name);
-
/// Initialize using the given serialized information.
AbstractClassElementImpl.forSerialized(
CompilationUnitElementImpl enclosingUnit)
@@ -456,9 +454,6 @@
Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created class element to have the given [name].
- ClassElementImpl.forNode(Identifier name) : super.forNode(name);
-
@override
List<PropertyAccessorElement> get accessors {
if (_accessors != null) return _accessors;
@@ -1787,9 +1782,6 @@
ConstFieldElementImpl.forLinkedNode(
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
-
- /// Initialize a newly created field element to have the given [name].
- ConstFieldElementImpl.forNode(Identifier name) : super.forNode(name);
}
/// A field element representing an enum constant.
@@ -1937,10 +1929,6 @@
/// Initialize a newly created local variable element to have the given [name]
/// and [offset].
ConstLocalVariableElementImpl(String name, int offset) : super(name, offset);
-
- /// Initialize a newly created local variable element to have the given
- /// [name].
- ConstLocalVariableElementImpl.forNode(Identifier name) : super.forNode(name);
}
/// A concrete implementation of a [ConstructorElement].
@@ -1976,9 +1964,6 @@
Reference reference, ConstructorDeclaration linkedNode)
: super.forLinkedNode(enclosingClass, reference, linkedNode);
- /// Initialize a newly created constructor element to have the given [name].
- ConstructorElementImpl.forNode(Identifier name) : super.forNode(name);
-
/// Return the constant initializers for this element, which will be empty if
/// there are no initializers, or `null` if there was an error in the source.
List<ConstructorInitializer> get constantInitializers {
@@ -2223,11 +2208,6 @@
ConstTopLevelVariableElementImpl.forLinkedNode(
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
-
- /// Initialize a newly created top-level variable element to have the given
- /// [name].
- ConstTopLevelVariableElementImpl.forNode(Identifier name)
- : super.forNode(name);
}
/// Mixin used by elements that represent constant variables and have
@@ -2300,10 +2280,6 @@
DefaultFieldFormalParameterElementImpl.forLinkedNode(
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
-
- /// Initialize a newly created parameter element to have the given [name].
- DefaultFieldFormalParameterElementImpl.forNode(Identifier name)
- : super.forNode(name);
}
/// A [ParameterElement] for parameters that have an initializer.
@@ -2317,9 +2293,6 @@
DefaultParameterElementImpl.forLinkedNode(
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
-
- /// Initialize a newly created parameter element to have the given [name].
- DefaultParameterElementImpl.forNode(Identifier name) : super.forNode(name);
}
/// The synthetic element representing the declaration of the type `dynamic`.
@@ -2666,10 +2639,6 @@
reference?.element ??= this;
}
- /// Initialize a newly created element to have the given [name].
- ElementImpl.forNode(Identifier name)
- : this(name == null ? "" : name.name, name == null ? -1 : name.offset);
-
/// Initialize from serialized information.
ElementImpl.forSerialized(this._enclosingElement)
: reference = null,
@@ -3317,9 +3286,6 @@
Reference reference, EnumDeclaration linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created class element to have the given [name].
- EnumElementImpl.forNode(Identifier name) : super.forNode(name);
-
@override
List<PropertyAccessorElement> get accessors {
if (_accessors == null) {
@@ -3567,9 +3533,6 @@
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created executable element to have the given [name].
- ExecutableElementImpl.forNode(Identifier name) : super.forNode(name);
-
/// Set whether this executable element's body is asynchronous.
void set asynchronous(bool isAsynchronous) {
setModifier(Modifier.ASYNCHRONOUS, isAsynchronous);
@@ -3980,9 +3943,6 @@
Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created extension element to have the given [name].
- ExtensionElementImpl.forNode(Identifier name) : super.forNode(name);
-
@override
List<PropertyAccessorElement> get accessors {
if (_accessors != null) {
@@ -4333,9 +4293,6 @@
return FieldElementImpl.forLinkedNode(enclosing, reference, linkedNode);
}
- /// Initialize a newly created field element to have the given [name].
- FieldElementImpl.forNode(Identifier name) : super.forNode(name);
-
@override
FieldElement get declaration => this;
@@ -4395,10 +4352,6 @@
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created parameter element to have the given [name].
- FieldFormalParameterElementImpl.forNode(Identifier name)
- : super.forNode(name);
-
@override
FieldElement get field {
if (_field == null) {
@@ -4450,9 +4403,6 @@
FunctionDeclaration linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created function element to have the given [name].
- FunctionElementImpl.forNode(Identifier name) : super.forNode(name);
-
/// Initialize a newly created function element to have no name and the given
/// [nameOffset]. This is used for function expressions, that have no name.
FunctionElementImpl.forOffset(int nameOffset) : super("", nameOffset);
@@ -4639,7 +4589,7 @@
void appendTo(StringBuffer buffer) {
DartType type = returnType;
if (type is TypeImpl) {
- type.appendTo(buffer, new HashSet<TypeImpl>());
+ type.appendTo(buffer);
buffer.write(' Function');
} else {
buffer.write('Function');
@@ -4698,9 +4648,6 @@
AstNode linkedNode)
: super.forLinkedNode(enclosingUnit, reference, linkedNode);
- /// Initialize a newly created type alias element to have the given [name].
- GenericTypeAliasElementImpl.forNode(Identifier name) : super.forNode(name);
-
@override
int get codeLength {
if (linkedNode != null) {
@@ -5197,14 +5144,6 @@
this._onSwitchMember)
: super(name, nameOffset);
- /// Initialize a newly created label element to have the given [name].
- /// [_onSwitchStatement] should be `true` if this label is associated with a
- /// `switch` statement and [_onSwitchMember] should be `true` if this label is
- /// associated with a `switch` member.
- LabelElementImpl.forNode(
- Identifier name, this._onSwitchStatement, this._onSwitchMember)
- : super.forNode(name);
-
@override
String get displayName => name;
@@ -5234,6 +5173,12 @@
@override
final AnalysisSession session;
+ @override
+ TypeProviderImpl typeProvider;
+
+ @override
+ TypeSystemImpl typeSystem;
+
/// The context of the defining unit.
final LinkedUnitContext linkedContext;
@@ -5307,14 +5252,6 @@
LibraryResolutionCapability.constantExpressions, true);
}
- /// Initialize a newly created library element in the given [context] to have
- /// the given [name].
- LibraryElementImpl.forNode(this.context, this.session, LibraryIdentifier name,
- this.isNonNullableByDefault)
- : nameLength = name != null ? name.length : 0,
- linkedContext = null,
- super.forNode(name);
-
@override
int get codeLength {
CompilationUnitElement unit = _definingCompilationUnit;
@@ -5810,10 +5747,6 @@
/// [offset].
LocalVariableElementImpl(String name, int offset) : super(name, offset);
- /// Initialize a newly created local variable element to have the given
- /// [name].
- LocalVariableElementImpl.forNode(Identifier name) : super.forNode(name);
-
@override
String get identifier {
return '$name$nameOffset';
@@ -5854,9 +5787,6 @@
Reference reference, MethodDeclaration linkedNode)
: super.forLinkedNode(enclosingClass, reference, linkedNode);
- /// Initialize a newly created method element to have the given [name].
- MethodElementImpl.forNode(Identifier name) : super.forNode(name);
-
@override
MethodElement get declaration => this;
@@ -5956,9 +5886,6 @@
Reference reference, MixinDeclaration linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created class element to have the given [name].
- MixinElementImpl.forNode(Identifier name) : super.forNode(name);
-
@override
bool get isAbstract => true;
@@ -6399,10 +6326,6 @@
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created variable element to have the given [name].
- NonParameterVariableElementImpl.forNode(Identifier name)
- : super.forNode(name);
-
@override
int get codeLength {
if (linkedNode != null) {
@@ -6544,9 +6467,6 @@
}
}
- /// Initialize a newly created parameter element to have the given [name].
- ParameterElementImpl.forNode(Identifier name) : super.forNode(name);
-
/// Creates a synthetic parameter with [name], [type] and [kind].
factory ParameterElementImpl.synthetic(
String name, DartType type, ParameterKind kind) {
@@ -7002,9 +6922,6 @@
ElementImpl enclosing, Reference reference, SimpleIdentifier linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created prefix element to have the given [name].
- PrefixElementImpl.forNode(Identifier name) : super.forNode(name);
-
@override
String get displayName => name;
@@ -7055,10 +6972,6 @@
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created property accessor element to have the given
- /// [name].
- PropertyAccessorElementImpl.forNode(Identifier name) : super.forNode(name);
-
/// Initialize a newly created synthetic property accessor element to be
/// associated with the given [variable].
PropertyAccessorElementImpl.forVariable(PropertyInducingElementImpl variable,
@@ -7306,9 +7219,6 @@
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created element to have the given [name].
- PropertyInducingElementImpl.forNode(Identifier name) : super.forNode(name);
-
@override
bool get isConstantEvaluated => true;
@@ -7461,9 +7371,8 @@
);
}
- /// Initialize a newly created top-level variable element to have the given
- /// [name].
- TopLevelVariableElementImpl.forNode(Identifier name) : super.forNode(name);
+ @override
+ TopLevelVariableElement get declaration => this;
@override
bool get isStatic => true;
@@ -7503,10 +7412,6 @@
ElementImpl enclosing, Reference reference, TypeParameter linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created type parameter element to have the given
- /// [name].
- TypeParameterElementImpl.forNode(Identifier name) : super.forNode(name);
-
/// Initialize a newly created synthetic type parameter element to have the
/// given [name], and with [synthetic] set to true.
TypeParameterElementImpl.synthetic(String name) : super(name, -1) {
@@ -7566,6 +7471,13 @@
@override
String get displayName => name;
+ bool get isLegacyCovariant {
+ if (linkedNode != null) {
+ return linkedContext.getTypeParameterVariance(linkedNode) == null;
+ }
+ return _variance == null;
+ }
+
@override
ElementKind get kind => ElementKind.TYPE_PARAMETER;
@@ -7601,12 +7513,21 @@
_type = type;
}
- Variance get variance => _variance ?? Variance.covariant;
+ Variance get variance {
+ if (_variance != null) return _variance;
+
+ if (linkedNode != null) {
+ var varianceKeyword = linkedContext.getTypeParameterVariance(linkedNode);
+ if (varianceKeyword != null) {
+ _variance = Variance.fromKeywordString(varianceKeyword.lexeme);
+ }
+ }
+
+ return _variance ?? Variance.covariant;
+ }
void set variance(Variance newVariance) => _variance = newVariance;
- bool get isLegacyCovariant => _variance == null;
-
@override
bool operator ==(Object other) {
if (identical(other, this)) {
@@ -7627,6 +7548,9 @@
@override
void appendTo(StringBuffer buffer) {
+ if (!isLegacyCovariant) {
+ buffer.write(variance.toKeywordString() + " ");
+ }
buffer.write(displayName);
if (bound != null) {
buffer.write(" extends ");
@@ -7748,9 +7672,6 @@
ElementImpl enclosing, Reference reference, AstNode linkedNode)
: super.forLinkedNode(enclosing, reference, linkedNode);
- /// Initialize a newly created variable element to have the given [name].
- VariableElementImpl.forNode(Identifier name) : super.forNode(name);
-
/// Initialize using the given serialized information.
VariableElementImpl.forSerialized(ElementImpl enclosingElement)
: super.forSerialized(enclosingElement);
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index 8f3af4e..c80aa0f 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -4,7 +4,8 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/type_system.dart';
+import 'package:analyzer/dart/element/type_system.dart';
+import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
import 'package:analyzer/src/generated/utilities_general.dart';
/// Description of a failure to find a valid override from superinterfaces.
@@ -32,8 +33,6 @@
class InheritanceManager3 {
static final _noSuchMethodName = Name(null, 'noSuchMethod');
- final TypeSystem _typeSystem;
-
/// Cached instance interfaces for [InterfaceType].
final Map<InterfaceType, Interface> _interfaces = {};
@@ -41,7 +40,7 @@
/// self-referencing cycles.
final Set<ClassElement> _processingClasses = new Set<ClassElement>();
- InheritanceManager3(this._typeSystem);
+ InheritanceManager3([@deprecated TypeSystem typeSystem]);
/// Return the most specific signature of the member with the given [name]
/// that the [type] inherits from the mixins, superclasses, or interfaces;
@@ -69,6 +68,7 @@
if (interface._inheritedMap == null) {
interface._inheritedMap = {};
_findMostSpecificFromNamedCandidates(
+ type.element.library.typeSystem,
interface._inheritedMap,
interface._overridden,
);
@@ -94,6 +94,8 @@
return Interface._empty;
}
+ var typeSystem = classElement.library.typeSystem;
+
Map<Name, List<ExecutableElement>> namedCandidates = {};
List<Map<Name, ExecutableElement>> superImplemented = [];
Map<Name, ExecutableElement> declared;
@@ -123,7 +125,11 @@
// `mixin M on S1, S2 {}` can call using `super` any instance member
// from its superclass constraints, whether it is abstract or concrete.
var superClass = <Name, ExecutableElement>{};
- _findMostSpecificFromNamedCandidates(superClass, superClassCandidates);
+ _findMostSpecificFromNamedCandidates(
+ typeSystem,
+ superClass,
+ superClassCandidates,
+ );
superImplemented.add(superClass);
} else {
if (type.superclass != null) {
@@ -172,6 +178,7 @@
// signature becomes the signature of the class's interface.
Map<Name, ExecutableElement> map = new Map.of(declared);
List<Conflict> conflicts = _findMostSpecificFromNamedCandidates(
+ typeSystem,
map,
namedCandidates,
);
@@ -340,6 +347,7 @@
/// such single most specific signature (i.e. no valid override), then add a
/// new conflict description.
List<Conflict> _findMostSpecificFromNamedCandidates(
+ TypeSystemImpl typeSystem,
Map<Name, ExecutableElement> map,
Map<Name, List<ExecutableElement>> namedCandidates) {
List<Conflict> conflicts;
@@ -374,7 +382,7 @@
validOverride = candidates[i];
for (var j = 0; j < candidates.length; j++) {
var candidate = candidates[j];
- if (!_typeSystem.isOverrideSubtypeOf(
+ if (!typeSystem.isOverrideSubtypeOf(
validOverride.type, candidate.type)) {
validOverride = null;
break;
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index e349274..a086001 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
@@ -28,7 +29,8 @@
ConstructorMember(
ConstructorElement declaration,
MapSubstitution substitution,
- ) : super(declaration, substitution);
+ bool isLegacy,
+ ) : super(declaration, substitution, isLegacy);
@deprecated
@override
@@ -81,7 +83,7 @@
substitution = _substitution;
}
- return ConstructorMember(declaration, substitution);
+ return ConstructorMember(declaration, substitution, false);
}
@override
@@ -137,6 +139,7 @@
return ConstructorMember(
constructor,
Substitution.fromInterfaceType(definingType),
+ false,
);
}
}
@@ -156,7 +159,8 @@
ExecutableMember(
ExecutableElement declaration,
MapSubstitution substitution,
- ) : super(declaration, substitution);
+ bool isLegacy,
+ ) : super(declaration, substitution, isLegacy);
@deprecated
@override
@@ -196,9 +200,9 @@
List<ParameterElement> get parameters {
return declaration.parameters.map((p) {
if (p is FieldFormalParameterElement) {
- return FieldFormalParameterMember(p, _substitution);
+ return FieldFormalParameterMember(p, _substitution, isLegacy);
}
- return ParameterMember(p, _substitution);
+ return ParameterMember(p, _substitution, isLegacy);
}).toList();
}
@@ -209,7 +213,9 @@
FunctionType get type {
if (_type != null) return _type;
- return _type = _substitution.substituteType(declaration.type);
+ _type = _substitution.substituteType(declaration.type);
+ _type = _toLegacyType(_type);
+ return _type;
}
@override
@@ -232,6 +238,10 @@
ExecutableElement element,
MapSubstitution substitution,
) {
+ if (element == null) {
+ return null;
+ }
+
var combined = substitution;
if (element is ExecutableMember) {
ExecutableMember member = element;
@@ -247,11 +257,11 @@
}
if (element is ConstructorElement) {
- return ConstructorMember(element, combined);
+ return ConstructorMember(element, combined, false);
} else if (element is MethodElement) {
- return MethodMember(element, combined);
+ return MethodMember(element, combined, false);
} else if (element is PropertyAccessorElement) {
- return PropertyAccessorMember(element, combined);
+ return PropertyAccessorMember(element, combined, false);
} else {
throw UnimplementedError('(${element.runtimeType}) $element');
}
@@ -271,7 +281,8 @@
FieldFormalParameterMember(
FieldFormalParameterElement declaration,
MapSubstitution substitution,
- ) : super(declaration, substitution);
+ bool isLegacy,
+ ) : super(declaration, substitution, isLegacy);
@override
FieldElement get field {
@@ -280,7 +291,7 @@
return null;
}
- return FieldMember(field, _substitution);
+ return FieldMember(field, _substitution, isLegacy);
}
@override
@@ -303,7 +314,8 @@
FieldMember(
FieldElement declaration,
MapSubstitution substitution,
- ) : super(declaration, substitution);
+ bool isLegacy,
+ ) : super(declaration, substitution, isLegacy);
@deprecated
@override
@@ -321,7 +333,7 @@
if (baseGetter == null) {
return null;
}
- return PropertyAccessorMember(baseGetter, _substitution);
+ return PropertyAccessorMember(baseGetter, _substitution, isLegacy);
}
@override
@@ -336,7 +348,7 @@
if (baseSetter == null) {
return null;
}
- return PropertyAccessorMember(baseSetter, _substitution);
+ return PropertyAccessorMember(baseSetter, _substitution, isLegacy);
}
@override
@@ -359,6 +371,7 @@
return FieldMember(
field,
Substitution.fromInterfaceType(definingType),
+ false,
);
}
@@ -369,7 +382,26 @@
if (substitution.map.isEmpty) {
return element;
}
- return FieldMember(element, substitution);
+ return FieldMember(element, substitution, false);
+ }
+}
+
+class FunctionMember extends ExecutableMember implements FunctionElement {
+ FunctionMember(
+ ExecutableElement declaration,
+ MapSubstitution substitution,
+ bool isLegacy,
+ ) : super(declaration, substitution, isLegacy);
+
+ @override
+ FunctionElement get declaration => super.declaration;
+
+ @override
+ bool get isEntryPoint => declaration.isEntryPoint;
+
+ @override
+ T accept<T>(ElementVisitor<T> visitor) {
+ return visitor.visitFunctionElement(this);
}
}
@@ -389,10 +421,15 @@
final MapSubstitution _substitution;
/**
+ * If `true`, then this is a legacy view on a NNBD element.
+ */
+ final bool isLegacy;
+
+ /**
* Initialize a newly created element to represent a member, based on the
* [declaration], and applied [_substitution].
*/
- Member(this._declaration, this._substitution) {
+ Member(this._declaration, this._substitution, this.isLegacy) {
if (_declaration is Member) {
throw StateError('Members must be created from a declarations.');
}
@@ -417,6 +454,9 @@
String get documentationComment => _declaration.documentationComment;
@override
+ Element get enclosingElement => _declaration.enclosingElement;
+
+ @override
bool get hasAlwaysThrows => _declaration.hasAlwaysThrows;
@override
@@ -539,6 +579,78 @@
void visitChildren(ElementVisitor visitor) {
// There are no children to visit
}
+
+ /// If this member is a legacy view, erase nullability from the [type].
+ /// Otherwise, return the type unchanged.
+ DartType _toLegacyType(DartType type) {
+ if (isLegacy) {
+ return NullabilityEliminator.perform(type);
+ } else {
+ return type;
+ }
+ }
+
+ /// Return the legacy view of them [element], so that all its types, and
+ /// types of any elements that are returned from it, are legacy types.
+ ///
+ /// If the [element] is declared in a legacy library, return it unchanged.
+ static Element legacy(Element element) {
+ if (element is ConstructorElement) {
+ if (!element.library.isNonNullableByDefault) {
+ return element;
+ } else if (element is Member) {
+ var member = element as Member;
+ return ConstructorMember(
+ member._declaration,
+ member._substitution,
+ true,
+ );
+ } else {
+ return ConstructorMember(element, Substitution.empty, true);
+ }
+ } else if (element is FunctionElement) {
+ if (!element.library.isNonNullableByDefault) {
+ return element;
+ } else if (element is Member) {
+ var member = element as Member;
+ return FunctionMember(
+ member._declaration,
+ member._substitution,
+ true,
+ );
+ } else {
+ return FunctionMember(element, Substitution.empty, true);
+ }
+ } else if (element is MethodElement) {
+ if (!element.library.isNonNullableByDefault) {
+ return element;
+ } else if (element is Member) {
+ var member = element as Member;
+ return MethodMember(
+ member._declaration,
+ member._substitution,
+ true,
+ );
+ } else {
+ return MethodMember(element, Substitution.empty, true);
+ }
+ } else if (element is PropertyAccessorElement) {
+ if (!element.library.isNonNullableByDefault) {
+ return element;
+ } else if (element is Member) {
+ var member = element as Member;
+ return PropertyAccessorMember(
+ member._declaration,
+ member._substitution,
+ true,
+ );
+ } else {
+ return PropertyAccessorMember(element, Substitution.empty, true);
+ }
+ } else {
+ return element;
+ }
+ }
}
/**
@@ -553,7 +665,8 @@
MethodMember(
MethodElement declaration,
MapSubstitution substitution,
- ) : super(declaration, substitution);
+ bool isLegacy,
+ ) : super(declaration, substitution, isLegacy);
@deprecated
@override
@@ -648,6 +761,7 @@
return MethodMember(
method,
Substitution.fromInterfaceType(definingType),
+ false,
);
}
@@ -658,7 +772,7 @@
if (substitution.map.isEmpty) {
return element;
}
- return MethodMember(element, substitution);
+ return MethodMember(element, substitution, false);
}
}
@@ -676,7 +790,8 @@
ParameterMember(
ParameterElement declaration,
MapSubstitution substitution,
- ) : super(declaration, substitution);
+ bool isLegacy,
+ ) : super(declaration, substitution, isLegacy);
@deprecated
@override
@@ -771,7 +886,8 @@
PropertyAccessorMember(
PropertyAccessorElement declaration,
MapSubstitution substitution,
- ) : super(declaration, substitution);
+ bool isLegacy,
+ ) : super(declaration, substitution, isLegacy);
@deprecated
@override
@@ -782,6 +898,7 @@
return PropertyAccessorMember(
declaration.correspondingGetter,
_substitution,
+ isLegacy,
);
}
@@ -790,6 +907,7 @@
return PropertyAccessorMember(
declaration.correspondingSetter,
_substitution,
+ isLegacy,
);
}
@@ -808,9 +926,12 @@
@override
PropertyInducingElement get variable {
+ // TODO
PropertyInducingElement variable = declaration.variable;
if (variable is FieldElement) {
- return FieldMember(variable, _substitution);
+ return FieldMember(variable, _substitution, isLegacy);
+ } else if (variable is TopLevelVariableElement) {
+ return TopLevelVariableMember(variable, _substitution, isLegacy);
}
return variable;
}
@@ -866,10 +987,46 @@
return PropertyAccessorMember(
accessor,
Substitution.fromInterfaceType(definingType),
+ false,
);
}
}
+class TopLevelVariableMember extends VariableMember
+ implements TopLevelVariableElement {
+ TopLevelVariableMember(
+ VariableElement declaration,
+ MapSubstitution substitution,
+ bool isLegacy,
+ ) : super(declaration, substitution, isLegacy);
+
+ @override
+ TopLevelVariableElement get declaration => _declaration;
+
+ @override
+ PropertyAccessorElement get getter {
+ var baseGetter = declaration.getter;
+ if (baseGetter == null) {
+ return null;
+ }
+ return PropertyAccessorMember(baseGetter, _substitution, isLegacy);
+ }
+
+ @override
+ PropertyAccessorElement get setter {
+ var baseSetter = declaration.setter;
+ if (baseSetter == null) {
+ return null;
+ }
+ return PropertyAccessorMember(baseSetter, _substitution, isLegacy);
+ }
+
+ @override
+ T accept<T>(ElementVisitor<T> visitor) {
+ return visitor.visitTopLevelVariableElement(this);
+ }
+}
+
/**
* A type parameter defined inside of another parameterized type, where the
* values of the enclosing type parameters are known.
@@ -891,7 +1048,7 @@
TypeParameterMember(TypeParameterElement declaration,
MapSubstitution substitution, this._bound)
- : super(declaration, substitution) {
+ : super(declaration, substitution, false) {
_type = TypeParameterTypeImpl(this);
}
@@ -993,8 +1150,11 @@
* Initialize a newly created element to represent a variable, based on the
* [declaration], with applied [substitution].
*/
- VariableMember(VariableElement declaration, MapSubstitution substitution)
- : super(declaration, substitution);
+ VariableMember(
+ VariableElement declaration,
+ MapSubstitution substitution,
+ bool isLegacy,
+ ) : super(declaration, substitution, isLegacy);
@deprecated
@override
@@ -1038,7 +1198,9 @@
DartType get type {
if (_type != null) return _type;
- return _type = _substitution.substituteType(declaration.type);
+ _type = _substitution.substituteType(declaration.type);
+ _type = _toLegacyType(_type);
+ return _type;
}
@override
diff --git a/pkg/analyzer/lib/src/dart/element/nullability_eliminator.dart b/pkg/analyzer/lib/src/dart/element/nullability_eliminator.dart
index c1485e2..fa1dc26 100644
--- a/pkg/analyzer/lib/src/dart/element/nullability_eliminator.dart
+++ b/pkg/analyzer/lib/src/dart/element/nullability_eliminator.dart
@@ -9,6 +9,7 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/element/type_visitor.dart';
+import 'package:analyzer/src/generated/type_system.dart';
class NullabilityEliminator extends DartTypeVisitor<DartType> {
int _counter = 0;
@@ -96,6 +97,11 @@
}
@override
+ DartType visitUnknownInferredType(UnknownInferredType type) {
+ return type;
+ }
+
+ @override
DartType visitVoidType(VoidType type) {
return type;
}
@@ -126,8 +132,13 @@
var freshElements = List<TypeParameterElement>(elements.length);
for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ var element = elements[i] as TypeParameterElementImpl;
var freshElement = TypeParameterElementImpl(element.name, -1);
+ if (!element.isLegacyCovariant) {
+ freshElement.variance = element.variance;
+ }
freshElement.bound = freshBounds[i];
freshElements[i] = freshElement;
}
@@ -152,6 +163,10 @@
/// return a new type with legacy nullability suffixes. Otherwise return the
/// original instance.
static T perform<T extends DartType>(T type) {
+ if (type == null) {
+ return type;
+ }
+
return NullabilityEliminator().visit(type);
}
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 920a511..14581cc 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -13,7 +13,7 @@
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/generated/engine.dart'
show AnalysisContext, AnalysisEngine;
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:meta/meta.dart';
@@ -149,7 +149,7 @@
// Function types have an empty name when they are defined implicitly by
// either a closure or as part of a parameter declaration.
StringBuffer buffer = new StringBuffer();
- appendTo(buffer, new Set.identity());
+ appendTo(buffer);
if (nullabilitySuffix == NullabilitySuffix.question) {
buffer.write('?');
}
@@ -295,71 +295,68 @@
}
@override
- void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
- {bool withNullability = false}) {
+ void appendTo(StringBuffer buffer, {bool withNullability = false}) {
// TODO(paulberry): eliminate code duplication with
// _ElementWriter.writeType. See issue #35818.
- if (visitedTypes.add(this)) {
- if (typeFormals.isNotEmpty) {
- StringBuffer typeParametersBuffer = StringBuffer();
- // To print a type with type variables, first make sure we have unique
- // variable names to print.
- var freeVariables = <TypeParameterElement>{};
- _freeVariablesInFunctionType(this, freeVariables);
+ if (typeFormals.isNotEmpty) {
+ StringBuffer typeParametersBuffer = StringBuffer();
+ // To print a type with type variables, first make sure we have unique
+ // variable names to print.
+ var freeVariables = <TypeParameterElement>{};
+ _freeVariablesInFunctionType(this, freeVariables);
- var namesToAvoid = <String>{};
- for (TypeParameterElement arg in freeVariables) {
- namesToAvoid.add(arg.displayName);
- }
-
- List<DartType> instantiateTypeArgs = <DartType>[];
- List<TypeParameterElement> variables = <TypeParameterElement>[];
- typeParametersBuffer.write('<');
- for (TypeParameterElement e in typeFormals) {
- if (e != typeFormals[0]) {
- typeParametersBuffer.write(', ');
- }
- String name = e.name;
- int counter = 0;
- while (!namesToAvoid.add(name)) {
- // Unicode subscript-zero is U+2080, zero is U+0030. Other digits
- // are sequential from there. Thus +0x2050 will get us the subscript.
- String subscript = new String.fromCharCodes(
- counter.toString().codeUnits.map((n) => n + 0x2050));
-
- name = e.name + subscript;
- counter++;
- }
- TypeParameterTypeImpl t = new TypeParameterTypeImpl(
- new TypeParameterElementImpl(name, -1),
- nullabilitySuffix: NullabilitySuffix.none);
- t.appendTo(typeParametersBuffer, visitedTypes,
- withNullability: withNullability);
- instantiateTypeArgs.add(t);
- variables.add(e);
- if (e.bound != null) {
- typeParametersBuffer.write(' extends ');
- TypeImpl renamed =
- Substitution.fromPairs(variables, instantiateTypeArgs)
- .substituteType(e.bound);
- renamed.appendTo(typeParametersBuffer, visitedTypes,
- withNullability: withNullability);
- }
- }
- typeParametersBuffer.write('>');
-
- // Instantiate it and print the resulting type.
- this.instantiate(instantiateTypeArgs)._appendToWithTypeParameters(
- buffer,
- visitedTypes,
- withNullability,
- typeParametersBuffer.toString());
- } else {
- _appendToWithTypeParameters(buffer, visitedTypes, withNullability, '');
+ var namesToAvoid = <String>{};
+ for (TypeParameterElement arg in freeVariables) {
+ namesToAvoid.add(arg.displayName);
}
- visitedTypes.remove(this);
+
+ List<DartType> instantiateTypeArgs = <DartType>[];
+ List<TypeParameterElement> variables = <TypeParameterElement>[];
+ typeParametersBuffer.write('<');
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ for (TypeParameterElementImpl e in typeFormals) {
+ if (e != typeFormals[0]) {
+ typeParametersBuffer.write(', ');
+ }
+
+ if (!e.isLegacyCovariant) {
+ typeParametersBuffer.write(e.variance.toKeywordString() + ' ');
+ }
+
+ String name = e.name;
+ int counter = 0;
+ while (!namesToAvoid.add(name)) {
+ // Unicode subscript-zero is U+2080, zero is U+0030. Other digits
+ // are sequential from there. Thus +0x2050 will get us the subscript.
+ String subscript = new String.fromCharCodes(
+ counter.toString().codeUnits.map((n) => n + 0x2050));
+
+ name = e.name + subscript;
+ counter++;
+ }
+ TypeParameterTypeImpl t = new TypeParameterTypeImpl(
+ new TypeParameterElementImpl(name, -1),
+ nullabilitySuffix: NullabilitySuffix.none);
+ t.appendTo(typeParametersBuffer, withNullability: withNullability);
+ instantiateTypeArgs.add(t);
+ variables.add(e);
+ if (e.bound != null) {
+ typeParametersBuffer.write(' extends ');
+ TypeImpl renamed =
+ Substitution.fromPairs(variables, instantiateTypeArgs)
+ .substituteType(e.bound);
+ renamed.appendTo(typeParametersBuffer,
+ withNullability: withNullability);
+ }
+ }
+ typeParametersBuffer.write('>');
+
+ // Instantiate it and print the resulting type.
+ this.instantiate(instantiateTypeArgs)._appendToWithTypeParameters(
+ buffer, withNullability, typeParametersBuffer.toString());
} else {
- buffer.write('<recursive>');
+ _appendToWithTypeParameters(buffer, withNullability, '');
}
}
@@ -461,8 +458,8 @@
);
}
- void _appendToWithTypeParameters(StringBuffer buffer,
- Set<TypeImpl> visitedTypes, bool withNullability, String typeParameters) {
+ void _appendToWithTypeParameters(
+ StringBuffer buffer, bool withNullability, String typeParameters) {
List<DartType> normalParameterTypes = this.normalParameterTypes;
List<DartType> optionalParameterTypes = this.optionalParameterTypes;
DartType returnType = this.returnType;
@@ -471,7 +468,7 @@
buffer.write('null');
} else {
(returnType as TypeImpl)
- .appendTo(buffer, visitedTypes, withNullability: withNullability);
+ .appendTo(buffer, withNullability: withNullability);
}
buffer.write(' Function');
buffer.write(typeParameters);
@@ -496,8 +493,7 @@
if (normalParameterTypes.isNotEmpty) {
for (DartType type in normalParameterTypes) {
writeSeparator();
- (type as TypeImpl)
- .appendTo(buffer, visitedTypes, withNullability: withNullability);
+ (type as TypeImpl).appendTo(buffer, withNullability: withNullability);
}
}
if (optionalParameterTypes.isNotEmpty) {
@@ -505,8 +501,7 @@
buffer.write('[');
for (DartType type in optionalParameterTypes) {
writeSeparator();
- (type as TypeImpl)
- .appendTo(buffer, visitedTypes, withNullability: withNullability);
+ (type as TypeImpl).appendTo(buffer, withNullability: withNullability);
}
buffer.write(']');
needsComma = true;
@@ -524,7 +519,7 @@
buffer.write(parameter.name);
buffer.write(': ');
(parameter.type as TypeImpl)
- .appendTo(buffer, visitedTypes, withNullability: withNullability);
+ .appendTo(buffer, withNullability: withNullability);
}
buffer.write('}');
needsComma = true;
@@ -779,7 +774,9 @@
TypeParameterElementImpl pFresh =
new TypeParameterElementImpl.synthetic(p2.name);
- DartType variableFresh = new TypeParameterTypeImpl(pFresh);
+ DartType variableFresh = pFresh.instantiate(
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
variables1.add(p1);
variables2.add(p2);
@@ -1179,28 +1176,22 @@
}
@override
- void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
- {bool withNullability = false}) {
- if (visitedTypes.add(this)) {
- buffer.write(name);
- int argumentCount = typeArguments.length;
- if (argumentCount > 0) {
- buffer.write("<");
- for (int i = 0; i < argumentCount; i++) {
- if (i > 0) {
- buffer.write(", ");
- }
- (typeArguments[i] as TypeImpl)
- .appendTo(buffer, visitedTypes, withNullability: withNullability);
+ void appendTo(StringBuffer buffer, {bool withNullability = false}) {
+ buffer.write(name);
+ int argumentCount = typeArguments.length;
+ if (argumentCount > 0) {
+ buffer.write("<");
+ for (int i = 0; i < argumentCount; i++) {
+ if (i > 0) {
+ buffer.write(", ");
}
- buffer.write(">");
+ (typeArguments[i] as TypeImpl)
+ .appendTo(buffer, withNullability: withNullability);
}
- if (withNullability) {
- _appendNullability(buffer);
- }
- visitedTypes.remove(this);
- } else {
- buffer.write('<recursive>');
+ buffer.write(">");
+ }
+ if (withNullability) {
+ _appendNullability(buffer);
}
}
@@ -1663,7 +1654,7 @@
* types in [types], return it. Otherwise return `null`.
*/
static DartType findMostSpecificType(
- List<DartType> types, TypeSystem typeSystem) {
+ List<DartType> types, TypeSystemImpl typeSystem) {
// The << relation ("more specific than") is a partial ordering on types,
// so to find the most specific type of a set, we keep a bucket of the most
// specific types seen so far such that no type in the bucket is more
@@ -2032,26 +2023,17 @@
@override
bool get isVoid => false;
- /**
- * Return the nullability suffix of this type.
- */
+ @override
NullabilitySuffix get nullabilitySuffix;
/**
- * Append a textual representation of this type to the given [buffer]. The set
- * of [visitedTypes] is used to prevent infinite recursion.
+ * Append a textual representation of this type to the given [buffer].
*/
- void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
- {bool withNullability = false}) {
- if (visitedTypes.add(this)) {
- if (name == null) {
- buffer.write("<unnamed type>");
- } else {
- buffer.write(name);
- }
- visitedTypes.remove(this);
+ void appendTo(StringBuffer buffer, {bool withNullability = false}) {
+ if (name == null) {
+ buffer.write("<unnamed type>");
} else {
- buffer.write('<recursive>');
+ buffer.write(name);
}
if (withNullability) {
_appendNullability(buffer);
@@ -2081,7 +2063,7 @@
@override
String toString({bool withNullability = false}) {
StringBuffer buffer = new StringBuffer();
- appendTo(buffer, new Set.identity(), withNullability: withNullability);
+ appendTo(buffer, withNullability: withNullability);
return buffer.toString();
}
@@ -2095,7 +2077,7 @@
* so it is what you want if you are constructing a fresh type and want it to
* have the correct nullability suffix, but it is generally *not* what you
* want if you're manipulating existing types. For manipulating existing
- * types, please use the methods in [TypeSystem].
+ * types, please use the methods in [TypeSystemImpl].
*/
TypeImpl withNullability(NullabilitySuffix nullabilitySuffix);
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index c74ce935..2cab0ed 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -36,7 +36,14 @@
var substitution = Substitution.fromMap(map);
for (int i = 0; i < typeParameters.length; ++i) {
- var bound = typeParameters[i].bound;
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ var typeParameter = typeParameters[i] as TypeParameterElementImpl;
+ if (!typeParameter.isLegacyCovariant) {
+ freshParameters[i].variance = typeParameter.variance;
+ }
+
+ var bound = typeParameter.bound;
if (bound != null) {
var newBound = substitution.substituteType(bound);
freshParameters[i].bound = newBound;
@@ -242,7 +249,9 @@
var freshElements = List<TypeParameterElement>(elements.length);
for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ var element = elements[i] as TypeParameterElementImpl;
var freshElement = TypeParameterElementImpl(element.name, -1);
freshElements[i] = freshElement;
var freshType = freshElement.instantiate(
@@ -250,6 +259,10 @@
);
freshElement.type = freshType;
substitution[element] = freshType;
+
+ if (!element.isLegacyCovariant) {
+ freshElement.variance = element.variance;
+ }
}
for (var i = 0; i < freshElements.length; i++) {
diff --git a/pkg/analyzer/lib/src/dart/element/type_provider.dart b/pkg/analyzer/lib/src/dart/element/type_provider.dart
index 07a7fe8..8884f1b 100644
--- a/pkg/analyzer/lib/src/dart/element/type_provider.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_provider.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart';
+import 'package:meta/meta.dart';
/// Provide common functionality shared by the various TypeProvider
/// implementations.
@@ -41,10 +42,13 @@
}
class TypeProviderImpl extends TypeProviderBase {
- final NullabilitySuffix _nullabilitySuffix;
final LibraryElement _coreLibrary;
final LibraryElement _asyncLibrary;
+ /// If `true`, then NNBD types are returned.
+ /// If `false`, then legacy types are returned.
+ final bool _isNonNullableByDefault;
+
ClassElement _boolElement;
ClassElement _doubleElement;
ClassElement _futureElement;
@@ -96,13 +100,37 @@
/// Initialize a newly created type provider to provide the types defined in
/// the given [coreLibrary] and [asyncLibrary].
- TypeProviderImpl(
- LibraryElement coreLibrary,
- LibraryElement asyncLibrary, {
- NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
- }) : _nullabilitySuffix = nullabilitySuffix,
- _coreLibrary = coreLibrary,
- _asyncLibrary = asyncLibrary;
+ TypeProviderImpl({
+ @required LibraryElement coreLibrary,
+ @required LibraryElement asyncLibrary,
+ @required bool isNonNullableByDefault,
+ }) : _coreLibrary = coreLibrary,
+ _asyncLibrary = asyncLibrary,
+ _isNonNullableByDefault = isNonNullableByDefault;
+
+ TypeProviderImpl get asLegacy {
+ if (_isNonNullableByDefault) {
+ return TypeProviderImpl(
+ coreLibrary: _coreLibrary,
+ asyncLibrary: _asyncLibrary,
+ isNonNullableByDefault: false,
+ );
+ } else {
+ return this;
+ }
+ }
+
+ TypeProviderImpl get asNonNullableByDefault {
+ if (_isNonNullableByDefault) {
+ return this;
+ } else {
+ return TypeProviderImpl(
+ coreLibrary: _coreLibrary,
+ asyncLibrary: _asyncLibrary,
+ isNonNullableByDefault: true,
+ );
+ }
+ }
@override
ClassElement get boolElement {
@@ -117,7 +145,7 @@
@override
DartType get bottomType {
- if (_nullabilitySuffix == NullabilitySuffix.none) {
+ if (_isNonNullableByDefault) {
return NeverTypeImpl.instance;
}
return NeverTypeImpl.instanceLegacy;
@@ -434,8 +462,16 @@
@override
VoidType get voidType => VoidTypeImpl.instance;
+ NullabilitySuffix get _nullabilitySuffix {
+ if (_isNonNullableByDefault) {
+ return NullabilitySuffix.none;
+ } else {
+ return NullabilitySuffix.star;
+ }
+ }
+
NullabilitySuffix get _questionOrStarSuffix {
- return _nullabilitySuffix == NullabilitySuffix.none
+ return _isNonNullableByDefault
? NullabilitySuffix.question
: NullabilitySuffix.star;
}
@@ -496,14 +532,6 @@
);
}
- TypeProviderImpl withNullability(NullabilitySuffix nullabilitySuffix) {
- if (_nullabilitySuffix == nullabilitySuffix) {
- return this;
- }
- return TypeProviderImpl(_coreLibrary, _asyncLibrary,
- nullabilitySuffix: nullabilitySuffix);
- }
-
/// Return the class with the given [name] from the given [library], or
/// throw a [StateError] if there is no class with the given name.
ClassElement _getClassElement(LibraryElement library, String name) {
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 291e8b08..75008d4 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -22,7 +22,56 @@
/**
* Dead code is code that is never reached, this can happen for instance if a
* statement follows a return statement.
+ *
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when code is found that won't be
+ // executed because execution will never reach the code.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the invocation of
+ // `print` occurs after the function has returned:
+ //
+ // ```dart
+ // void f() {
+ // return;
+ // [!print('here');!]
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the code isn't needed, then remove it:
+ //
+ // ```dart
+ // void f() {
+ // return;
+ // }
+ // ```
+ //
+ // If the code needs to be executed, then either move the code to a place
+ // where it will be executed:
+ //
+ // ```dart
+ // void f() {
+ // print('here');
+ // return;
+ // }
+ // ```
+ //
+ // Or, rewrite the code before it, so that it can be reached:
+ //
+ // ```dart
+ // void f({bool skipPrinting = true}) {
+ // if (skipPrinting) {
+ // return;
+ // }
+ // print('here');
+ // }
+ // ```
static const HintCode DEAD_CODE = const HintCode('DEAD_CODE', "Dead code.",
correction: "Try removing the code, or "
"fixing the code before it so that it can be reached.");
@@ -30,11 +79,57 @@
/**
* Dead code is code that is never reached. This case covers cases where the
* user has catch clauses after `catch (e)` or `on Object catch (e)`.
+ *
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a catch clause is found that
+ // can't be executed because it’s after a catch clause of the form `catch (e)`
+ // or `on Object catch (e)`. The first catch clause that matches the thrown
+ // object is selected, and both of those forms will match any object, so no
+ // catch clauses that follow them will be selected.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic:
+ //
+ // ```dart
+ // void f() {
+ // try {
+ // } catch (e) {
+ // } [!on String {
+ // }!]
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the clause should be selectable, then move the clause before the general
+ // clause:
+ //
+ // ```dart
+ // void f() {
+ // try {
+ // } on String {
+ // } catch (e) {
+ // }
+ // }
+ // ```
+ //
+ // If the clause doesn't need to be selectable, then remove it:
+ //
+ // ```dart
+ // void f() {
+ // try {
+ // } catch (e) {
+ // }
+ // }
+ // ```
static const HintCode DEAD_CODE_CATCH_FOLLOWING_CATCH = const HintCode(
'DEAD_CODE_CATCH_FOLLOWING_CATCH',
- "Dead code: catch clauses after a 'catch (e)' or "
- "an 'on Object catch (e)' are never reached.",
+ "Dead code: Catch clauses after a 'catch (e)' or an "
+ "'on Object catch (e)' are never reached.",
correction:
"Try reordering the catch clauses so that they can be reached, or "
"removing the unreachable catch clauses.");
@@ -48,10 +143,55 @@
* 0: name of the subtype
* 1: name of the supertype
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a catch clause is found that
+ // can't be executed because it is after a catch clause that catches either
+ // the same type or a supertype of the clause's type. The first catch clause
+ // that matches the thrown object is selected, and the earlier clause l always
+ // matches anything matchable by the highlighted clause, so the highlighted
+ // clause will never be selected.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic:
+ //
+ // ```dart
+ // void f() {
+ // try {
+ // } on num {
+ // } [!on int {
+ // }!]
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the clause should be selectable, then move the clause before the general
+ // clause:
+ //
+ // ```dart
+ // void f() {
+ // try {
+ // } on int {
+ // } on num {
+ // }
+ // }
+ // ```
+ //
+ // If the clause doesn't need to be selectable, then remove it:
+ //
+ // ```dart
+ // void f() {
+ // try {
+ // } on num {
+ // }
+ // }
+ // ```
static const HintCode DEAD_CODE_ON_CATCH_SUBTYPE = const HintCode(
'DEAD_CODE_ON_CATCH_SUBTYPE',
- "Dead code: this on-catch block will never be executed because '{0}' is "
- "a subtype of '{1}' and hence will have been caught above.",
+ "Dead code: This on-catch block won’t be executed because '{0}' is a "
+ "subtype of '{1}' and hence will have been caught already.",
correction:
"Try reordering the catch clauses so that this block can be reached, "
"or removing the unreachable catch clause.");
@@ -112,7 +252,7 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `x` is deprecated:
//
// ```dart
// @deprecated
@@ -177,7 +317,35 @@
/**
* Duplicate imports.
+ *
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an import directive is found
+ // that is the same as an import before it in the file. The second import
+ // doesn’t add value and should be removed.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ // import [!'package:meta/meta.dart'!];
+ //
+ // @sealed class C {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Remove the unnecessary import:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // @sealed class C {}
+ // ```
static const HintCode DUPLICATE_IMPORT = const HintCode(
'DUPLICATE_IMPORT', "Duplicate import.",
correction: "Try removing all but one import of the library.");
@@ -330,12 +498,25 @@
*/
// #### Description
//
- // The meaning of the `@literal` annotation is only defined when it's applied
- // to a const constructor.
+ // The analyzer produces this diagnostic when the `@literal` annotation is
+ // applied to anything other than a const constructor.
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the constructor is not
+ // a `const` constructor:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // class C {
+ // [!@literal!]
+ // C();
+ // }
+ // ```
+ //
+ // The following code produces this diagnostic because `x` isn't a
+ // constructor:
//
// ```dart
// import 'package:meta/meta.dart';
@@ -346,7 +527,23 @@
//
// #### Common fixes
//
- // Remove the annotation:
+ // If the annotation is on a constructor and the constructor should always be
+ // invoked with `const`, when possible, then mark the constructor with the
+ // `const` keyword:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // class C {
+ // @literal
+ // const C();
+ // }
+ // ```
+ //
+ // If the constructor can't be marked as `const`, then remove the annotation.
+ //
+ // If the annotation is on anything other than a constructor, then remove the
+ // annotation:
//
// ```dart
// var x;
@@ -467,34 +664,79 @@
"The member '{0}' can only be used within instance members of subclasses "
"of '{1}'.");
- /// This hint is generated anywhere where a member annotated with
- /// `@visibleForTemplate` is used outside of a "template" Dart file.
- ///
- /// Parameters:
- /// 0: the name of the member
- /// 1: the name of the defining class
+ /**
+ * This hint is generated anywhere where a member annotated with
+ * `@visibleForTemplate` is used outside of a "template" Dart file.
+ *
+ * Parameters:
+ * 0: the name of the member
+ * 1: the name of the defining class
+ */
static const HintCode INVALID_USE_OF_VISIBLE_FOR_TEMPLATE_MEMBER =
const HintCode(
'INVALID_USE_OF_VISIBLE_FOR_TEMPLATE_MEMBER',
"The member '{0}' can only be used within '{1}' or a template "
"library.");
- /// This hint is generated anywhere where a member annotated with
- /// `@visibleForTesting` is used outside the defining library, or a test.
- ///
- /// Parameters:
- /// 0: the name of the member
- /// 1: the name of the defining class
+ /**
+ * This hint is generated anywhere where a member annotated with
+ * `@visibleForTesting` is used outside the defining library, or a test.
+ *
+ * Parameters:
+ * 0: the name of the member
+ * 1: the name of the defining class
+ */
static const HintCode INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER =
const HintCode('INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER',
"The member '{0}' can only be used within '{1}' or a test.");
- /// This hint is generated anywhere where a private declaration is annotated
- /// with `@visibleForTemplate` or `@visibleForTesting`.
- ///
- /// Parameters:
- /// 0: the name of the member
- /// 1: the name of the annotation
+ /**
+ * This hint is generated anywhere where a private declaration is annotated
+ * with `@visibleForTemplate` or `@visibleForTesting`.
+ *
+ * Parameters:
+ * 0: the name of the member
+ * 1: the name of the annotation
+ */
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when either the `@visibleForTemplate`
+ // or `@visibleForTesting` annotation is applied to a non-public declaration.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // [!@visibleForTesting!]
+ // void _someFunction() {}
+ //
+ // void f() => _someFunction();
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the declaration doesn't need to be used by test code, then remove the
+ // annotation:
+ //
+ // ```dart
+ // void _someFunction() {}
+ //
+ // void f() => _someFunction();
+ // ```
+ //
+ // If it does, then make it public:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // @visibleForTesting
+ // void someFunction() {}
+ //
+ // void f() => someFunction();
+ // ```
static const HintCode INVALID_VISIBILITY_ANNOTATION = const HintCode(
'INVALID_VISIBILITY_ANNOTATION',
"The member '{0}' is annotated with '{1}', but this annotation is only "
@@ -557,6 +799,40 @@
* Parameters:
* 0: the name of the parameter
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a method or function with a
+ // named parameter that is annotated as being required is invoked without
+ // providing a value for the parameter.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the named parameter `x`
+ // is required:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // void f({@required int x}) {}
+ //
+ // void g() {
+ // [!f!]();
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Provide the required value:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // void f({@required int x}) {}
+ //
+ // void g() {
+ // f(x: 2);
+ // }
+ // ```
static const HintCode MISSING_REQUIRED_PARAM = const HintCode(
'MISSING_REQUIRED_PARAM', "The parameter '{0}' is required.");
@@ -568,9 +844,11 @@
* 0: the name of the parameter
* 1: message details
*/
- static const HintCode MISSING_REQUIRED_PARAM_WITH_DETAILS = const HintCode(
- 'MISSING_REQUIRED_PARAM_WITH_DETAILS',
- "The parameter '{0}' is required. {1}.");
+ static const HintCode MISSING_REQUIRED_PARAM_WITH_DETAILS =
+ const HintCodeWithUniqueName(
+ 'MISSING_REQUIRED_PARAM',
+ 'HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS',
+ "The parameter '{0}' is required. {1}.");
/**
* Parameters:
@@ -584,7 +862,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `f` doesn't end with a
+ // return:
//
// ```dart
// int [!f!](int x) {
@@ -609,11 +888,47 @@
/**
* This hint is generated anywhere where a `@sealed` class is used as a
* a superclass constraint of a mixin.
+ *
+ * Parameters:
+ * 0: the name of the sealed class
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when the superclass constraint of a
+ // mixin is a class from a different package that was marked as `@sealed`.
+ // Classes that are sealed can't be extended, implemented, mixed in, or used
+ // as a superclass constraint.
+ //
+ // #### Example
+ //
+ // If the package 'p' defines a sealed class:
+ //
+ // ```dart
+ // %uri="package:p/p.dart"
+ // import 'package:meta/meta.dart';
+ //
+ // @sealed
+ // class C {}
+ // ```
+ //
+ // Then, the following code, when in a package other than 'p', produces this
+ // diagnostic:
+ //
+ // ```dart
+ // import 'package:p/p.dart';
+ //
+ // [!mixin M on C {}!]
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the classes that use the mixin don't need to be subclasses of the sealed
+ // class, then consider adding a field and delegating to the wrapped instance
+ // of the sealed class.
static const HintCode MIXIN_ON_SEALED_CLASS = const HintCode(
'MIXIN_ON_SEALED_CLASS',
"The class '{0}' shouldn't be used as a mixin constraint because it is "
- "sealed, and any class mixing in this mixin has '{0}' as a "
+ "sealed, and any class mixing in this mixin must have '{0}' as a "
"superclass.",
correction:
"Try composing with this class, or refer to its documentation for "
@@ -644,7 +959,47 @@
/**
* Generate a hint for non-const instance creation using a constructor
* annotated with `@literal`.
+ *
+ * Parameters:
+ * 0: the name of the class defining the annotated constructor
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a constructor that has the
+ // `@literal` annotation is invoked without using the `const` keyword, but all
+ // of the arguments to the constructor are constants. The annotation indicates
+ // that the constructor should be used to create a constant value whenever
+ // possible.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // class C {
+ // @literal
+ // const C();
+ // }
+ //
+ // C f() => [!C()!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Add the keyword `const` before the constructor invocation:
+ //
+ // ```dart
+ // import 'package:meta/meta.dart';
+ //
+ // class C {
+ // @literal
+ // const C();
+ // }
+ //
+ // void f() => const C();
+ // ```
static const HintCode NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR = const HintCode(
'NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR',
"This instance creation must be 'const', because the {0} constructor is "
@@ -654,10 +1009,14 @@
/**
* Generate a hint for non-const instance creation (with the `new` keyword)
* using a constructor annotated with `@literal`.
+ *
+ * Parameters:
+ * 0: the name of the class defining the annotated constructor
*/
static const HintCode NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW =
- const HintCode(
- 'NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW',
+ const HintCodeWithUniqueName(
+ 'NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR',
+ 'HintCode.NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW',
"This instance creation must be 'const', because the {0} constructor "
"is marked as '@literal'.",
correction: "Try replacing the 'new' keyword with 'const'.");
@@ -706,39 +1065,89 @@
/**
* A getter with the override annotation does not override an existing getter.
+ *
+ * No parameters.
*/
- static const HintCode OVERRIDE_ON_NON_OVERRIDING_GETTER = const HintCode(
- 'OVERRIDE_ON_NON_OVERRIDING_GETTER',
- "Getter doesn't override an inherited getter.",
- correction: "Try updating this class to match the superclass, or "
- "removing the override annotation.");
+ static const HintCode OVERRIDE_ON_NON_OVERRIDING_GETTER =
+ const HintCodeWithUniqueName(
+ 'OVERRIDE_ON_NON_OVERRIDING_MEMBER',
+ 'HintCode.OVERRIDE_ON_NON_OVERRIDING_GETTER',
+ "The getter doesn't override an inherited getter.",
+ correction: "Try updating this class to match the superclass, or "
+ "removing the override annotation.");
/**
* A field with the override annotation does not override a getter or setter.
+ *
+ * No parameters.
*/
- static const HintCode OVERRIDE_ON_NON_OVERRIDING_FIELD = const HintCode(
- 'OVERRIDE_ON_NON_OVERRIDING_FIELD',
- "Field doesn't override an inherited getter or setter.",
- correction: "Try updating this class to match the superclass, or "
- "removing the override annotation.");
+ static const HintCode OVERRIDE_ON_NON_OVERRIDING_FIELD =
+ const HintCodeWithUniqueName(
+ 'OVERRIDE_ON_NON_OVERRIDING_MEMBER',
+ 'HintCode.OVERRIDE_ON_NON_OVERRIDING_FIELD',
+ "The field doesn't override an inherited getter or setter.",
+ correction: "Try updating this class to match the superclass, or "
+ "removing the override annotation.");
/**
* A method with the override annotation does not override an existing method.
+ *
+ * No parameters.
*/
- static const HintCode OVERRIDE_ON_NON_OVERRIDING_METHOD = const HintCode(
- 'OVERRIDE_ON_NON_OVERRIDING_METHOD',
- "Method doesn't override an inherited method.",
- correction: "Try updating this class to match the superclass, or "
- "removing the override annotation.");
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a class member is annotated with
+ // the `@override` annotation, but the member isn’t declared in any of the
+ // supertypes of the class.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `m` isn't declared in
+ // any of the supertypes of `C`:
+ //
+ // ```dart
+ // class C {
+ // @override
+ // String [!m!]() => '';
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the member is intended to override a member with a different name, then
+ // update the member to have the same name:
+ //
+ // ```dart
+ // class C {
+ // @override
+ // String toString() => '';
+ // }
+ // ```
+ //
+ // If the member is intended to override a member that was removed from the
+ // superclass, then consider removing the member from the subclass.
+ //
+ // If the member can't be removed, then remove the annotation.
+ static const HintCode OVERRIDE_ON_NON_OVERRIDING_METHOD =
+ const HintCodeWithUniqueName(
+ 'OVERRIDE_ON_NON_OVERRIDING_MEMBER',
+ 'HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD',
+ "The method doesn't override an inherited method.",
+ correction: "Try updating this class to match the superclass, or "
+ "removing the override annotation.");
/**
* A setter with the override annotation does not override an existing setter.
+ *
+ * No parameters.
*/
- static const HintCode OVERRIDE_ON_NON_OVERRIDING_SETTER = const HintCode(
- 'OVERRIDE_ON_NON_OVERRIDING_SETTER',
- "Setter doesn't override an inherited setter.",
- correction: "Try updating this class to match the superclass, or "
- "removing the override annotation.");
+ static const HintCode OVERRIDE_ON_NON_OVERRIDING_SETTER =
+ const HintCodeWithUniqueName(
+ 'OVERRIDE_ON_NON_OVERRIDING_MEMBER',
+ 'HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER',
+ "The setter doesn't override an inherited setter.",
+ correction: "Try updating this class to match the superclass, or "
+ "removing the override annotation.");
/**
* It is a bad practice for a package import to reference anything outside the
@@ -1527,7 +1936,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `_x` isn't referenced
+ // anywhere in the library:
//
// ```dart
// class Point {
@@ -1557,7 +1967,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because nothing defined in
+ // `dart:async` is referenced in the library:
//
// ```dart
// import [!'dart:async'!];
@@ -1595,7 +2006,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the value of `count` is
+ // never read:
//
// ```dart
// void main() {
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 5f1bace..442e549 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -218,7 +218,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the method `a` doesn't
+ // have a body:
//
// ```dart
// extension E on String {
@@ -244,7 +245,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because there is a constructor
+ // declaration in `E`:
//
// ```dart
// extension E on String {
@@ -269,7 +271,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `s` is an instance
+ // field:
//
// ```dart
// extension E on String {
@@ -494,7 +497,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `i` is marked as being
+ // covariant:
//
// ```dart
// extension E on String {
@@ -826,6 +830,9 @@
static const ParserErrorCode TYPEDEF_IN_CLASS = _TYPEDEF_IN_CLASS;
+ static const ParserErrorCode TYPE_PARAMETER_ON_CONSTRUCTOR =
+ _TYPE_PARAMETER_ON_CONSTRUCTOR;
+
/**
* Parameters:
* 0: the starting character that was missing
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index f5eff9d..7aad143 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -106,6 +106,7 @@
_NULL_AWARE_CASCADE_OUT_OF_ORDER,
_MULTIPLE_VARIANCE_MODIFIERS,
_INVALID_USE_OF_COVARIANT_IN_EXTENSION,
+ _TYPE_PARAMETER_ON_CONSTRUCTOR,
];
const ParserErrorCode _ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
@@ -563,6 +564,11 @@
'TYPE_BEFORE_FACTORY', r"Factory constructors cannot have a return type.",
correction: "Try removing the type appearing before 'factory'.");
+const ParserErrorCode _TYPE_PARAMETER_ON_CONSTRUCTOR = const ParserErrorCode(
+ 'TYPE_PARAMETER_ON_CONSTRUCTOR',
+ r"Constructors can't have type parameters.",
+ correction: "Try removing the type parameters.");
+
const ParserErrorCode _VAR_AND_TYPE = const ParserErrorCode('VAR_AND_TYPE',
r"Variables can't be declared using both 'var' and a type name.",
correction: "Try removing 'var.'");
diff --git a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
index 4c3462b..cd96592 100644
--- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
@@ -28,7 +28,7 @@
TypeProvider get _typeProvider => _resolver.typeProvider;
- TypeSystem get _typeSystem => _resolver.typeSystem;
+ TypeSystemImpl get _typeSystem => _resolver.typeSystem;
/// Return the most specific extension in the current scope for this [type],
/// that defines the member with the given [name].
@@ -95,10 +95,11 @@
node.typeArgumentTypes,
);
- var getterMember =
- getter != null ? ExecutableMember.from2(getter, substitution) : null;
- var setterMember =
- setter != null ? ExecutableMember.from2(setter, substitution) : null;
+ var getterMember = ExecutableMember.from2(getter, substitution);
+ var setterMember = ExecutableMember.from2(setter, substitution);
+
+ getterMember = _resolver.toLegacyElement(getterMember);
+ setterMember = _resolver.toLegacyElement(setterMember);
return ResolutionResult(getter: getterMember, setter: setterMember);
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index 15de2d3..6916281 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -10,7 +10,7 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
+import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
import 'package:analyzer/src/generated/variable_type_provider.dart';
/// Data gathered by flow analysis, retained for testing purposes.
@@ -283,7 +283,7 @@
class TypeSystemTypeOperations
implements TypeOperations<PromotableElement, DartType> {
- final Dart2TypeSystem typeSystem;
+ final TypeSystemImpl typeSystem;
TypeSystemTypeOperations(this.typeSystem);
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index dfff9aa..6ac99e7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -362,7 +362,7 @@
return result;
}
- ExecutableElement member = result.getter;
+ var member = _resolver.toLegacyElement(result.getter);
nameNode.staticElement = member;
if (member.isStatic) {
@@ -387,6 +387,7 @@
ExtensionElement extension, SimpleIdentifier nameNode, String name) {
var getter = extension.getGetter(name);
if (getter != null) {
+ getter = _resolver.toLegacyElement(getter);
nameNode.staticElement = getter;
_reportStaticAccessToInstanceMember(getter, nameNode);
_rewriteAsFunctionExpressionInvocation(node, getter.returnType);
@@ -395,6 +396,7 @@
var method = extension.getMethod(name);
if (method != null) {
+ method = _resolver.toLegacyElement(method);
nameNode.staticElement = method;
_reportStaticAccessToInstanceMember(method, nameNode);
_setResolution(node, method.type);
@@ -412,7 +414,7 @@
void _resolveExtensionOverride(MethodInvocation node,
ExtensionOverride override, SimpleIdentifier nameNode, String name) {
var result = _extensionResolver.getOverrideMember(override, name);
- var member = result.getter;
+ var member = _resolver.toLegacyElement(result.getter);
if (member == null) {
_setDynamicResolution(node);
@@ -464,7 +466,7 @@
ResolutionResult result =
_extensionResolver.findExtension(receiverType, name, nameNode);
if (result.isSingle) {
- var member = result.getter;
+ var member = _resolver.toLegacyElement(result.getter);
nameNode.staticElement = member;
if (member is PropertyAccessorElement) {
return _rewriteAsFunctionExpressionInvocation(node, member.returnType);
@@ -473,6 +475,7 @@
} else if (result.isAmbiguous) {
return;
}
+
// We can invoke Object methods on Function.
var member = _inheritance.getMember(
_resolver.typeProvider.functionType,
@@ -500,6 +503,7 @@
var target = _inheritance.getMember(receiverType, _currentName);
if (target != null) {
+ target = _resolver.toLegacyElement(target);
nameNode.staticElement = target;
if (target is PropertyAccessorElement) {
return _rewriteAsFunctionExpressionInvocation(node, target.returnType);
@@ -545,6 +549,7 @@
MethodInvocation node, SimpleIdentifier nameNode, String name) {
var element = nameScope.lookup(nameNode, _definingLibrary);
if (element != null) {
+ element = _resolver.toLegacyElement(element);
nameNode.staticElement = element;
if (element is MultiplyDefinedElement) {
MultiplyDefinedElement multiply = element;
@@ -590,6 +595,7 @@
var target = _inheritance.getMember(receiverType, _currentName);
if (target != null) {
+ target = _resolver.toLegacyElement(target);
nameNode.staticElement = target;
if (target is PropertyAccessorElement) {
return _rewriteAsFunctionExpressionInvocation(node, target.returnType);
@@ -619,7 +625,7 @@
var result = _extensionResolver.findExtension(receiverType, name, nameNode);
if (result.isSingle) {
- var target = result.getter;
+ var target = _resolver.toLegacyElement(result.getter);
if (target != null) {
nameNode.staticElement = target;
_setResolution(node, target.type);
@@ -651,6 +657,7 @@
// But maybe this is the only one solution.
var prefixedName = new PrefixedIdentifierImpl.temp(receiver, nameNode);
var element = nameScope.lookup(prefixedName, _definingLibrary);
+ element = _resolver.toLegacyElement(element);
nameNode.staticElement = element;
if (element is MultiplyDefinedElement) {
@@ -682,6 +689,7 @@
_currentName,
forSuper: true,
);
+ target = _resolver.toLegacyElement(target);
// If there is that concrete dispatch target, then we are done.
if (target != null) {
@@ -723,6 +731,7 @@
}
var element = _resolveElement(receiver, nameNode);
+ element = _resolver.toLegacyElement(element);
if (element != null) {
if (element is ExecutableElement) {
nameNode.staticElement = element;
@@ -804,6 +813,7 @@
return;
}
}
+ call = _resolver.toLegacyElement(call);
if (call != null && call.kind == ElementKind.METHOD) {
invocation.staticElement = call;
rawFunctionType = call.type;
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 8df0142..bef6eac 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -15,7 +15,6 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/ast_rewrite.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
-import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/declaration_resolver.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -61,6 +60,10 @@
final AstRewriter _astRewriter;
final TypeNameResolver _typeNameResolver;
+ /// This index is incremented every time we visit a [LibraryDirective].
+ /// There is just one [LibraryElement], so we can support only one node.
+ int _libraryDirectiveIndex = 0;
+
/// The provider of pre-built children elements from the element being
/// visited. For example when we visit a method, its element is resynthesized
/// from the summary, and we get resynthesized elements for type parameters
@@ -161,7 +164,10 @@
_withNameScope(() {
var exceptionNode = node.exceptionParameter;
if (exceptionNode != null) {
- var element = LocalVariableElementImpl.forNode(exceptionNode);
+ var element = LocalVariableElementImpl(
+ exceptionNode.name,
+ exceptionNode.offset,
+ );
_elementHolder.enclose(element);
_nameScope.define(element);
@@ -181,7 +187,10 @@
var stackTraceNode = node.stackTraceParameter;
if (stackTraceNode != null) {
- var element = LocalVariableElementImpl.forNode(stackTraceNode);
+ var element = LocalVariableElementImpl(
+ stackTraceNode.name,
+ stackTraceNode.offset,
+ );
_elementHolder.enclose(element);
_nameScope.define(element);
@@ -292,7 +301,7 @@
@override
void visitDeclaredIdentifier(DeclaredIdentifier node) {
var nameNode = node.identifier;
- var element = LocalVariableElementImpl.forNode(nameNode);
+ var element = LocalVariableElementImpl(nameNode.name, nameNode.offset);
_elementHolder.enclose(element);
nameNode.staticElement = element;
@@ -322,7 +331,11 @@
if (_elementWalker != null) {
element = _elementWalker.getParameter();
} else {
- element = DefaultParameterElementImpl.forNode(nameNode);
+ if (nameNode != null) {
+ element = DefaultParameterElementImpl(nameNode.name, nameNode.offset);
+ } else {
+ element = DefaultParameterElementImpl('', -1);
+ }
_elementHolder.addParameter(element);
_setCodeRange(element, node);
@@ -390,10 +403,12 @@
@override
void visitExportDirective(ExportDirective node) {
- super.visitExportDirective(node);
- if (node.element != null) {
- _setElementAnnotations(node.metadata, node.element.metadata);
- }
+ _withElementWalker(null, () {
+ super.visitExportDirective(node);
+ if (node.element != null) {
+ _setElementAnnotations(node.metadata, node.element.metadata);
+ }
+ });
}
@override
@@ -430,20 +445,26 @@
FieldFormalParameterElementImpl element;
if (node.parent is DefaultFormalParameter) {
element = node.declaredElement;
- } else if (_elementWalker != null) {
- element = _elementWalker.getParameter();
} else {
- // Only for recovery, this should not happen in valid code.
- element = FieldFormalParameterElementImpl.forNode(node.identifier);
- _elementHolder.enclose(element);
- element.isConst = node.isConst;
- element.isExplicitlyCovariant = node.covariantKeyword != null;
- element.isFinal = node.isFinal;
- // ignore: deprecated_member_use_from_same_package
- element.parameterKind = node.kind;
- _setCodeRange(element, node);
+ var nameNode = node.identifier;
+ if (_elementWalker != null) {
+ element = _elementWalker.getParameter();
+ } else {
+ // Only for recovery, this should not happen in valid code.
+ element = FieldFormalParameterElementImpl(
+ nameNode.name,
+ nameNode.offset,
+ );
+ _elementHolder.enclose(element);
+ element.isConst = node.isConst;
+ element.isExplicitlyCovariant = node.covariantKeyword != null;
+ element.isFinal = node.isFinal;
+ // ignore: deprecated_member_use_from_same_package
+ element.parameterKind = node.kind;
+ _setCodeRange(element, node);
+ }
+ nameNode.staticElement = element;
}
- node.identifier.staticElement = element;
node.metadata.accept(this);
_setElementAnnotations(node.metadata, element.metadata);
@@ -602,7 +623,7 @@
if (_elementWalker != null) {
element = _elementWalker.getParameter();
} else {
- element = new ParameterElementImpl.forNode(nameNode);
+ element = new ParameterElementImpl(nameNode.name, nameNode.offset);
_elementHolder.addParameter(element);
element.isConst = node.isConst;
element.isExplicitlyCovariant = node.covariantKeyword != null;
@@ -703,10 +724,12 @@
@override
void visitImportDirective(ImportDirective node) {
- super.visitImportDirective(node);
- if (node.element != null) {
- _setElementAnnotations(node.metadata, node.element.metadata);
- }
+ _withElementWalker(null, () {
+ super.visitImportDirective(node);
+ if (node.element != null) {
+ _setElementAnnotations(node.metadata, node.element.metadata);
+ }
+ });
}
@override
@@ -735,8 +758,13 @@
@override
void visitLibraryDirective(LibraryDirective node) {
super.visitLibraryDirective(node);
- if (node.element != null) {
+ ++_libraryDirectiveIndex;
+ if (node.element != null && _libraryDirectiveIndex == 1) {
_setElementAnnotations(node.metadata, node.element.metadata);
+ } else {
+ for (var annotation in node.metadata) {
+ annotation.elementAnnotation = ElementAnnotationImpl(_unitElement);
+ }
}
}
@@ -803,10 +831,12 @@
@override
void visitPartDirective(PartDirective node) {
- super.visitPartDirective(node);
- if (node.element != null) {
- _setElementAnnotations(node.metadata, node.element.metadata);
- }
+ _withElementWalker(null, () {
+ super.visitPartDirective(node);
+ if (node.element != null) {
+ _setElementAnnotations(node.metadata, node.element.metadata);
+ }
+ });
}
@override
@@ -819,7 +849,11 @@
if (_elementWalker != null) {
element = _elementWalker.getParameter();
} else {
- element = ParameterElementImpl.forNode(nameNode);
+ if (nameNode != null) {
+ element = ParameterElementImpl(nameNode.name, nameNode.offset);
+ } else {
+ element = ParameterElementImpl('', -1);
+ }
_elementHolder.addParameter(element);
_setCodeRange(element, node);
@@ -893,13 +927,6 @@
void visitTypeParameter(TypeParameter node) {
TypeParameterElementImpl element = node.declaredElement;
- // TODO (kallentu) : Clean up TypeParameterImpl checks and casting once
- // variance is added to the interface.
- if (node is TypeParameterImpl && node.varianceKeyword != null) {
- element.variance =
- Variance.fromKeywordString(node.varianceKeyword.lexeme);
- }
-
node.metadata?.accept(this);
_setElementAnnotations(node.metadata, element.metadata);
@@ -908,9 +935,6 @@
boundNode.accept(this);
if (_elementWalker == null) {
element.bound = boundNode.type;
-
- element.metadata = _createElementAnnotations(node.metadata);
- _setCodeRange(element, node);
}
}
}
@@ -987,8 +1011,12 @@
List<Label> labels, bool onSwitchStatement, bool onSwitchMember) {
for (Label label in labels) {
var labelName = label.label;
- var element = LabelElementImpl.forNode(
- labelName, onSwitchStatement, onSwitchMember);
+ var element = LabelElementImpl(
+ labelName.name,
+ labelName.offset,
+ onSwitchStatement,
+ onSwitchMember,
+ );
labelName.staticElement = element;
_elementHolder.enclose(element);
}
@@ -1006,8 +1034,9 @@
void _buildLocalFunctionElement(FunctionDeclarationStatement statement) {
var node = statement.functionDeclaration;
- var element = FunctionElementImpl.forNode(node.name);
- node.name.staticElement = element;
+ var nameNode = node.name;
+ var element = FunctionElementImpl(nameNode.name, nameNode.offset);
+ nameNode.staticElement = element;
_nameScope.define(element);
_elementHolder.enclose(element);
}
@@ -1021,9 +1050,15 @@
LocalVariableElementImpl element;
if (isConst && variable.initializer != null) {
- element = ConstLocalVariableElementImpl.forNode(variableName);
+ element = ConstLocalVariableElementImpl(
+ variableName.name,
+ variableName.offset,
+ );
} else {
- element = LocalVariableElementImpl.forNode(variableName);
+ element = LocalVariableElementImpl(
+ variableName.name,
+ variableName.offset,
+ );
}
variableName.staticElement = element;
_elementHolder.enclose(element);
@@ -1048,8 +1083,11 @@
if (_elementWalker != null) {
element = _elementWalker.getTypeParameter();
} else {
- element = TypeParameterElementImpl.forNode(name);
+ element = TypeParameterElementImpl(name.name, name.offset);
_elementHolder.addTypeParameter(element);
+
+ element.metadata = _createElementAnnotations(typeParameter.metadata);
+ _setCodeRange(element, typeParameter);
}
name.staticElement = element;
_nameScope.define(element);
diff --git a/pkg/analyzer/lib/src/dart/resolver/variance.dart b/pkg/analyzer/lib/src/dart/resolver/variance.dart
index 3f69514..ccb7fa8 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variance.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variance.dart
@@ -4,6 +4,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
/// The variance of a type parameter `X` in a type `T`.
class Variance {
@@ -33,10 +34,16 @@
}
} else if (type is InterfaceType) {
var result = unrelated;
- for (var argument in type.typeArguments) {
- result = result.meet(
- Variance(typeParameter, argument),
- );
+ for (int i = 0; i < type.typeArguments.length; ++i) {
+ var argument = type.typeArguments[i];
+ var parameter = type.element.typeParameters[i];
+
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ var parameterVariance =
+ (parameter as TypeParameterElementImpl).variance;
+ result = result
+ .meet(parameterVariance.combine(Variance(typeParameter, argument)));
}
return result;
} else if (type is FunctionType) {
@@ -98,6 +105,23 @@
'Invalid keyword string for variance: $varianceString');
}
+ /// Returns the associated keyword lexeme.
+ String toKeywordString() {
+ switch (this) {
+ case contravariant:
+ return 'in';
+ case invariant:
+ return 'inout';
+ case covariant:
+ return 'out';
+ case unrelated:
+ return '';
+ default:
+ throw new ArgumentError(
+ 'Missing keyword lexeme representation for variance: $this');
+ }
+ }
+
/// Return `true` if this represents the case when `X` occurs free in `T`, and
/// `U <: V` implies `[V/X]T <: [U/X]T`.
bool get isContravariant => this == contravariant;
@@ -156,6 +180,29 @@
/// [meet] calculates the meet of two elements of such lattice. It can be
/// used, for example, to calculate the variance of a typedef type parameter
/// if it's encountered on the RHS of the typedef multiple times.
+ ///
+ /// unrelated
+ /// covariant contravariant
+ /// invariant
Variance meet(Variance other) =>
Variance._fromEncoding(_encoding | other._encoding);
+
+ /// Returns true if this variance is greater than (above) or equal to the
+ /// [other] variance in the partial order induced by the variance lattice.
+ ///
+ /// unrelated
+ /// covariant contravariant
+ /// invariant
+ bool greaterThanOrEqual(Variance other) {
+ if (isUnrelated) {
+ return true;
+ } else if (isCovariant) {
+ return other.isCovariant || other.isInvariant;
+ } else if (isContravariant) {
+ return other.isContravariant || other.isInvariant;
+ } else {
+ assert(isInvariant);
+ return other.isInvariant;
+ }
+ }
}
diff --git a/pkg/analyzer/lib/src/dart/sdk/sdk.dart b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
index 10e559f..2d46430 100644
--- a/pkg/analyzer/lib/src/dart/sdk/sdk.dart
+++ b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
@@ -83,9 +83,8 @@
@override
AnalysisContext get context {
if (_analysisContext == null) {
- _analysisContext = new SdkAnalysisContext(_analysisOptions);
- SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
- _analysisContext.sourceFactory = factory;
+ var factory = SourceFactory([DartUriResolver(this)]);
+ _analysisContext = SdkAnalysisContext(_analysisOptions, factory);
}
return _analysisContext;
}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 240ec8c..4e41047 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -118,7 +118,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `B` doesn't inherit a
+ // concrete implementation of `a`:
//
// ```dart
// abstract class A {
@@ -448,7 +449,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `mixin` is a built-in
+ // identifier:
//
// ```dart
// extension [!mixin!] on int {}
@@ -936,15 +938,32 @@
"removing the keyword 'const' from the map.");
/**
- * 5 Variables: A constant variable must be initialized to a compile-time
- * constant (12.1) or a compile-time error occurs.
- *
* Parameters:
* 0: the name of the uninitialized final variable
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a variable that is declared to
+ // be a constant doesn't have an initializer.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `c` isn't initialized:
+ //
+ // ```dart
+ // const [!c!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Add an initializer:
+ //
+ // ```dart
+ // const c = 'c';
+ // ```
static const CompileTimeErrorCode CONST_NOT_INITIALIZED =
- const CompileTimeErrorCode('CONST_NOT_INITIALIZED',
- "The const variable '{0}' must be initialized.",
+ const CompileTimeErrorCode(
+ 'CONST_NOT_INITIALIZED', "The constant '{0}' must be initialized.",
correction: "Try adding an initialization to the declaration.");
/**
@@ -970,7 +989,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the value of `list1` is
+ // `null`, which is neither a list nor a set:
//
// ```dart
// const List<int> list1 = null;
@@ -1001,7 +1021,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the value of `map1` is
+ // `null`, which isn't a map:
//
// ```dart
// const Map<String, int> map1 = null;
@@ -1065,7 +1086,7 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `i` isn't a constant:
//
// ```dart
// class C {
@@ -1271,7 +1292,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the name `x` is
+ // declared twice:
//
// ```dart
// int x = 0;
@@ -1331,7 +1353,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the string `'a'` is
+ // specified twice:
//
// ```dart
// const Set<String> set = {'a', [!'a'!]};
@@ -1365,7 +1388,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the key `1` is used
+ // twice:
//
// ```dart
// const map = <int, String>{1: 'a', 2: 'b', [!1!]: 'c', 4: 'd'};
@@ -1501,13 +1525,45 @@
"removing the extends clause.");
/**
- * 7.9 Superclasses: It is a compile-time error if the extends clause of a
- * class <i>C</i> includes a type expression that does not denote a class
- * available in the lexical scope of <i>C</i>.
- *
* Parameters:
- * 0: the name of the superclass that was not found
+ * 0: the name in the extends clause
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an extends clause contains a
+ // name that is declared to be something other than a class.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `f` is declared to be a
+ // function:
+ //
+ // ```dart
+ // void f() {}
+ //
+ // class C extends [!f!] {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If you want the class to extend a class other than `Object`, then replace
+ // the name in the extends clause with the name of that class:
+ //
+ // ```dart
+ // void f() {}
+ //
+ // class C extends B {}
+ //
+ // class B {}
+ // ```
+ //
+ // If you want the class to extend `Object`, then remove the extends clause:
+ //
+ // ```dart
+ // void f() {}
+ //
+ // class C {}
+ // ```
static const CompileTimeErrorCode EXTENDS_NON_CLASS =
const CompileTimeErrorCode(
'EXTENDS_NON_CLASS', "Classes can only extend other classes.",
@@ -1523,11 +1579,14 @@
//
// The analyzer produces this diagnostic when the name of an extension is used
// in an expression other than in an extension override or to qualify an
- // access to a static member of the extension.
+ // access to a static member of the extension. Because classes define a type,
+ // the name of a class can be used to refer to the instance of `Type`
+ // representing the type of the class. Extensions, on the other hand, don't
+ // define a type and can't be used as a type literal.
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `E` is an extension:
//
// ```dart
// extension E on int {
@@ -1570,7 +1629,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the name `a` is being
+ // used for two different members:
//
// ```dart
// extension E on Object {
@@ -1610,7 +1670,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `toString` is defined
+ // by `Object`:
//
// ```dart
// extension E on String {
@@ -1648,15 +1709,15 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `m` is static:
//
// ```dart
// extension E on String {
- // static void staticMethod() {}
+ // static void m() {}
// }
//
// void f() {
- // E('').[!staticMethod!]();
+ // E('').[!m!]();
// }
// ```
//
@@ -1666,11 +1727,11 @@
//
// ```dart
// extension E on String {
- // static void staticMethod() {}
+ // static void m() {}
// }
//
// void f() {
- // E.staticMethod();
+ // E.m();
// }
// ```
static const CompileTimeErrorCode EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER =
@@ -1693,7 +1754,7 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `3` isn't a `String`:
//
// ```dart
// extension E on String {
@@ -1736,11 +1797,14 @@
// #### Description
//
// The analyzer produces this diagnostic when an extension override is used as
- // the target of a cascade expression.
+ // the target of a cascade expression. The value of a cascade expression
+ // `e..m` is the value of the target `e`, but extension overrides are not
+ // expressions and don't have a value.
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `E(3)` isn't an
+ // expression:
//
// ```dart
// extension E on int {
@@ -1786,7 +1850,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `E(i)` isn't an
+ // expression:
//
// ```dart
// extension E on int {
@@ -1842,7 +1907,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `f` defines 2
+ // parameters but is invoked with 3 arguments:
//
// ```dart
// void f(int a, int b) {}
@@ -1880,7 +1946,9 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `f` defines 2
+ // positional parameters but has a named parameter that could be used for the
+ // third argument:
//
// ```dart
// void f(int a, int b, {int c}) {}
@@ -2084,7 +2152,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `x` is a variable
+ // rather than a class or mixin:
//
// ```dart
// var x;
@@ -2139,14 +2208,54 @@
correction: "Try removing one of the occurrences.");
/**
- * 7.6.1 Generative Constructors: Note that <b>this</b> is not in scope on the
- * right hand side of an initializer.
- *
- * 12.10 This: It is a compile-time error if this appears in a top-level
- * function or variable initializer, in a factory constructor, or in a static
- * method or variable initializer, or in the initializer of an instance
- * variable.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when it finds a reference to an
+ // instance member in a constructor's initializer list.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `defaultX` is an
+ // instance member:
+ //
+ // ```dart
+ // class C {
+ // int x;
+ //
+ // C() : x = [!defaultX!];
+ //
+ // int get defaultX => 0;
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the member can be made static, then do so:
+ //
+ // ```dart
+ // class C {
+ // int x;
+ //
+ // C() : x = defaultX;
+ //
+ // static int get defaultX => 0;
+ // }
+ // ```
+ //
+ // If not, then replace the reference in the initializer with a different
+ // expression that doesn't use an instance member:
+ //
+ // ```dart
+ // class C {
+ // int x;
+ //
+ // C() : x = 0;
+ //
+ // int get defaultX => 0;
+ // }
+ // ```
static const CompileTimeErrorCode IMPLICIT_THIS_REFERENCE_IN_INITIALIZER =
const CompileTimeErrorCode('IMPLICIT_THIS_REFERENCE_IN_INITIALIZER',
"Only static members can be accessed in initializers.");
@@ -2264,17 +2373,74 @@
correction: "Try removing the initialization.");
/**
- * 7.6.1 Generative Constructors: An initializing formal has the form
- * <i>this.id</i>. It is a compile-time error if <i>id</i> is not the name of
- * an instance variable of the immediately enclosing class.
- *
* Parameters:
* 0: the name of the initializing formal that is not an instance variable in
* the immediately enclosing class
- *
- * See [INITIALIZING_FORMAL_FOR_STATIC_FIELD], and
- * [INITIALIZER_FOR_NON_EXISTENT_FIELD].
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a field formal parameter is
+ // found in a constructor in a class that doesn't declare the field being
+ // initialized.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the field `x` isn't
+ // defined:
+ //
+ // ```dart
+ // class C {
+ // int y;
+ //
+ // C([!this.x!]);
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the field name was wrong, then change it to the name of an existing
+ // field:
+ //
+ // ```dart
+ // class C {
+ // int y;
+ //
+ // C(this.y);
+ // }
+ // ```
+ //
+ // If the field name is correct but hasn't yet been defined, then declare the
+ // field:
+ //
+ // ```dart
+ // class C {
+ // int x;
+ // int y;
+ //
+ // C(this.x);
+ // }
+ // ```
+ //
+ // If the parameter is needed but shouldn't initialize a field, then convert
+ // it to a normal parameter and use it:
+ //
+ // ```dart
+ // class C {
+ // int y;
+ //
+ // C(int x) : y = x * 2;
+ // }
+ // ```
+ //
+ // If the parameter isn't needed, then remove it:
+ //
+ // ```dart
+ // class C {
+ // int y;
+ //
+ // C();
+ // }
+ // ```
static const CompileTimeErrorCode INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD =
const CompileTimeErrorCode('INITIALIZING_FORMAL_FOR_NON_EXISTENT_FIELD',
"'{0}' isn't a field in the enclosing class.",
@@ -2518,14 +2684,6 @@
"making this a required parameter.");
/**
- * If a class declaration has a member declaration, the signature of that
- * member declaration becomes the signature in the interface. It's a
- * compile-time error if that signature is not a valid override of all
- * super-interface member signatures with the same name. (Not just the
- * members of the immediate super-interfaces, but all of them. For
- * non-covariant parameters, it's sufficient to check just the immediate
- * super-interfaces).
- *
* Parameters:
* 0: the name of the declared member that is not a valid override.
* 1: the name of the interface that declares the member.
@@ -2533,6 +2691,62 @@
* 3. the name of the interface with the overridden member.
* 4. the type of the overridden member.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a member of a class is found
+ // that overrides a member from a supertype and the override isn't valid. An
+ // override is valid if all of these are true:
+ // * It allows all of the arguments allowed by the overridden member.
+ // * It doesn't require any arguments that aren't required by the overridden
+ // member.
+ // * The type of every parameter of the overridden member is assignable to the
+ // corresponding parameter of the override.
+ // * The return type of the override is assignable to the return type of the
+ // overridden member.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the type of the
+ // parameter `s` (`String`) isn't assignable to the type of the parameter `i`
+ // (`int`):
+ //
+ // ```dart
+ // class A {
+ // void m(int i) {}
+ // }
+ //
+ // class B extends A {
+ // void [!m!](String s) {}
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the invalid method is intended to override the method from the
+ // superclass, then change it to conform:
+ //
+ // ```dart
+ // class A {
+ // void m(int i) {}
+ // }
+ //
+ // class B extends A {
+ // void m(int i) {}
+ // }
+ // ```
+ //
+ // If it isn't intended to override the method from the superclass, then
+ // rename it:
+ //
+ // ```dart
+ // class A {
+ // void m(int i) {}
+ // }
+ //
+ // class B extends A {
+ // void m2(String s) {}
+ // }
+ // ```
static const CompileTimeErrorCode INVALID_OVERRIDE =
const CompileTimeErrorCode('INVALID_OVERRIDE',
"'{1}.{0}' ('{2}') isn't a valid override of '{3}.{0}' ('{4}').");
@@ -2621,10 +2835,47 @@
* Parameters:
* 0: the name of the extension
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an extension override is used to
+ // invoke a function but the extension doesn't declare a `call` method.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the extension `E`
+ // doesn't define a `call` method:
+ //
+ // ```dart
+ // extension E on String {}
+ //
+ // void f() {
+ // [!E('')!]();
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the extension is intended to define a `call` method, then declare it:
+ //
+ // ```dart
+ // extension E on String {
+ // int call() => 0;
+ // }
+ //
+ // void f() {
+ // E('')();
+ // }
+ // ```
+ //
+ // If the extended type defines a `call` method, then remove the extension
+ // override.
+ //
+ // If the `call` method isn't defined, then rewrite the code so that it
+ // doesn't invoke the `call` method.
static const CompileTimeErrorCode INVOCATION_OF_EXTENSION_WITHOUT_CALL =
const CompileTimeErrorCode(
'INVOCATION_OF_EXTENSION_WITHOUT_CALL',
- "The extension '{0}' does not define a 'call' method so the override "
+ "The extension '{0}' doesn't define a 'call' method so the override "
"can't be used in an invocation.");
/**
@@ -2671,7 +2922,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the literal has a map
+ // entry even though it's a set literal:
//
// ```dart
// const collection = <String>{[!'a' : 'b'!]};
@@ -2998,9 +3250,34 @@
'MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS',
"'{0}' can't be used as a super-class constraint.");
+ /**
+ * No parameters.
+ */
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a type following the `on`
+ // keyword in a mixin declaration is neither a class nor a mixin.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `F` is neither a class
+ // nor a mixin:
+ //
+ // ```dart
+ // typedef F = void Function();
+ //
+ // mixin M on [!F!] {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the type was intended to be a class but was mistyped, then replace the
+ // name.
+ //
+ // Otherwise, remove the type from the on clause.
static const CompileTimeErrorCode MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE =
const CompileTimeErrorCode('MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE',
- "Only classes and mixins can be used as super-class constraints.");
+ "Only classes and mixins can be used as superclass constraints.");
/**
* 9.1 Mixin Application: It is a compile-time error if <i>S</i> does not
@@ -3112,7 +3389,7 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `j` isn't a constant:
//
// ```dart
// void f(int i, int j) {
@@ -3166,12 +3443,47 @@
"changing the import to not be deferred.");
/**
- * 6.2.2 Optional Formals: It is a compile-time error if the default value of
- * an optional parameter is not a compile-time constant.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when an optional parameter, either
+ // named or positional, has a default value that isn't a compile-time
+ // constant.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic:
+ //
+ // ```dart
+ // var defaultValue = 3;
+ //
+ // void f([int value = [!defaultValue!]]) {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the default value can be converted to be a constant, then convert it:
+ //
+ // ```dart
+ // const defaultValue = 3;
+ //
+ // void f([int value = defaultValue]) {}
+ // ```
+ //
+ // If the default value needs to change over time, then apply the default
+ // value inside the function:
+ //
+ // ```dart
+ // var defaultValue = 3;
+ //
+ // void f([int value]) {
+ // value ??= defaultValue;
+ // }
+ // ```
static const CompileTimeErrorCode NON_CONSTANT_DEFAULT_VALUE =
const CompileTimeErrorCode('NON_CONSTANT_DEFAULT_VALUE',
- "Default values of an optional parameter must be constant.");
+ "The default value of an optional parameter must be constant.");
/**
* 6.2.2 Optional Formals: It is a compile-time error if the default value of
@@ -3262,7 +3574,7 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic beause `a` isn't a constant:
//
// ```dart
// var a = 'a';
@@ -3315,7 +3627,7 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `a` isn't a constant:
//
// ```dart
// var a = 'a';
@@ -3486,7 +3798,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `f` declares two
+ // required parameters, but only one argument is provided:
//
// ```dart
// void f(int a, int b) {}
@@ -3607,7 +3920,7 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `l` isn't a `Map`:
//
// ```dart
// var l = <String>['a', 'b'];
@@ -4009,7 +4322,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `i` is used before it
+ // is declared:
//
// ```dart
// void f() {
@@ -4119,7 +4433,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `super` can't be used
+ // in an extension:
//
// ```dart
// extension E on Object {
@@ -4186,7 +4501,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `String` isn't a
+ // subclass of `num`:
//
// ```dart
// class A<E extends num> {}
@@ -4219,10 +4535,9 @@
"Typedefs can't reference themselves directly or recursively via "
"another typedef.");
- static const CompileTimeErrorCode TYPE_PARAMETER_ON_CONSTRUCTOR =
- const CompileTimeErrorCode('TYPE_PARAMETER_ON_CONSTRUCTOR',
- "Constructors can't have type parameters.",
- correction: "Try removing the type parameters.");
+ @Deprecated('Use ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR')
+ static const ParserErrorCode TYPE_PARAMETER_ON_CONSTRUCTOR =
+ ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR;
/**
* No parameters.
@@ -4234,7 +4549,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the name `undefined`
+ // isn't defined:
//
// ```dart
// [!@undefined!]
@@ -4281,7 +4597,7 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `Piont` isn't defined:
//
// ```dart
// class Point {}
@@ -4672,7 +4988,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `m` doesn't declare a
+ // named parameter named `a`:
//
// ```dart
// class C {
@@ -4747,7 +5064,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `m` is a static member
+ // of the extended type `C`:
//
// ```dart
// class C {
@@ -4889,23 +5207,43 @@
'URI_WITH_INTERPOLATION', "URIs can't use string interpolation.");
/**
- * 7.1.1 Operators: It is a compile-time error if the arity of the
- * user-declared operator []= is not 2. It is a compile time error if the
- * arity of a user-declared operator with one of the names: <, >, <=,
- * >=, ==, +, /, ~/, *, %, |, ^, &, <<, >>, [] is not 1. It is
- * a compile time error if the arity of the user-declared operator - is not 0
- * or 1. It is a compile time error if the arity of the user-declared operator
- * ~ is not 0.
- *
* Parameters:
* 0: the name of the declared operator
* 1: the number of parameters expected
* 2: the number of parameters found in the operator declaration
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a declaration of an operator has
+ // the wrong number of parameters.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the operator `+` must
+ // have a single parameter corresponding to the right operand:
+ //
+ // ```dart
+ // class C {
+ // int operator [!+!](a, b) => 0;
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Add or remove parameters to match the required number:
+ //
+ // ```dart
+ // class C {
+ // int operator +(a) => 0;
+ // }
+ // ```
+ // TODO(brianwilkerson) It would be good to add a link to the spec or some
+ // other documentation that lists the number of parameters for each operator,
+ // but I don't know what to link to.
static const CompileTimeErrorCode WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR =
const CompileTimeErrorCode(
'WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR',
- "Operator '{0}' should declare exactly {1} parameter(s), but {2} "
+ "Operator '{0}' should declare exactly {1} parameters, but {2} "
"found.");
/**
@@ -4940,7 +5278,61 @@
'WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE',
"'{0}' can't be used contravariantly or invariantly in '{1}'.",
correction: "Try not using class type parameters in types of formal "
- "parameters of function types.",
+ "parameters of function types, nor in explicitly contravariant or "
+ "invariant superinterfaces.",
+ );
+
+ /**
+ * Let `C` be a generic class that declares a formal type parameter `X`.
+ *
+ * If `X` is explicitly contravariant then it is a compile-time error for
+ * `X` to occur in a non-contravariant position in a member signature in the
+ * body of `C`, except when `X` is in a contravariant position in the type
+ * annotation of a covariant formal parameter.
+ *
+ * If `X` is explicitly covariant then it is a compile-time error for
+ * `X` to occur in a non-covariant position in a member signature in the
+ * body of `C`, except when `X` is in a covariant position in the type
+ * annotation of a covariant formal parameter.
+ *
+ * Parameters:
+ * 0: the variance modifier defined for {0}
+ * 1: the name of the type parameter
+ * 2: the variance position that the type parameter {1} is in
+ */
+ static const CompileTimeErrorCode WRONG_TYPE_PARAMETER_VARIANCE_POSITION =
+ const CompileTimeErrorCode(
+ 'WRONG_TYPE_PARAMETER_VARIANCE_POSITION',
+ "The '{0}' type parameter '{1}' can't be used in an '{2}' position.",
+ correction: "Try removing the type parameter or change the explicit "
+ "variance modifier declaration for the type parameter to another one of"
+ " 'in', 'out', or 'inout'.",
+ );
+
+ /**
+ * Let `C` be a generic class that declares a formal type parameter `X`, and
+ * assume that `T` is a direct superinterface of `C`.
+ *
+ * It is a compile-time error if `X` is explicitly defined as a covariant or
+ * 'in' type parameter and `X` occurs in a non-covariant position in `T`.
+ * It is a compile-time error if `X` is explicitly defined as a contravariant
+ * or 'out' type parameter and `X` occurs in a non-contravariant position in
+ * `T`.
+ *
+ * Parameters:
+ * 0: the name of the type parameter
+ * 1: the variance modifier defined for {0}
+ * 2: the variance position of the type parameter {0} in the
+ * superinterface {3}
+ * 3: the name of the superinterface
+ */
+ static const CompileTimeErrorCode
+ WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE =
+ const CompileTimeErrorCode(
+ 'WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE',
+ "'{0}' is an '{1}' type parameter and can't be used in an '{2}' position in '{3}'.",
+ correction: "Try using 'in' type parameters in 'in' positions and 'out' "
+ "type parameters in 'out' positions in the superinterface.",
);
/**
@@ -5150,7 +5542,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `Binary` is the name of
+ // a function type, not a function:
//
// ```dart
// typedef Binary = int Function(int, int);
@@ -5189,18 +5582,37 @@
"invoked.");
/**
- * 12.20 Conditional: It is a static type warning if the type of
- * <i>e<sub>1</sub></i> may not be assigned to bool.
- *
- * 13.5 If: It is a static type warning if the type of the expression <i>b</i>
- * may not be assigned to bool.
- *
- * 13.7 While: It is a static type warning if the type of <i>e</i> may not be
- * assigned to bool.
- *
- * 13.8 Do: It is a static type warning if the type of <i>e</i> cannot be
- * assigned to bool.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a condition, such as an `if` or
+ // `while` loop, doesn't have the static type `bool`.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `x` has the static type
+ // `int`:
+ //
+ // ```dart
+ // void f(int x) {
+ // if ([!x!]) {
+ // // ...
+ // }
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Change the condition so that it produces a Boolean value:
+ //
+ // ```dart
+ // void f(int x) {
+ // if (x == 0) {
+ // // ...
+ // }
+ // }
+ // ```
static const StaticTypeWarningCode NON_BOOL_CONDITION =
const StaticTypeWarningCode(
'NON_BOOL_CONDITION', "Conditions must have a static type of 'bool'.",
@@ -5275,15 +5687,13 @@
isUnresolvedIdentifier: true);
/**
- * 13.11 Return: It is a static type warning if the type of <i>e</i> may not
- * be assigned to the declared return type of the immediately enclosing
- * function.
- *
* Parameters:
* 0: the return type as declared in the return statement
* 1: the expected return type as defined by the method
* 2: the name of the method
*/
+ @Deprecated('Use either RETURN_OF_INVALID_TYPE_FROM_FUNCTION or '
+ 'RETURN_OF_INVALID_TYPE_FROM_METHOD')
static const StaticTypeWarningCode RETURN_OF_INVALID_TYPE =
const StaticTypeWarningCode(
'RETURN_OF_INVALID_TYPE',
@@ -5306,6 +5716,60 @@
"closure.");
/**
+ * Parameters:
+ * 0: the return type as declared in the return statement
+ * 1: the expected return type as defined by the method
+ * 2: the name of the method
+ */
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a method or function returns a
+ // value whose type isn't assignable to the declared return type.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `f` has a return type
+ // of `String` but is returning an `int`:
+ //
+ // ```dart
+ // String f() => [!3!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the return type is correct, then replace the value being returned with a
+ // value of the correct type, possibly by converting the existing value:
+ //
+ // ```dart
+ // String f() => 3.toString();
+ // ```
+ //
+ // If the value is correct, then change the return type to match:
+ //
+ // ```dart
+ // int f() => 3;
+ // ```
+ static const StaticTypeWarningCode RETURN_OF_INVALID_TYPE_FROM_FUNCTION =
+ const StaticTypeWarningCodeWithUniqueName(
+ 'RETURN_OF_INVALID_TYPE',
+ 'StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION',
+ "A value of type '{0} can't be returned from function '{2}' because it "
+ "has a return type of '{1}'.");
+
+ /**
+ * Parameters:
+ * 0: the return type as declared in the return statement
+ * 1: the expected return type as defined by the method
+ * 2: the name of the method
+ */
+ static const StaticTypeWarningCode RETURN_OF_INVALID_TYPE_FROM_METHOD =
+ const StaticTypeWarningCodeWithUniqueName(
+ 'RETURN_OF_INVALID_TYPE',
+ 'StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_METHOD',
+ "A value of type '{0} can't be returned from method '{2}' because it has "
+ "a return type of '{1}'.");
+
+ /**
* 10 Generics: It is a static type warning if a type parameter is a supertype
* of its upper bound.
*
@@ -5348,7 +5812,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the name `emty` isn't
+ // defined:
//
// ```dart
// List<int> empty() => [];
@@ -5396,7 +5861,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `String` has no member
+ // named `len`:
//
// ```dart
// int f(String s) => s.[!len!];
@@ -5434,7 +5900,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the identifier
+ // `removeMiddle` isn't defined:
//
// ```dart
// int f(List<int> l) => l.[!removeMiddle!]();
@@ -5458,25 +5925,37 @@
hasPublishedDocs: true);
/**
- * 12.18 Assignment: Evaluation of an assignment of the form
- * <i>e<sub>1</sub></i>[<i>e<sub>2</sub></i>] = <i>e<sub>3</sub></i> is
- * equivalent to the evaluation of the expression (a, i, e){a.[]=(i, e);
- * return e;} (<i>e<sub>1</sub></i>, <i>e<sub>2</sub></i>,
- * <i>e<sub>2</sub></i>).
- *
- * 12.29 Assignable Expressions: An assignable expression of the form
- * <i>e<sub>1</sub></i>[<i>e<sub>2</sub></i>] is evaluated as a method
- * invocation of the operator method [] on <i>e<sub>1</sub></i> with argument
- * <i>e<sub>2</sub></i>.
- *
- * 12.15.1 Ordinary Invocation: Let <i>T</i> be the static type of <i>o</i>.
- * It is a static type warning if <i>T</i> does not have an accessible
- * instance member named <i>m</i>.
- *
* Parameters:
* 0: the name of the operator
* 1: the name of the enclosing type where the operator is being looked for
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a user-definable operator is
+ // invoked on an object for which the operator isn't defined.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the class `C` doesn't
+ // define the operator `+`:
+ //
+ // ```dart
+ // class C {}
+ //
+ // C f(C c) => c [!+!] 2;
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the operator should be defined for the class, then define it:
+ //
+ // ```dart
+ // class C {
+ // C operator +(int i) => this;
+ // }
+ //
+ // C f(C c) => c + 2;
+ // ```
static const StaticTypeWarningCode UNDEFINED_OPERATOR =
const StaticTypeWarningCode('UNDEFINED_OPERATOR',
"The operator '{0}' isn't defined for the class '{1}'.",
@@ -5493,7 +5972,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `dart:core` doesn't
+ // define anything named `a`:
//
// ```dart
// import 'dart:core' as p;
@@ -5533,7 +6013,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because there isn't a setter
+ // named `z`:
//
// ```dart
// class C {
@@ -5594,7 +6075,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `Object` doesn't define
+ // a member named `n`:
//
// ```dart
// class C {
@@ -5683,17 +6165,38 @@
correction: "Try adding '{0}.' before the name.");
/**
- * 15.8 Parameterized Types: It is a static type warning if <i>G</i> is not a
- * generic type with exactly <i>n</i> type parameters.
- *
* Parameters:
* 0: the name of the type being referenced (<i>G</i>)
* 1: the number of type parameters that were declared
* 2: the number of type arguments provided
- *
- * See [CompileTimeErrorCode.CONST_WITH_INVALID_TYPE_PARAMETERS], and
- * [CompileTimeErrorCode.NEW_WITH_INVALID_TYPE_PARAMETERS].
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a type that has type parameters
+ // is used and type arguments are provided, but the number of type arguments
+ // isn't the same as the number of type parameters.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `C` has one type
+ // parameter but two type arguments are provided:
+ //
+ // ```dart
+ // class C<E> {}
+ //
+ // void f([!C<int, int>!] x) {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Add or remove type arguments, as necessary, to match the number of type
+ // parameters defined for the type:
+ //
+ // ```dart
+ // class C<E> {}
+ //
+ // void f(C<int> x) {}
+ // ```
static const StaticTypeWarningCode WRONG_NUMBER_OF_TYPE_ARGUMENTS =
const StaticTypeWarningCode(
'WRONG_NUMBER_OF_TYPE_ARGUMENTS',
@@ -5805,6 +6308,17 @@
ErrorType get type => ErrorType.STATIC_TYPE_WARNING;
}
+class StaticTypeWarningCodeWithUniqueName extends StaticTypeWarningCode {
+ @override
+ final String uniqueName;
+
+ const StaticTypeWarningCodeWithUniqueName(
+ String name, this.uniqueName, String message,
+ {String correction, bool hasPublishedDocs})
+ : super(name, message,
+ correction: correction, hasPublishedDocs: hasPublishedDocs);
+}
+
/**
* The error codes used for static warnings. The convention for this class is
* for the name of the error code to indicate the problem that caused the error
@@ -5813,19 +6327,74 @@
*/
class StaticWarningCode extends AnalyzerErrorCode {
/**
- * 14.1 Imports: If a name <i>N</i> is referenced by a library <i>L</i> and
- * <i>N</i> is introduced into the top level scope <i>L</i> by more than one
- * import then:
- * 1. A static warning occurs.
- * 2. If <i>N</i> is referenced as a function, getter or setter, a
- * <i>NoSuchMethodError</i> is raised.
- * 3. If <i>N</i> is referenced as a type, it is treated as a malformed type.
- *
* Parameters:
* 0: the name of the ambiguous type
* 1: the name of the first library that the type is found
* 2: the name of the second library that the type is found
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a name is referenced that is
+ // declared in two or more imported libraries.
+ //
+ // #### Example
+ //
+ // Given a library (`a.dart`) that defines a class (`C` in this example):
+ //
+ // ```dart
+ // %uri="lib/a.dart"
+ // class A {}
+ // class C {}
+ // ```
+ //
+ // And a library (`b.dart`) that defines a different class with the same name:
+ //
+ // ```dart
+ // %uri="lib/b.dart"
+ // class B {}
+ // class C {}
+ // ```
+ //
+ // The following code produces this diagnostic:
+ //
+ // ```dart
+ // import 'a.dart';
+ // import 'b.dart';
+ //
+ // void f([!C!] c1, [!C!] c2) {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If any of the libraries aren't needed, then remove the import directives
+ // for them:
+ //
+ // ```dart
+ // import 'a.dart';
+ //
+ // void f(C c1, C c2) {}
+ // ```
+ //
+ // If the name is still defined by more than one library, then add a `hide`
+ // clause to the import directives for all except one library:
+ //
+ // ```dart
+ // import 'a.dart' hide C;
+ // import 'b.dart';
+ //
+ // void f(C c1, C c2) {}
+ // ```
+ //
+ // If you must be able to reference more than one of these types, then add a
+ // prefix to each of the import directives, and qualify the references with
+ // the appropriate prefix:
+ //
+ // ```dart
+ // import 'a.dart' as a;
+ // import 'b.dart' as b;
+ //
+ // void f(a.C c1, b.C c2) {}
+ // ```
static const StaticWarningCode AMBIGUOUS_IMPORT = const StaticWarningCode(
'AMBIGUOUS_IMPORT', "The name '{0}' is defined in the libraries {1}.",
correction: "Try using 'as prefix' for one of the import directives, or "
@@ -5843,7 +6412,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because a `num` can't be
+ // assigned to a `String`:
//
// ```dart
// String f(String x) => x;
@@ -5924,13 +6494,62 @@
correction: "Try making '{0}' non-final.");
/**
- * 5 Variables: Attempting to assign to a final variable elsewhere will cause
- * a NoSuchMethodError to be thrown, because no setter is defined for it. The
- * assignment will also give rise to a static warning for the same reason.
+ * No parameters.
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a reference to a setter is
+ // found; there is no setter defined for the type; but there is a getter
+ // defined with the same name.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because there is no setter
+ // named `x` in `C`, but there is a getter named `x`:
+ //
+ // ```dart
+ // class C {
+ // int get x => 0;
+ // set y(int p) {}
+ // }
+ //
+ // void f(C c) {
+ // c.[!x!] = 1;
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If you want to invoke an existing setter, then correct the name:
+ //
+ // ```dart
+ // class C {
+ // int get x => 0;
+ // set y(int p) {}
+ // }
+ //
+ // void f(C c) {
+ // c.y = 1;
+ // }
+ // ```
+ //
+ // If you want to invoke the setter but it just doesn't exist yet, then
+ // declare it:
+ //
+ // ```dart
+ // class C {
+ // int get x => 0;
+ // set x(int p) {}
+ // set y(int p) {}
+ // }
+ //
+ // void f(C c) {
+ // c.x = 1;
+ // }
+ // ```
static const StaticWarningCode ASSIGNMENT_TO_FINAL_NO_SETTER =
const StaticWarningCode('ASSIGNMENT_TO_FINAL_NO_SETTER',
- "No setter named '{0}' in class '{1}'.",
+ "There isn’t a setter named '{0}' in class '{1}'.",
correction:
"Try correcting the name to reference an existing setter, or "
"declare the setter.");
@@ -5986,7 +6605,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `x` is a variable, not
+ // a type:
//
// ```dart
// num x = 0;
@@ -6009,13 +6629,46 @@
hasPublishedDocs: true);
/**
- * 7.4 Abstract Instance Members: It is a static warning if an abstract member
- * is declared or inherited in a concrete class.
- *
* Parameters:
* 0: the name of the abstract method
* 1: the name of the enclosing class
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a member of a concrete class is
+ // found that doesn't have a concrete implementation. Concrete classes aren't
+ // allowed to contain abstract members.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `m` is an abstract
+ // method but `C` isn't an abstract class:
+ //
+ // ```dart
+ // class C {
+ // [!void m();!]
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If it's valid to create instances of the class, provide an implementation
+ // for the member:
+ //
+ // ```dart
+ // class C {
+ // void m() {}
+ // }
+ // ```
+ //
+ // If it isn't valid to create instances of the class, mark the class as being
+ // abstract:
+ //
+ // ```dart
+ // abstract class C {
+ // void m();
+ // }
+ // ```
static const StaticWarningCode CONCRETE_CLASS_WITH_ABSTRACT_MEMBER =
const StaticWarningCode('CONCRETE_CLASS_WITH_ABSTRACT_MEMBER',
"'{0}' must have a method body because '{1}' isn't abstract.",
@@ -6136,7 +6789,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because `x` doesn't have an
+ // initializer:
//
// ```dart
// final [!x!];
@@ -6180,57 +6834,122 @@
hasPublishedDocs: true);
/**
- * 7.6.1 Generative Constructors: Each final instance variable <i>f</i>
- * declared in the immediately enclosing class must have an initializer in
- * <i>k</i>'s initializer list unless it has already been initialized by one
- * of the following means:
- * * Initialization at the declaration of <i>f</i>.
- * * Initialization by means of an initializing formal of <i>k</i>.
- * or a static warning occurs.
- *
* Parameters:
* 0: the name of the uninitialized final variable
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a class defines one or more
+ // final instance fields without initializers and has at least one constructor
+ // that doesn't initialize those fields. All final instance fields must be
+ // initialized when the instance is created, either by the field's initializer
+ // or by the constructor.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic:
+ //
+ // ```dart
+ // class C {
+ // final String value;
+ //
+ // [!C!]();
+ // }
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the value should be passed in to the constructor directly, then use a
+ // field formal parameter to initialize the field `value`:
+ //
+ // ```dart
+ // class C {
+ // final String value;
+ //
+ // C(this.value);
+ // }
+ // ```
+ //
+ // If the value should be computed indirectly from a value provided by the
+ // caller, then add a parameter and include an initializer:
+ //
+ // ```dart
+ // class C {
+ // final String value;
+ //
+ // C(Object o) : value = o.toString();
+ // }
+ // ```
+ //
+ // If the value of the field doesn't depend on values that can be passed to
+ // the constructor, then add an initializer for the field as part of the field
+ // declaration:
+ //
+ // ```dart
+ // class C {
+ // final String value = '';
+ //
+ // C();
+ // }
+ // ```
+ //
+ // If the value of the field doesn't depend on values that can be passed to
+ // the constructor but different constructors need to initialize it to
+ // different values, then add an initializer for the field in the initializer
+ // list:
+ //
+ // ```dart
+ // class C {
+ // final String value;
+ //
+ // C() : value = '';
+ //
+ // C.named() : value = 'c';
+ // }
+ // ```
+ //
+ // However, if the value is the same for all instances, then consider using a
+ // static field instead of an instance field:
+ //
+ // ```dart
+ // class C {
+ // static const String value = '';
+ //
+ // C();
+ // }
+ // ```
static const StaticWarningCode FINAL_NOT_INITIALIZED_CONSTRUCTOR_1 =
- const StaticWarningCode('FINAL_NOT_INITIALIZED_CONSTRUCTOR_1',
- "The final variable '{0}' must be initialized.",
+ const StaticWarningCodeWithUniqueName(
+ 'FINAL_NOT_INITIALIZED_CONSTRUCTOR',
+ 'StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1',
+ "All final variables must be initialized, but '{0}' is not.",
correction: "Try adding an initializer for the field.");
/**
- * 7.6.1 Generative Constructors: Each final instance variable <i>f</i>
- * declared in the immediately enclosing class must have an initializer in
- * <i>k</i>'s initializer list unless it has already been initialized by one
- * of the following means:
- * * Initialization at the declaration of <i>f</i>.
- * * Initialization by means of an initializing formal of <i>k</i>.
- * or a static warning occurs.
- *
* Parameters:
* 0: the name of the uninitialized final variable
* 1: the name of the uninitialized final variable
*/
static const StaticWarningCode FINAL_NOT_INITIALIZED_CONSTRUCTOR_2 =
- const StaticWarningCode('FINAL_NOT_INITIALIZED_CONSTRUCTOR_2',
- "The final variables '{0}' and '{1}' must be initialized.",
+ const StaticWarningCodeWithUniqueName(
+ 'FINAL_NOT_INITIALIZED_CONSTRUCTOR',
+ 'StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2',
+ "All final variables must be initialized, but '{0}' and '{1}' are "
+ "not.",
correction: "Try adding initializers for the fields.");
/**
- * 7.6.1 Generative Constructors: Each final instance variable <i>f</i>
- * declared in the immediately enclosing class must have an initializer in
- * <i>k</i>'s initializer list unless it has already been initialized by one
- * of the following means:
- * * Initialization at the declaration of <i>f</i>.
- * * Initialization by means of an initializing formal of <i>k</i>.
- * or a static warning occurs.
- *
* Parameters:
* 0: the name of the uninitialized final variable
* 1: the name of the uninitialized final variable
* 2: the number of additional not initialized variables that aren't listed
*/
static const StaticWarningCode FINAL_NOT_INITIALIZED_CONSTRUCTOR_3_PLUS =
- const StaticWarningCode('FINAL_NOT_INITIALIZED_CONSTRUCTOR_3',
- "The final variables '{0}', '{1}' and {2} more must be initialized.",
+ const StaticWarningCodeWithUniqueName(
+ 'FINAL_NOT_INITIALIZED_CONSTRUCTOR',
+ 'StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_3',
+ "All final variables must be initialized, but '{0}', '{1}', and {2} "
+ "others are not.",
correction: "Try adding initializers for the fields.");
/**
@@ -6286,22 +7005,45 @@
errorSeverity: ErrorSeverity.WARNING);
/**
- * 12.6 Lists: A run-time list literal <<i>E</i>> [<i>e<sub>1</sub></i>
- * … <i>e<sub>n</sub></i>] is evaluated as follows:
- * * The operator []= is invoked on <i>a</i> with first argument <i>i</i> and
- * second argument <i>o<sub>i+1</sub></i><i>, 1 <= i <= n</i>
- *
- * 12.14.2 Binding Actuals to Formals: Let <i>T<sub>i</sub></i> be the static
- * type of <i>a<sub>i</sub></i>, let <i>S<sub>i</sub></i> be the type of
- * <i>p<sub>i</sub>, 1 <= i <= n+k</i> and let <i>S<sub>q</sub></i> be
- * the type of the named parameter <i>q</i> of <i>f</i>. It is a static
- * warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1
- * <= j <= m</i>.
- *
* Parameters:
* 0: the actual type of the list element
* 1: the expected type of the list element
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when the type of an element in a list
+ // literal isn't assignable to the element type of the list.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because `2.5` is a double, and
+ // the list can hold only integers:
+ //
+ // ```dart
+ // List<int> x = [1, [!2.5!], 3];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If you intended to add a different object to the list, then replace the
+ // element with an expression that computes the intended object:
+ //
+ // ```dart
+ // List<int> x = [1, 2, 3];
+ // ```
+ //
+ // If the object shouldn't be in the list, then remove the element:
+ //
+ // ```dart
+ // List<int> x = [1, 3];
+ // ```
+ //
+ // If the object being computed is correct, then widen the element type of the
+ // list to allow all of the different types of objects it needs to contain:
+ //
+ // ```dart
+ // List<num> x = [1, 2.5, 3];
+ // ```
static const StaticWarningCode LIST_ELEMENT_TYPE_NOT_ASSIGNABLE =
const StaticWarningCode('LIST_ELEMENT_TYPE_NOT_ASSIGNABLE',
"The element type '{0}' can't be assigned to the list type '{1}'.");
@@ -6385,16 +7127,10 @@
correction: "Try adding a case clause for the missing constant, or "
"adding a default clause.");
- /**
- * 13.12 Return: It is a static warning if a function contains both one or
- * more return statements of the form <i>return;</i> and one or more return
- * statements of the form <i>return e;</i>.
- */
+ @Deprecated('No longer an error in the spec and no longer generated')
static const StaticWarningCode MIXED_RETURN_TYPES = const StaticWarningCode(
'MIXED_RETURN_TYPES',
"Functions can't include return statements both with and without values.",
- // TODO(brianwilkerson) Split this error code depending on whether the
- // function declares a return type.
correction: "Try making all the return statements consistent "
"(either include a value or not).");
@@ -6475,19 +7211,6 @@
"Try using one of the named constructors defined in '{0}'.");
/**
- * 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract
- * class inherits an abstract method.
- *
- * 7.10 Superinterfaces: Let <i>C</i> be a concrete class that does not
- * declare its own <i>noSuchMethod()</i> method. It is a static warning if the
- * implicit interface of <i>C</i> includes an instance member <i>m</i> of type
- * <i>F</i> and <i>C</i> does not declare or inherit a corresponding instance
- * member <i>m</i> of type <i>F'</i> such that <i>F' <: F</i>.
- *
- * 7.4 Abstract Instance Members: It is a static warning if an abstract member
- * is declared or inherited in a concrete class unless that member overrides a
- * concrete one.
- *
* Parameters:
* 0: the name of the first member
* 1: the name of the second member
@@ -6497,27 +7220,15 @@
*/
static const StaticWarningCode
NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS =
- const StaticWarningCode(
- 'NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS',
- "Missing concrete implementations of {0}, {1}, {2}, {3} and {4} "
- "more.",
+ const StaticWarningCodeWithUniqueName(
+ 'NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER',
+ 'StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS',
+ "Missing concrete implementations of '{0}', '{1}', '{2}', '{3}', and "
+ "{4} more.",
correction: "Try implementing the missing methods, or make the class "
"abstract.");
/**
- * 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract
- * class inherits an abstract method.
- *
- * 7.10 Superinterfaces: Let <i>C</i> be a concrete class that does not
- * declare its own <i>noSuchMethod()</i> method. It is a static warning if the
- * implicit interface of <i>C</i> includes an instance member <i>m</i> of type
- * <i>F</i> and <i>C</i> does not declare or inherit a corresponding instance
- * member <i>m</i> of type <i>F'</i> such that <i>F' <: F</i>.
- *
- * 7.4 Abstract Instance Members: It is a static warning if an abstract member
- * is declared or inherited in a concrete class unless that member overrides a
- * concrete one.
- *
* Parameters:
* 0: the name of the first member
* 1: the name of the second member
@@ -6526,50 +7237,86 @@
*/
static const StaticWarningCode
NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR =
- const StaticWarningCode(
- 'NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR',
- "Missing concrete implementations of {0}, {1}, {2} and {3}.",
+ const StaticWarningCodeWithUniqueName(
+ 'NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER',
+ 'StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR',
+ "Missing concrete implementations of '{0}', '{1}', '{2}', and '{3}'.",
correction: "Try implementing the missing methods, or make the class "
"abstract.");
/**
- * 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract
- * class inherits an abstract method.
- *
- * 7.10 Superinterfaces: Let <i>C</i> be a concrete class that does not
- * declare its own <i>noSuchMethod()</i> method. It is a static warning if the
- * implicit interface of <i>C</i> includes an instance member <i>m</i> of type
- * <i>F</i> and <i>C</i> does not declare or inherit a corresponding instance
- * member <i>m</i> of type <i>F'</i> such that <i>F' <: F</i>.
- *
- * 7.4 Abstract Instance Members: It is a static warning if an abstract member
- * is declared or inherited in a concrete class unless that member overrides a
- * concrete one.
- *
* Parameters:
* 0: the name of the member
*/
+ // #### Description
+ //
+ // The analyzer produces this diagnostic when a concrete class inherits one or
+ // more abstract members, and doesn't provide or inherit an implementation for
+ // at least one of those abstract members.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the class `B` doesn't
+ // have a concrete implementation of `m`:
+ //
+ // ```dart
+ // abstract class A {
+ // void m();
+ // }
+ //
+ // class [!B!] extends A {}
+ // ```
+ //
+ // #### Common fixes
+ //
+ // If the subclass can provide a concrete implementation for some or all of
+ // the abstract inherited members, then add the concrete implementations:
+ //
+ // ```dart
+ // abstract class A {
+ // void m();
+ // }
+ //
+ // class B extends A {
+ // void m() {}
+ // }
+ // ```
+ //
+ // If there is a mixin that provides an implementation of the inherited
+ // methods, then apply the mixin to the subclass:
+ //
+ // ```dart
+ // abstract class A {
+ // void m();
+ // }
+ //
+ // class B extends A with M {}
+ //
+ // mixin M {
+ // void m() {}
+ // }
+ // ```
+ //
+ // If the subclass can't provide a concrete implementation for all of the
+ // abstract inherited members, then mark the subclass as being abstract:
+ //
+ // ```dart
+ // abstract class A {
+ // void m();
+ // }
+ //
+ // abstract class B extends A {}
+ // ```
static const StaticWarningCode
- NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE = const StaticWarningCode(
- 'NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE',
- "Missing concrete implementation of {0}.",
+ NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE =
+ const StaticWarningCodeWithUniqueName(
+ 'NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER',
+ 'StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE',
+ "Missing concrete implementation of '{0}'.",
correction: "Try implementing the missing method, or make the class "
"abstract.");
/**
- * 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract
- * class inherits an abstract method.
- *
- * 7.10 Superinterfaces: Let <i>C</i> be a concrete class that does not
- * declare its own <i>noSuchMethod()</i> method. It is a static warning if the
- * implicit interface of <i>C</i> includes an instance member <i>m</i> of type
- * <i>F</i> and <i>C</i> does not declare or inherit a corresponding instance
- * member <i>m</i> of type <i>F'</i> such that <i>F' <: F</i>.
- *
- * 7.4 Abstract Instance Members: It is a static warning if an abstract member
- * is declared or inherited in a concrete class unless that member overrides a
- * concrete one.
- *
* Parameters:
* 0: the name of the first member
* 1: the name of the second member
@@ -6577,34 +7324,24 @@
*/
static const StaticWarningCode
NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE =
- const StaticWarningCode(
- 'NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE',
- "Missing concrete implementations of {0}, {1} and {2}.",
+ const StaticWarningCodeWithUniqueName(
+ 'NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER',
+ 'StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE',
+ "Missing concrete implementations of '{0}', '{1}', and '{2}'.",
correction: "Try implementing the missing methods, or make the class "
"abstract.");
/**
- * 7.9.1 Inheritance and Overriding: It is a static warning if a non-abstract
- * class inherits an abstract method.
- *
- * 7.10 Superinterfaces: Let <i>C</i> be a concrete class that does not
- * declare its own <i>noSuchMethod()</i> method. It is a static warning if the
- * implicit interface of <i>C</i> includes an instance member <i>m</i> of type
- * <i>F</i> and <i>C</i> does not declare or inherit a corresponding instance
- * member <i>m</i> of type <i>F'</i> such that <i>F' <: F</i>.
- *
- * 7.4 Abstract Instance Members: It is a static warning if an abstract member
- * is declared or inherited in a concrete class unless that member overrides a
- * concrete one.
- *
* Parameters:
* 0: the name of the first member
* 1: the name of the second member
*/
static const StaticWarningCode
- NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO = const StaticWarningCode(
- 'NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO',
- "Missing concrete implementations of {0} and {1}.",
+ NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO =
+ const StaticWarningCodeWithUniqueName(
+ 'NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER',
+ 'StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO',
+ "Missing concrete implementations of '{0}' and '{1}'.",
correction: "Try implementing the missing methods, or make the class "
"abstract.");
@@ -6808,7 +7545,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the name `Srting` isn't
+ // defined:
//
// ```dart
// void f(Object o) {
@@ -6878,7 +7616,8 @@
//
// #### Example
//
- // The following code produces this diagnostic:
+ // The following code produces this diagnostic because the name `rihgt` isn't
+ // defined:
//
// ```dart
// int min(int left, int right) => left <= [!rihgt!] ? left : right;
@@ -7036,6 +7775,17 @@
ErrorType get type => ErrorType.STATIC_WARNING;
}
+class StaticWarningCodeWithUniqueName extends StaticWarningCode {
+ @override
+ final String uniqueName;
+
+ const StaticWarningCodeWithUniqueName(
+ String name, this.uniqueName, String message,
+ {String correction, bool hasPublishedDocs})
+ : super(name, message,
+ correction: correction, hasPublishedDocs: hasPublishedDocs);
+}
+
/**
* This class has Strong Mode specific error codes.
*
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index 16ae004..fc45c4b 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -20,7 +20,7 @@
class InheritanceOverrideVerifier {
static const _missingOverridesKey = 'missingOverrides';
- final TypeSystem _typeSystem;
+ final TypeSystemImpl _typeSystem;
final TypeProvider _typeProvider;
final InheritanceManager3 _inheritance;
final ErrorReporter _reporter;
@@ -84,7 +84,7 @@
}
class _ClassVerifier {
- final TypeSystem typeSystem;
+ final TypeSystemImpl typeSystem;
final TypeProvider typeProvider;
final InheritanceManager3 inheritance;
final ErrorReporter reporter;
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
index 8aeb435..411e42a 100644
--- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -13,7 +13,7 @@
/// Verifier for [CollectionElement]s in list, set, or map literals.
class LiteralElementVerifier {
final TypeProvider typeProvider;
- final TypeSystem typeSystem;
+ final TypeSystemImpl typeSystem;
final ErrorReporter errorReporter;
final FeatureSet featureSet;
final bool Function(Expression) checkForUseOfVoidResult;
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index c5ef35c..c19222c 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -17,7 +17,7 @@
class TypeArgumentsVerifier {
final AnalysisOptionsImpl _options;
- final TypeSystem _typeSystem;
+ final TypeSystemImpl _typeSystem;
final ErrorReporter _errorReporter;
TypeArgumentsVerifier(this._options, this._typeSystem, this._errorReporter);
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index c40153a2..feb7883 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -2142,14 +2142,13 @@
// Peek to leave type parameters on top of stack.
List<TypeParameter> typeParameters = peek();
- TypeParameter typeParameter = typeParameters[index];
- typeParameter
- ..extendsKeyword = extendsOrSuper
- ..bound = bound;
- if (typeParameter is TypeParameterImpl) {
- typeParameter.varianceKeyword = variance;
- }
+ // TODO (kallentu) : Clean up TypeParameterImpl casting once variance is
+ // added to the interface.
+ (typeParameters[index] as TypeParameterImpl)
+ ..extendsKeyword = extendsOrSuper
+ ..bound = bound
+ ..varianceKeyword = variance;
}
@override
@@ -3413,20 +3412,10 @@
List<T> popTypedList<T>(int count, [List<T> list]) {
if (count == 0) return null;
- assert(stack.arrayLength >= count);
-
- final table = stack.array;
- final length = stack.arrayLength;
+ assert(stack.length >= count);
final tailList = list ?? new List<T>.filled(count, null, growable: true);
- final startIndex = length - count;
- for (int i = 0; i < count; i++) {
- final value = table[startIndex + i];
- tailList[i] = value is NullValue ? null : value;
- table[startIndex + i] = null;
- }
- stack.arrayLength -= count;
-
+ stack.popList(count, tailList, null);
return tailList;
}
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index 385b75f..eb81df0 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -278,10 +278,6 @@
offset,
length);
return;
- case "TYPE_PARAMETER_ON_CONSTRUCTOR":
- errorReporter?.reportErrorForOffset(
- CompileTimeErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, offset, length);
- return;
case "UNDEFINED_CLASS":
errorReporter?.reportErrorForOffset(
CompileTimeErrorCode.UNDEFINED_CLASS, offset, length);
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index ea8336f..2cf8f0e 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -12,8 +12,7 @@
import 'package:analyzer/src/generated/engine.dart' show RecordingErrorListener;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/source.dart' show Source;
-import 'package:analyzer/src/generated/type_system.dart'
- show Dart2TypeSystem, TypeSystem;
+import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
export 'package:analyzer/dart/analysis/declared_variables.dart';
export 'package:analyzer/dart/constant/value.dart';
@@ -110,7 +109,7 @@
/**
* The type system primitives.
*/
- final TypeSystem _typeSystem;
+ final TypeSystemImpl _typeSystem;
/**
* Initialize a newly created evaluator to evaluate expressions in the given
@@ -118,8 +117,14 @@
* types.
*/
ConstantEvaluator(this._source, TypeProvider typeProvider,
- {TypeSystem typeSystem})
- : _typeSystem = typeSystem ?? new Dart2TypeSystem(typeProvider),
+ {TypeSystemImpl typeSystem})
+ : _typeSystem = typeSystem ??
+ TypeSystemImpl(
+ implicitCasts: true,
+ isNonNullableByDefault: false,
+ strictInference: false,
+ typeProvider: typeProvider,
+ ),
_typeProvider = typeProvider;
EvaluationResult evaluate(Expression expression) {
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index cb5fd6a..4f3f96f 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -18,7 +18,6 @@
SimpleIdentifierImpl;
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
@@ -89,11 +88,6 @@
*/
class ElementResolver extends SimpleAstVisitor<void> {
/**
- * The manager for the inheritance mappings.
- */
- final InheritanceManager3 _inheritance;
-
- /**
* The resolver driving this participant.
*/
final ResolverVisitor _resolver;
@@ -127,8 +121,7 @@
* resolve the nodes in a compilation unit.
*/
ElementResolver(this._resolver, {this.reportConstEvaluationErrors: true})
- : _inheritance = _resolver.inheritance,
- _definingLibrary = _resolver.definingLibrary,
+ : _definingLibrary = _resolver.definingLibrary,
_extensionResolver = _resolver.extensionResolver,
_methodInvocationResolver = new MethodInvocationResolver(_resolver) {
_dynamicType = _resolver.typeProvider.dynamicType;
@@ -332,8 +325,10 @@
SimpleIdentifier name = node.name;
if (name == null) {
constructor = type.lookUpConstructor(null, _definingLibrary);
+ constructor = _resolver.toLegacyElement(constructor);
} else {
constructor = type.lookUpConstructor(name.name, _definingLibrary);
+ constructor = _resolver.toLegacyElement(constructor);
name.staticElement = constructor;
}
node.staticElement = constructor;
@@ -600,6 +595,7 @@
"${node.identifier.name}=", node.identifier.offset - 1)));
element = _resolver.nameScope.lookup(setterName, _definingLibrary);
}
+ element = _resolver.toLegacyElement(element);
if (element == null && _resolver.nameScope.shouldIgnoreUndefined(node)) {
return;
}
@@ -898,6 +894,7 @@
String superName = name?.name;
ConstructorElement element =
superType.lookUpConstructor(superName, _definingLibrary);
+ element = _resolver.toLegacyElement(element);
if (element == null || !element.isAccessibleIn(_definingLibrary)) {
if (name != null) {
_resolver.errorReporter.reportErrorForNode(
@@ -1241,7 +1238,7 @@
}
_PropertyResolver _newPropertyResolver() {
- return _PropertyResolver(_resolver.typeProvider, _inheritance,
+ return _PropertyResolver(_resolver, _resolver.typeProvider,
_definingLibrary, _extensionResolver);
}
@@ -1552,6 +1549,7 @@
element ??= extension.getGetter(memberName);
element ??= extension.getMethod(memberName);
if (element != null) {
+ element = _resolver.toLegacyElement(element);
propertyName.staticElement = element;
_checkForStaticAccessToInstanceMember(propertyName, element);
} else {
@@ -1566,6 +1564,7 @@
if (propertyName.inSetterContext()) {
var element = extension.getSetter(memberName);
if (element != null) {
+ element = _resolver.toLegacyElement(element);
propertyName.staticElement = element;
_checkForStaticAccessToInstanceMember(propertyName, element);
} else {
@@ -1610,6 +1609,7 @@
}
if (element != null) {
+ element = _resolver.toLegacyElement(element);
propertyName.staticElement = element;
_checkForStaticAccessToInstanceMember(propertyName, element);
} else {
@@ -1630,6 +1630,7 @@
}
if (element != null) {
+ element = _resolver.toLegacyElement(element);
propertyName.staticElement = element;
_checkForStaticAccessToInstanceMember(propertyName, element);
} else {
@@ -1658,6 +1659,7 @@
setter: false, concrete: true, forSuperInvocation: true);
if (element != null) {
+ element = _resolver.toLegacyElement(element);
propertyName.staticElement = element;
} else {
// We were not able to find the concrete dispatch target.
@@ -1693,6 +1695,7 @@
setter: true, concrete: true, forSuperInvocation: true);
if (element != null) {
+ element = _resolver.toLegacyElement(element);
propertyName.staticElement = element;
} else {
// We were not able to find the concrete dispatch target.
@@ -1799,6 +1802,7 @@
*/
Element _resolveSimpleIdentifier(SimpleIdentifier identifier) {
Element element = _resolver.nameScope.lookup(identifier, _definingLibrary);
+ element = _resolver.toLegacyElement(element);
if (element is PropertyAccessorElement && identifier.inSetterContext()) {
PropertyInducingElement variable =
(element as PropertyAccessorElement).variable;
@@ -2006,16 +2010,16 @@
/// Helper for resolving properties (getters, setters, or methods).
class _PropertyResolver {
+ final ResolverVisitor _resolver;
final TypeProvider _typeProvider;
- final InheritanceManager3 _inheritance;
final LibraryElement _definingLibrary;
final ExtensionMemberResolver _extensionResolver;
ResolutionResult result = ResolutionResult.none;
_PropertyResolver(
+ this._resolver,
this._typeProvider,
- this._inheritance,
this._definingLibrary,
this._extensionResolver,
);
@@ -2073,6 +2077,13 @@
result = _extensionResolver.findExtension(type, name, errorNode);
}
+ if (result.isSingle) {
+ result = ResolutionResult(
+ getter: _resolver.toLegacyElement(result.getter),
+ setter: _resolver.toLegacyElement(result.setter),
+ );
+ }
+
return result;
}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index f2af195..81081ba 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -10,7 +10,6 @@
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/source/error_processor.dart';
-import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/java_engine.dart';
@@ -19,6 +18,7 @@
import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/services/lint.dart';
import 'package:analyzer/src/summary/api_signature.dart';
+import 'package:meta/meta.dart';
import 'package:path/path.dart' as pathos;
import 'package:pub_semver/pub_semver.dart';
@@ -151,11 +151,6 @@
StringToken.canonicalizer.clear();
}
- /// Create and return a new context in which analysis can be performed.
- AnalysisContext createAnalysisContext() {
- return new AnalysisContextImpl();
- }
-
/// A utility method that clients can use to process all of the required
/// plugins. This method can only be used by clients that do not need to
/// process any other plugins.
@@ -853,8 +848,11 @@
/// Additional behavior for an analysis context that is required by internal
/// users of the context.
abstract class InternalAnalysisContext implements AnalysisContext {
- /// Sets the [TypeProvider] for this context.
- void set typeProvider(TypeProvider typeProvider);
+ /// Sets the [TypeProvider]s for this context.
+ void setTypeProviders({
+ @required TypeProvider legacy,
+ @required TypeProvider nonNullableByDefault,
+ });
}
/// Container with global [AnalysisContext] performance statistics.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index b7ce355..341e266 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -16,6 +16,7 @@
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
+import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
@@ -80,7 +81,7 @@
/**
* The type system primitives
*/
- TypeSystem _typeSystem;
+ TypeSystemImpl _typeSystem;
/**
* The manager for the inheritance mappings.
@@ -181,16 +182,6 @@
bool _hasExtUri = false;
/**
- * This is set to `false` on the entry of every [BlockFunctionBody], and is
- * restored to the enclosing value on exit. The value is used in
- * [_checkForMixedReturns] to prevent both
- * [StaticWarningCode.MIXED_RETURN_TYPES] and
- * [StaticWarningCode.RETURN_WITHOUT_VALUE] from being generated in the same
- * function body.
- */
- bool _hasReturnWithoutValue = false;
-
- /**
* The class containing the AST nodes being visited, or `null` if we are not
* in the scope of a class.
*/
@@ -446,8 +437,6 @@
void visitBlockFunctionBody(BlockFunctionBody node) {
bool wasInAsync = _inAsync;
bool wasInGenerator = _inGenerator;
- bool previousHasReturnWithoutValue = _hasReturnWithoutValue;
- _hasReturnWithoutValue = false;
List<ReturnStatement> previousReturnsWith = _returnsWith;
List<ReturnStatement> previousReturnsWithout = _returnsWithout;
try {
@@ -456,13 +445,11 @@
_returnsWith = new List<ReturnStatement>();
_returnsWithout = new List<ReturnStatement>();
super.visitBlockFunctionBody(node);
- _checkForMixedReturns(node);
} finally {
_inAsync = wasInAsync;
_inGenerator = wasInGenerator;
_returnsWith = previousReturnsWith;
_returnsWithout = previousReturnsWithout;
- _hasReturnWithoutValue = previousHasReturnWithoutValue;
}
}
@@ -720,6 +707,7 @@
}
try {
_checkForNotInitializedNonNullableStaticField(node);
+ _checkForWrongTypeParameterVarianceInField(node);
super.visitFieldDeclaration(node);
} finally {
_isInStaticVariableDeclaration = false;
@@ -1040,6 +1028,7 @@
_checkForIllegalReturnType(returnType);
_checkForImplicitDynamicReturn(node, node.declaredElement);
_checkForMustCallSuper(node);
+ _checkForWrongTypeParameterVarianceInMethod(node);
super.visitMethodDeclaration(node);
} finally {
_enclosingFunction = previousFunction;
@@ -1480,10 +1469,6 @@
* constructor and the return type is not assignable to `null`; that is, we
* don't have `return;` if the enclosing method has a non-void containing
* return type.
- *
- * See [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR],
- * [StaticWarningCode.RETURN_WITHOUT_VALUE], and
- * [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE].
*/
void _checkForAllEmptyReturnStatementErrorCodes(
ReturnStatement statement, DartType expectedReturnType) {
@@ -1498,7 +1483,6 @@
return;
}
// If we reach here, this is an invalid return
- _hasReturnWithoutValue = true;
_errorReporter.reportErrorForNode(
StaticWarningCode.RETURN_WITHOUT_VALUE, statement);
return;
@@ -1781,10 +1765,6 @@
*
* Check that the return type matches the type of the declared return type in
* the enclosing method or function.
- *
- * See [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR],
- * [StaticWarningCode.RETURN_WITHOUT_VALUE], and
- * [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE].
*/
void _checkForAllReturnStatementErrorCodes(ReturnStatement statement) {
FunctionType functionType = _enclosingFunction?.type;
@@ -2261,26 +2241,33 @@
void _checkForConflictingGenerics(NamedCompilationUnitMember node) {
var visitedClasses = <ClassElement>[];
var interfaces = <ClassElement, InterfaceType>{};
+
void visit(InterfaceType type) {
if (type == null) return;
+
var element = type.element;
if (visitedClasses.contains(element)) return;
visitedClasses.add(element);
+
if (element.typeParameters.isNotEmpty) {
+ type = _toLegacyType(type);
var oldType = interfaces[element];
if (oldType == null) {
interfaces[element] = type;
} else if (type != oldType) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
- node,
- [_enclosingClass.name, oldType, type]);
+ CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES,
+ node,
+ [_enclosingClass.name, oldType, type],
+ );
}
}
+
visit(type.superclass);
type.mixins.forEach(visit);
type.superclassConstraints.forEach(visit);
type.interfaces.forEach(visit);
+
visitedClasses.removeLast();
}
@@ -2624,29 +2611,13 @@
*/
void _checkForDeferredImportOfExtensions(
ImportDirective directive, ImportElement importElement) {
- List<String> shownNames = [];
- List<String> hiddenNames = [];
-
- Iterable<String> namesOf(List<SimpleIdentifier> identifiers) =>
- identifiers.map((identifier) => identifier.name);
- for (Combinator combinator in directive.combinators) {
- if (combinator is HideCombinator) {
- hiddenNames.addAll(namesOf(combinator.hiddenNames));
- } else if (combinator is ShowCombinator) {
- shownNames.addAll(namesOf(combinator.shownNames));
- }
- }
- for (Element element in importElement.importedLibrary.topLevelElements) {
+ for (var element in importElement.namespace.definedNames.values) {
if (element is ExtensionElement) {
- String name = element.name;
- if (name != null &&
- name.isNotEmpty &&
- (shownNames.contains(name) ||
- (shownNames.isEmpty && !hiddenNames.contains(name)))) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION, directive.uri);
- return;
- }
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION,
+ directive.uri,
+ );
+ return;
}
}
}
@@ -3789,30 +3760,6 @@
}
/**
- * Verify that the given function [body] does not contain return statements
- * that both have and do not have return values.
- *
- * See [StaticWarningCode.MIXED_RETURN_TYPES].
- */
- void _checkForMixedReturns(BlockFunctionBody body) {
- if (_hasReturnWithoutValue) {
- return;
- }
- var nonVoidReturnsWith =
- _returnsWith.where((stmt) => !getStaticType(stmt.expression).isVoid);
- if (nonVoidReturnsWith.isNotEmpty && _returnsWithout.isNotEmpty) {
- for (ReturnStatement returnWith in nonVoidReturnsWith) {
- _errorReporter.reportErrorForToken(
- StaticWarningCode.MIXED_RETURN_TYPES, returnWith.returnKeyword);
- }
- for (ReturnStatement returnWithout in _returnsWithout) {
- _errorReporter.reportErrorForToken(
- StaticWarningCode.MIXED_RETURN_TYPES, returnWithout.returnKeyword);
- }
- }
- }
-
- /**
* Verify that the given mixin does not have an explicitly declared
* constructor. The [mixinName] is the node to report problem on. The
* [mixinElement] is the mixing to evaluate.
@@ -4717,8 +4664,6 @@
*
* This method is called both by [_checkForAllReturnStatementErrorCodes]
* and [visitExpressionFunctionBody].
- *
- * See [StaticTypeWarningCode.RETURN_OF_INVALID_TYPE].
*/
void _checkForReturnOfInvalidType(
Expression returnExpression, DartType expectedType,
@@ -4746,9 +4691,14 @@
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
returnExpression,
[expressionType, expectedType]);
+ } else if (_enclosingFunction is MethodElement) {
+ _errorReporter.reportTypeErrorForNode(
+ StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_METHOD,
+ returnExpression,
+ [expressionType, expectedType, displayName]);
} else {
_errorReporter.reportTypeErrorForNode(
- StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
+ StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION,
returnExpression,
[expressionType, expectedType, displayName]);
}
@@ -5299,18 +5249,112 @@
}
}
+ void _checkForWrongTypeParameterVarianceInField(FieldDeclaration node) {
+ if (_enclosingClass != null) {
+ for (var typeParameter in _enclosingClass.typeParameters) {
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ if (!(typeParameter as TypeParameterElementImpl).isLegacyCovariant) {
+ var fields = node.fields;
+ var fieldElement = fields.variables.first.declaredElement;
+ var fieldName = fields.variables.first.name;
+ Variance fieldVariance = Variance(typeParameter, fieldElement.type);
+
+ _checkForWrongVariancePosition(
+ fieldVariance, typeParameter, fieldName);
+ if (!fields.isFinal && node.covariantKeyword == null) {
+ _checkForWrongVariancePosition(
+ Variance.contravariant.combine(fieldVariance),
+ typeParameter,
+ fieldName);
+ }
+ }
+ }
+ }
+ }
+
+ void _checkForWrongTypeParameterVarianceInMethod(MethodDeclaration method) {
+ // Only need to report errors for parameters with explicitly defined type
+ // parameters in classes or mixins.
+ if (_enclosingClass != null) {
+ for (var typeParameter in _enclosingClass.typeParameters) {
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ if (!(typeParameter as TypeParameterElementImpl).isLegacyCovariant) {
+ if (method.typeParameters != null) {
+ for (var methodTypeParameter
+ in method.typeParameters.typeParameters) {
+ Variance methodTypeParameterVariance = Variance.invariant.combine(
+ Variance(typeParameter, methodTypeParameter.bound.type));
+ _checkForWrongVariancePosition(methodTypeParameterVariance,
+ typeParameter, methodTypeParameter);
+ }
+ }
+ if (method.parameters != null) {
+ for (int i = 0; i < method.parameters.parameters.length; i++) {
+ var methodParameterElement =
+ method.parameters.parameterElements[i];
+ var methodParameterNode = method.parameters.parameters[i];
+ if (!methodParameterElement.isCovariant) {
+ Variance methodParameterVariance = Variance.contravariant
+ .combine(
+ Variance(typeParameter, methodParameterElement.type));
+ _checkForWrongVariancePosition(methodParameterVariance,
+ typeParameter, methodParameterNode);
+ }
+ }
+ }
+ if (method.returnType != null) {
+ Variance methodReturnTypeVariance =
+ Variance(typeParameter, method.returnType.type);
+ _checkForWrongVariancePosition(
+ methodReturnTypeVariance, typeParameter, method.returnType);
+ }
+ }
+ }
+ }
+ }
+
void _checkForWrongTypeParameterVarianceInSuperinterfaces() {
void checkOne(DartType superInterface) {
if (superInterface != null) {
for (var typeParameter in _enclosingClass.typeParameters) {
- var variance = Variance(typeParameter, superInterface);
- if (variance.isContravariant || variance.isInvariant) {
- _errorReporter.reportErrorForElement(
- CompileTimeErrorCode
- .WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
- typeParameter,
- [typeParameter.name, superInterface],
- );
+ var superVariance = Variance(typeParameter, superInterface);
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ var typeParameterElementImpl =
+ typeParameter as TypeParameterElementImpl;
+ // Let `D` be a class or mixin declaration, let `S` be a direct
+ // superinterface of `D`, and let `X` be a type parameter declared by
+ // `D`.
+ // If `X` is an `out` type parameter, it can only occur in `S` in an
+ // covariant or unrelated position.
+ // If `X` is an `in` type parameter, it can only occur in `S` in an
+ // contravariant or unrelated position.
+ // If `X` is an `inout` type parameter, it can occur in `S` in any
+ // position.
+ if (!superVariance
+ .greaterThanOrEqual(typeParameterElementImpl.variance)) {
+ if (!typeParameterElementImpl.isLegacyCovariant) {
+ _errorReporter.reportErrorForElement(
+ CompileTimeErrorCode
+ .WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ typeParameter,
+ [
+ typeParameter.name,
+ typeParameterElementImpl.variance.toKeywordString(),
+ superVariance.toKeywordString(),
+ superInterface
+ ],
+ );
+ } else {
+ _errorReporter.reportErrorForElement(
+ CompileTimeErrorCode
+ .WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ typeParameter,
+ [typeParameter.name, superInterface],
+ );
+ }
}
}
}
@@ -5323,6 +5367,38 @@
}
/**
+ * Check for invalid variance positions in members of a class or mixin.
+ *
+ * Let `C` be a class or mixin declaration with type parameter `T`.
+ * If `T` is an `out` type parameter then `T` can only appear in covariant
+ * positions within the accessors and methods of `C`.
+ * If `T` is an `in` type parameter then `T` can only appear in contravariant
+ * positions within the accessors and methods of `C`.
+ * If `T` is an `inout` type parameter or a type parameter with no explicit
+ * variance modifier then `T` can appear in any variant position within the
+ * accessors and methods of `C`.
+ *
+ * Errors should only be reported in classes and mixins since those are the
+ * only components that allow explicit variance modifiers.
+ */
+ void _checkForWrongVariancePosition(
+ Variance variance, TypeParameterElement typeParameter, AstNode node) {
+ TypeParameterElementImpl typeParameterImpl =
+ typeParameter as TypeParameterElementImpl;
+ if (!variance.greaterThanOrEqual(typeParameterImpl.variance)) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_POSITION,
+ node,
+ [
+ typeParameterImpl.variance.toKeywordString(),
+ typeParameterImpl.name,
+ variance.toKeywordString()
+ ],
+ );
+ }
+ }
+
+ /**
* Check for a type mis-match between the yielded type and the declared
* return type of a generator function.
*
@@ -5879,6 +5955,13 @@
return null;
}
+ /// If in a legacy library, return the legacy version of the [type].
+ /// Otherwise, return the original type.
+ DartType _toLegacyType(DartType type) {
+ if (_isNonNullable) return type;
+ return NullabilityEliminator.perform(type);
+ }
+
/**
* Return [FieldElement]s that are declared in the [ClassDeclaration] with
* the given [constructor], but are not initialized.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 8a3ddfc..08aaa19 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -21,7 +21,9 @@
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
+import 'package:analyzer/src/dart/element/member.dart'
+ show ConstructorMember, ExecutableMember, Member;
+import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/resolver/exit_detector.dart';
@@ -73,7 +75,7 @@
final InterfaceType _nullType;
/// The type system primitives
- final TypeSystem _typeSystem;
+ final TypeSystemImpl _typeSystem;
/// The inheritance manager to access interface type hierarchy.
final InheritanceManager3 _inheritanceManager;
@@ -104,13 +106,19 @@
this._currentLibrary,
CompilationUnit unit,
String content, {
- TypeSystem typeSystem,
+ TypeSystemImpl typeSystem,
@required InheritanceManager3 inheritanceManager,
ResourceProvider resourceProvider,
DeclaredVariables declaredVariables,
AnalysisOptions analysisOptions,
}) : _nullType = typeProvider.nullType,
- _typeSystem = typeSystem ?? new Dart2TypeSystem(typeProvider),
+ _typeSystem = typeSystem ??
+ TypeSystemImpl(
+ implicitCasts: true,
+ isNonNullableByDefault: false,
+ strictInference: false,
+ typeProvider: typeProvider,
+ ),
_isNonNullable = unit.featureSet.isEnabled(Feature.non_nullable),
_strictInference =
(analysisOptions as AnalysisOptionsImpl).strictInference,
@@ -1077,7 +1085,8 @@
if (flattenedType.isDartAsyncFutureOr) {
flattenedType = (flattenedType as InterfaceType).typeArguments[0];
}
- if (flattenedType.isDynamic ||
+ if (flattenedType.isBottom ||
+ flattenedType.isDynamic ||
flattenedType.isDartCoreNull ||
flattenedType.isVoid) {
return;
@@ -1519,7 +1528,7 @@
final ErrorReporter _errorReporter;
/// The type system for this visitor
- final TypeSystem _typeSystem;
+ final TypeSystemImpl _typeSystem;
/// The object used to track the usage of labels within a given label scope.
_LabelTracker labelTracker;
@@ -1531,8 +1540,14 @@
/// to the given [errorReporter] and will use the given [typeSystem] if one is
/// provided.
DeadCodeVerifier(this._errorReporter, FeatureSet featureSet,
- {TypeSystem typeSystem})
- : this._typeSystem = typeSystem ?? new Dart2TypeSystem(null),
+ {TypeSystemImpl typeSystem})
+ : this._typeSystem = typeSystem ??
+ TypeSystemImpl(
+ implicitCasts: true,
+ isNonNullableByDefault: false,
+ strictInference: false,
+ typeProvider: null,
+ ),
_isNonNullableUnit = featureSet.isEnabled(Feature.non_nullable);
@override
@@ -2060,6 +2075,10 @@
return;
}
Element element = node.staticElement;
+ // Store un-parameterized members.
+ if (element is ExecutableMember) {
+ element = element.declaration;
+ }
bool isIdentifierRead = _isReadIdentifier(node);
if (element is PropertyAccessorElement &&
element.isSynthetic &&
@@ -2072,12 +2091,20 @@
}
} else {
_useIdentifierElement(node);
- if (element == null ||
- element.enclosingElement is ClassElement &&
- !identical(element, _enclosingExec)) {
- usedElements.members.add(node.name);
+ if (element == null) {
if (isIdentifierRead) {
- usedElements.readMembers.add(node.name);
+ usedElements.unresolvedReadMembers.add(node.name);
+ }
+ } else if (element.enclosingElement is ClassElement &&
+ !identical(element, _enclosingExec)) {
+ usedElements.members.add(element);
+ if (isIdentifierRead) {
+ // Store the corresponding getter.
+ if (element is PropertyAccessorElement && element.isSetter) {
+ element = (element as PropertyAccessorElement).correspondingGetter;
+ }
+ usedElements.members.add(element);
+ usedElements.readMembers.add(element);
}
}
}
@@ -2153,6 +2180,8 @@
static const String _typeProperty =
'analyzer.src.generated.InferenceContext.contextType';
+ final ResolverVisitor _resolver;
+
/// The error listener on which to record inference information.
final ErrorReporter _errorReporter;
@@ -2163,7 +2192,7 @@
final TypeProvider _typeProvider;
/// The type system in use.
- final TypeSystem _typeSystem;
+ final TypeSystemImpl _typeSystem;
/// When no context type is available, this will track the least upper bound
/// of all return statements in a lambda.
@@ -2175,9 +2204,13 @@
/// functions and methods.
final List<DartType> _returnStack = <DartType>[];
- InferenceContext._(TypeProvider typeProvider, this._typeSystem,
- this._inferenceHints, this._errorReporter)
- : _typeProvider = typeProvider;
+ InferenceContext._(
+ ResolverVisitor resolver,
+ this._inferenceHints,
+ ) : _resolver = resolver,
+ _typeProvider = resolver.typeProvider,
+ _errorReporter = resolver.errorReporter,
+ _typeSystem = resolver.typeSystem;
/// Get the return type of the current enclosing function, if any.
///
@@ -2199,7 +2232,12 @@
}
DartType inferred = _inferredReturn.last;
- inferred = _typeSystem.getLeastUpperBound(type, inferred);
+ if (inferred == null) {
+ inferred = type;
+ } else {
+ inferred = _typeSystem.getLeastUpperBound(type, inferred);
+ inferred = _resolver.toLegacyTypeIfOptOut(inferred);
+ }
_inferredReturn[_inferredReturn.length - 1] = inferred;
}
@@ -2210,8 +2248,21 @@
/// bound of all types added with [addReturnOrYieldType].
void popReturnContext(FunctionBody node) {
if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) {
- DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance;
+ // If NNBD, and the function body end is reachable, infer nullable.
+ // If legacy, we consider the end as always reachable, and return Null.
+ if (_resolver._nonNullableEnabled) {
+ var flow = _resolver._flowAnalysis?.flow;
+ if (flow != null && flow.isReachable) {
+ addReturnOrYieldType(_typeProvider.nullType);
+ }
+ } else {
+ addReturnOrYieldType(_typeProvider.nullType);
+ }
+
+ DartType context = _returnStack.removeLast();
DartType inferred = _inferredReturn.removeLast();
+ context ??= DynamicTypeImpl.instance;
+ inferred ??= DynamicTypeImpl.instance;
if (_typeSystem.isSubtypeOf(inferred, context)) {
setType(node, inferred);
@@ -2224,7 +2275,7 @@
/// Push a block function body's return type onto the return stack.
void pushReturnContext(FunctionBody node) {
_returnStack.add(getContext(node));
- _inferredReturn.add(_typeProvider.nullType);
+ _inferredReturn.add(null);
}
/// Place an info node into the error stream indicating that a
@@ -2258,8 +2309,8 @@
///
/// The returned type may be partially or completely unknown, denoted with an
/// unknown type `?`, for example `List<?>` or `(?, int) -> void`.
- /// You can use [Dart2TypeSystem.upperBoundForType] or
- /// [Dart2TypeSystem.lowerBoundForType] if you would prefer a known type
+ /// You can use [TypeSystemImpl.upperBoundForType] or
+ /// [TypeSystemImpl.lowerBoundForType] if you would prefer a known type
/// that represents the bound of the context type.
static DartType getContext(AstNode node) => node?.getProperty(_typeProperty);
@@ -2664,7 +2715,7 @@
StaticTypeAnalyzer typeAnalyzer;
/// The type system in use during resolution.
- Dart2TypeSystem typeSystem;
+ TypeSystemImpl typeSystem;
/// The class declaration representing the class containing the current node,
/// or `null` if the current node is not contained in a class.
@@ -2775,8 +2826,7 @@
if (options is AnalysisOptionsImpl) {
strongModeHints = options.strongModeHints;
}
- this.inferenceContext = new InferenceContext._(
- typeProvider, typeSystem, strongModeHints, errorReporter);
+ this.inferenceContext = new InferenceContext._(this, strongModeHints);
this.typeAnalyzer = new StaticTypeAnalyzer(this, featureSet, _flowAnalysis);
}
@@ -2914,6 +2964,20 @@
}
}
+ /// If in a legacy library, return the legacy view on the [element].
+ /// Otherwise, return the original element.
+ T toLegacyElement<T extends Element>(T element) {
+ if (_nonNullableEnabled) return element;
+ return Member.legacy(element);
+ }
+
+ /// If in a legacy library, return the legacy version of the [type].
+ /// Otherwise, return the original type.
+ DartType toLegacyTypeIfOptOut(DartType type) {
+ if (_nonNullableEnabled) return type;
+ return NullabilityEliminator.perform(type);
+ }
+
@override
void visitAnnotation(Annotation node) {
AstNode parent = node.parent;
@@ -3540,7 +3604,7 @@
node,
identifierElement is VariableElement
? identifierElement
- : loopVariable.declaredElement,
+ : loopVariable?.declaredElement,
elementType ?? typeProvider.dynamicType);
node.body?.accept(this);
_flowAnalysis?.flow?.forEach_end();
@@ -4555,6 +4619,7 @@
isConst: isConst,
errorReporter: errorReporter,
errorNode: errorNode,
+ isNonNullableByDefault: _nonNullableEnabled,
);
if (typeArguments != null) {
return uninstantiatedType.instantiate(typeArguments);
@@ -5596,7 +5661,7 @@
///
/// The client must set [nameScope] before calling [resolveTypeName].
class TypeNameResolver {
- final Dart2TypeSystem typeSystem;
+ final TypeSystemImpl typeSystem;
final DartType dynamicType;
final bool isNonNullableUnit;
final AnalysisOptionsImpl analysisOptions;
@@ -6082,6 +6147,7 @@
declaredReturnType: typeElement.thisType,
argumentTypes: const [],
contextReturnType: enclosingClassElement.thisType,
+ isNonNullableByDefault: isNonNullableUnit,
);
}
}
@@ -6481,8 +6547,16 @@
/// The elements know to be used.
final UsedLocalElements _usedElements;
+ /// The inheritance manager used to find overridden methods.
+ final InheritanceManager3 _inheritanceManager;
+
+ /// The URI of the library being verified.
+ final Uri _libraryUri;
+
/// Create a new instance of the [UnusedLocalElementsVerifier].
- UnusedLocalElementsVerifier(this._errorListener, this._usedElements);
+ UnusedLocalElementsVerifier(this._errorListener, this._usedElements,
+ this._inheritanceManager, LibraryElement library)
+ : _libraryUri = library.source.uri;
visitSimpleIdentifier(SimpleIdentifier node) {
if (node.inDeclarationContext()) {
@@ -6507,6 +6581,8 @@
}
}
+ /// Returns whether the name of [element] consists only of underscore
+ /// characters.
bool _isNamedUnderscore(LocalVariableElement element) {
String name = element.name;
if (name != null) {
@@ -6521,6 +6597,8 @@
return false;
}
+ /// Returns whether [element] is a private element which is read somewhere in
+ /// the library.
bool _isReadMember(Element element) {
if (element.isPublic) {
return true;
@@ -6528,7 +6606,15 @@
if (element.isSynthetic) {
return true;
}
- return _usedElements.readMembers.contains(element.displayName);
+ if (element is FieldElement) {
+ element = (element as FieldElement).getter;
+ }
+ if (_usedElements.readMembers.contains(element) ||
+ _usedElements.unresolvedReadMembers.contains(element.name)) {
+ return true;
+ }
+
+ return _overridesUsedElement(element);
}
bool _isUsedElement(Element element) {
@@ -6553,10 +6639,32 @@
if (element.isSynthetic) {
return true;
}
- if (_usedElements.members.contains(element.displayName)) {
+ if (_usedElements.members.contains(element)) {
return true;
}
- return _usedElements.elements.contains(element);
+ if (_usedElements.elements.contains(element)) {
+ return true;
+ }
+
+ return _overridesUsedElement(element);
+ }
+
+ // Check if this is a class member which overrides a super class's class
+ // member which is used.
+ bool _overridesUsedElement(Element element) {
+ Element enclosingElement = element.enclosingElement;
+ if (enclosingElement is ClassElement) {
+ Name name = new Name(_libraryUri, element.name);
+ Iterable<ExecutableElement> overriddenElements = _inheritanceManager
+ .getOverridden(enclosingElement.thisType, name)
+ ?.map((ExecutableElement e) =>
+ (e is ExecutableMember) ? e.declaration : e);
+ if (overriddenElements != null) {
+ return overriddenElements.any((ExecutableElement e) =>
+ _usedElements.members.contains(e) || _overridesUsedElement(e));
+ }
+ }
+ return false;
}
void _reportErrorForElement(
@@ -6646,13 +6754,14 @@
final HashSet<LocalVariableElement> catchStackTraceElements =
new HashSet<LocalVariableElement>();
- /// Names of resolved or unresolved class members that are referenced in the
- /// library.
- final HashSet<String> members = new HashSet<String>();
+ /// Resolved class members that are referenced in the library.
+ final HashSet<Element> members = new HashSet<Element>();
- /// Names of resolved or unresolved class members that are read in the
- /// library.
- final HashSet<String> readMembers = new HashSet<String>();
+ /// Resolved class members that are read in the library.
+ final HashSet<Element> readMembers = new HashSet<Element>();
+
+ /// Unresolved class members that are read in the library.
+ final HashSet<String> unresolvedReadMembers = new HashSet<String>();
UsedLocalElements();
@@ -6666,6 +6775,7 @@
result.catchStackTraceElements.addAll(part.catchStackTraceElements);
result.members.addAll(part.members);
result.readMembers.addAll(part.readMembers);
+ result.unresolvedReadMembers.addAll(part.unresolvedReadMembers);
}
return result;
}
diff --git a/pkg/analyzer/lib/src/generated/sdk_io.dart b/pkg/analyzer/lib/src/generated/sdk_io.dart
index 48993a4..c2c8506 100644
--- a/pkg/analyzer/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer/lib/src/generated/sdk_io.dart
@@ -63,9 +63,8 @@
@override
AnalysisContext get context {
if (_analysisContext == null) {
- _analysisContext = new SdkAnalysisContext(_analysisOptions);
- SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
- _analysisContext.sourceFactory = factory;
+ var factory = SourceFactory([DartUriResolver(this)]);
+ _analysisContext = SdkAnalysisContext(_analysisOptions, factory);
}
return _analysisContext;
}
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index ff85dcb..f6872ad 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -53,7 +53,7 @@
/**
* The type system in use for static type analysis.
*/
- Dart2TypeSystem _typeSystem;
+ TypeSystemImpl _typeSystem;
/**
* The type representing the type 'dynamic'.
@@ -250,6 +250,7 @@
isConst: node.isConst,
errorReporter: _resolver.errorReporter,
errorNode: node,
+ isNonNullableByDefault: _nonNullableEnabled,
);
return element.instantiate(
typeArguments: typeArguments,
@@ -274,6 +275,7 @@
isConst: node.isConst,
errorReporter: _resolver.errorReporter,
errorNode: node,
+ isNonNullableByDefault: _nonNullableEnabled,
);
return element.instantiate(
typeArguments: typeArguments,
@@ -297,6 +299,7 @@
isConst: node.isConst,
errorReporter: _resolver.errorReporter,
errorNode: node,
+ isNonNullableByDefault: _nonNullableEnabled,
);
return element.instantiate(
typeArguments: typeArguments,
@@ -1279,6 +1282,8 @@
_typeSystem.getLeastUpperBound(staticType1, staticType2) ??
_dynamicType;
+ staticType = _resolver.toLegacyTypeIfOptOut(staticType);
+
_recordStaticType(node, staticType);
}
@@ -1679,6 +1684,7 @@
isConst: isConst,
errorReporter: _resolver.errorReporter,
errorNode: errorNode,
+ isNonNullableByDefault: _nonNullableEnabled,
);
if (node is InvocationExpressionImpl) {
node.typeArgumentTypes = typeArgs;
@@ -2124,6 +2130,7 @@
declaredReturnType: element.thisType,
argumentTypes: argumentTypes,
contextReturnType: contextType,
+ isNonNullableByDefault: _nonNullableEnabled,
);
return element.instantiate(
typeArguments: typeArguments,
@@ -2155,6 +2162,7 @@
declaredReturnType: element.thisType,
argumentTypes: argumentTypes,
contextReturnType: contextType,
+ isNonNullableByDefault: _nonNullableEnabled,
);
return element.instantiate(
typeArguments: typeArguments,
@@ -2205,7 +2213,7 @@
{this.elementType, this.keyType, this.valueType});
factory _InferredCollectionElementTypeInformation.forIfElement(
- TypeSystem typeSystem,
+ TypeSystemImpl typeSystem,
_InferredCollectionElementTypeInformation thenInfo,
_InferredCollectionElementTypeInformation elseInfo) {
if (thenInfo.isDynamic) {
@@ -2259,7 +2267,7 @@
}
static DartType _leastUpperBoundOfTypes(
- TypeSystem typeSystem, DartType first, DartType second) {
+ TypeSystemImpl typeSystem, DartType first, DartType second) {
if (first == null) {
return second;
} else if (second == null) {
diff --git a/pkg/analyzer/lib/src/generated/super_context.dart b/pkg/analyzer/lib/src/generated/super_context.dart
index 3613971..bee205b 100644
--- a/pkg/analyzer/lib/src/generated/super_context.dart
+++ b/pkg/analyzer/lib/src/generated/super_context.dart
@@ -7,6 +7,10 @@
/// An indication of the kind of context in which a super expression was found.
class SuperContext {
/// An indication that the super expression is in a context in which it is
+ /// invalid because it is in an annotation.
+ static const SuperContext annotation = SuperContext._('annotation');
+
+ /// An indication that the super expression is in a context in which it is
/// invalid because it is in an instance member of an extension.
static const SuperContext extension = SuperContext._('extension');
@@ -25,7 +29,9 @@
/// being used.
factory SuperContext.of(SuperExpression expression) {
for (AstNode node = expression; node != null; node = node.parent) {
- if (node is CompilationUnit) {
+ if (node is Annotation) {
+ return SuperContext.annotation;
+ } else if (node is CompilationUnit) {
return SuperContext.static;
} else if (node is ConstructorDeclaration) {
return node.factoryKeyword == null
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index a854d3f..a041a8a 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -1360,6 +1361,17 @@
astFactory.typeParameter(null, null, identifier3(name),
TokenFactory.tokenFromKeyword(Keyword.EXTENDS), bound);
+ static TypeParameter typeParameter3(String name, String varianceLexeme) =>
+ // TODO (kallentu) : Clean up AstFactoryImpl casting once variance is
+ // added to the interface.
+ (astFactory as AstFactoryImpl).typeParameter2(
+ comment: null,
+ metadata: null,
+ name: identifier3(name),
+ extendsKeyword: null,
+ bound: null,
+ varianceKeyword: TokenFactory.tokenFromString(varianceLexeme));
+
static TypeParameterList typeParameterList([List<String> typeNames]) {
List<TypeParameter> typeParameters;
if (typeNames != null && typeNames.isNotEmpty) {
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 846783b..05ea5ae 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -11,6 +11,7 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -223,8 +224,7 @@
static ExtensionElementImpl extensionElement(
[String name, DartType extendedType]) =>
- ExtensionElementImpl.forNode(AstTestFactory.identifier3(name))
- ..extendedType = extendedType;
+ ExtensionElementImpl(name, -1)..extendedType = extendedType;
static FieldElementImpl fieldElement(
String name, bool isStatic, bool isFinal, bool isConst, DartType type,
@@ -248,7 +248,7 @@
static FieldFormalParameterElementImpl fieldFormalParameter(
Identifier name) =>
- new FieldFormalParameterElementImpl.forNode(name);
+ new FieldFormalParameterElementImpl(name.name, name.offset);
/**
* Destroy any static state retained by [ElementFactory]. This should be
@@ -452,7 +452,7 @@
}
static LocalVariableElementImpl localVariableElement(Identifier name) =>
- new LocalVariableElementImpl.forNode(name);
+ new LocalVariableElementImpl(name.name, name.offset);
static LocalVariableElementImpl localVariableElement2(String name) =>
new LocalVariableElementImpl(name, 0);
@@ -589,7 +589,7 @@
}
static TopLevelVariableElementImpl topLevelVariableElement(Identifier name) =>
- new TopLevelVariableElementImpl.forNode(name);
+ new TopLevelVariableElementImpl(name.name, name.offset);
static TopLevelVariableElementImpl topLevelVariableElement2(String name) =>
topLevelVariableElement3(name, false, false, null);
@@ -599,8 +599,7 @@
TopLevelVariableElementImpl variable;
if (isConst) {
ConstTopLevelVariableElementImpl constant =
- new ConstTopLevelVariableElementImpl.forNode(
- AstTestFactory.identifier3(name));
+ new ConstTopLevelVariableElementImpl(name, -1);
InstanceCreationExpression initializer =
AstTestFactory.instanceCreationExpression2(
Keyword.CONST, AstTestFactory.typeName(type.element));
@@ -643,9 +642,10 @@
}
static TypeParameterElementImpl typeParameterWithType(String name,
- [DartType bound]) {
+ [DartType bound, Variance variance]) {
TypeParameterElementImpl typeParameter = typeParameterElement(name);
typeParameter.bound = bound;
+ typeParameter.variance = variance;
return typeParameter;
}
diff --git a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
index 411503d..8113abe 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -16,22 +16,29 @@
*/
class TestTypeProvider extends TypeProviderImpl {
factory TestTypeProvider({
- NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+ bool isNonNullableByDefault = false,
}) {
var context = _MockAnalysisContext();
- var sdkElements = MockSdkElements(context, nullabilitySuffix);
+ var sdkElements = MockSdkElements(
+ context,
+ isNonNullableByDefault ? NullabilitySuffix.none : NullabilitySuffix.star,
+ );
return TestTypeProvider._(
- nullabilitySuffix,
sdkElements.coreLibrary,
sdkElements.asyncLibrary,
+ isNonNullableByDefault,
);
}
TestTypeProvider._(
- NullabilitySuffix nullabilitySuffix,
LibraryElement coreLibrary,
LibraryElement asyncLibrary,
- ) : super(coreLibrary, asyncLibrary, nullabilitySuffix: nullabilitySuffix);
+ bool isNonNullableByDefault,
+ ) : super(
+ coreLibrary: coreLibrary,
+ asyncLibrary: asyncLibrary,
+ isNonNullableByDefault: isNonNullableByDefault,
+ );
}
class _MockAnalysisContext implements AnalysisContext {
diff --git a/pkg/analyzer/lib/src/generated/type_promotion_manager.dart b/pkg/analyzer/lib/src/generated/type_promotion_manager.dart
index 9ecf575..8411dc2 100644
--- a/pkg/analyzer/lib/src/generated/type_promotion_manager.dart
+++ b/pkg/analyzer/lib/src/generated/type_promotion_manager.dart
@@ -15,7 +15,7 @@
/// types of local variables and formal parameters from their declared types
/// based on control flow.
class TypePromotionManager {
- final TypeSystem _typeSystem;
+ final TypeSystemImpl _typeSystem;
/// The current promotion scope, or `null` if no scope has been entered.
_TypePromoteScope _currentScope;
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 1b841ec..74c495c 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -15,12 +15,11 @@
import 'package:analyzer/error/listener.dart' show ErrorReporter;
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember;
+import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/error/codes.dart' show HintCode, StrongModeCode;
-import 'package:analyzer/src/generated/engine.dart'
- show AnalysisContext, AnalysisOptionsImpl;
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/utilities_dart.dart' show ParameterKind;
import 'package:meta/meta.dart';
@@ -92,6 +91,8 @@
/**
* A type system that implements the type semantics for Dart 2.0.
+ *
+ * TODO(scheglov) Merge it into TypeSystemImpl.
*/
class Dart2TypeSystem extends TypeSystem {
/**
@@ -102,6 +103,10 @@
*/
final bool implicitCasts;
+ /// If `true`, then NNBD type rules should be used.
+ /// If `false`, then legacy type rules should be used.
+ final bool isNonNullableByDefault;
+
/// A flag indicating whether inference failures are allowed, off by default.
///
/// This option is experimental and subject to change.
@@ -118,8 +123,12 @@
/// The cached instance of `Null!`.
InterfaceTypeImpl _nullNoneCached;
- Dart2TypeSystem(this.typeProvider,
- {this.implicitCasts: true, this.strictInference: false});
+ Dart2TypeSystem({
+ @required this.implicitCasts,
+ @required this.isNonNullableByDefault,
+ @required this.strictInference,
+ @required this.typeProvider,
+ });
InterfaceTypeImpl get _nullNone =>
_nullNoneCached ??= (typeProvider.nullType as TypeImpl)
@@ -222,6 +231,241 @@
}
/**
+ * Compute the least upper bound of two types.
+ *
+ * https://github.com/dart-lang/language
+ * See `resources/type-system/upper-lower-bounds.md`
+ */
+ DartType getLeastUpperBound(DartType T1, DartType T2) {
+ // UP(T, T) = T
+ if (identical(T1, T2)) {
+ return T1;
+ }
+
+ // For any type T, LUB(?, T) == T.
+ if (identical(T1, UnknownInferredType.instance)) {
+ return T2;
+ }
+ if (identical(T2, UnknownInferredType.instance)) {
+ return T1;
+ }
+
+ var T1_isTop = isTop(T1);
+ var T2_isTop = isTop(T2);
+
+ // UP(T1, T2) where TOP(T1) and TOP(T2)
+ if (T1_isTop && T2_isTop) {
+ // * T1 if MORETOP(T1, T2)
+ // * T2 otherwise
+ if (isMoreTop(T1, T2)) {
+ return T1;
+ } else {
+ return T2;
+ }
+ }
+
+ // UP(T1, T2) = T1 if TOP(T1)
+ if (T1_isTop) {
+ return T1;
+ }
+
+ // UP(T1, T2) = T2 if TOP(T2)
+ if (T2_isTop) {
+ return T2;
+ }
+
+ var T1_isBottom = isBottom(T1);
+ var T2_isBottom = isBottom(T2);
+
+ // UP(T1, T2) where BOTTOM(T1) and BOTTOM(T2)
+ if (T1_isBottom && T2_isBottom) {
+ // * T2 if MOREBOTTOM(T1, T2)
+ // * T1 otherwise
+ if (isMoreBottom(T1, T2)) {
+ return T2;
+ } else {
+ return T1;
+ }
+ }
+
+ // UP(T1, T2) = T2 if BOTTOM(T1)
+ if (T1_isBottom) {
+ return T2;
+ }
+
+ // UP(T1, T2) = T1 if BOTTOM(T2)
+ if (T2_isBottom) {
+ return T1;
+ }
+
+ var T1_isNull = isNull(T1);
+ var T2_isNull = isNull(T2);
+
+ // UP(T1, T2) where NULL(T1) and NULL(T2)
+ if (T1_isNull && T2_isNull) {
+ // * T2 if MOREBOTTOM(T1, T2)
+ // * T1 otherwise
+ if (isMoreBottom(T1, T2)) {
+ return T2;
+ } else {
+ return T1;
+ }
+ }
+
+ // UP(T1, T2) where NULL(T1)
+ if (T1_isNull) {
+ // * T2 if T2 is nullable
+ // * T2? otherwise
+ if (isNullable(T2)) {
+ return T2;
+ } else {
+ return makeNullable(T2);
+ }
+ }
+
+ // UP(T1, T2) where NULL(T2)
+ if (T2_isNull) {
+ // * T1 if T1 is nullable
+ // * T1? otherwise
+ if (isNullable(T1)) {
+ return T1;
+ } else {
+ return makeNullable(T1);
+ }
+ }
+
+ var T1_isObject = isObject(T1);
+ var T2_isObject = isObject(T2);
+
+ // UP(T1, T2) where OBJECT(T1) and OBJECT(T2)
+ if (T1_isObject && T2_isObject) {
+ // * T1 if MORETOP(T1, T2)
+ // * T2 otherwise
+ if (isMoreTop(T1, T2)) {
+ return T1;
+ } else {
+ return T2;
+ }
+ }
+
+ // UP(T1, T2) where OBJECT(T1)
+ if (T1_isObject) {
+ // * T1 if T2 is non-nullable
+ // * T1? otherwise
+ if (isNonNullable(T2)) {
+ return T1;
+ } else {
+ return makeNullable(T1);
+ }
+ }
+
+ // UP(T1, T2) where OBJECT(T2)
+ if (T2_isObject) {
+ // * T2 if T1 is non-nullable
+ // * T2? otherwise
+ if (isNonNullable(T1)) {
+ return T2;
+ } else {
+ return makeNullable(T2);
+ }
+ }
+
+ var T1_impl = T1 as TypeImpl;
+ var T2_impl = T2 as TypeImpl;
+
+ var T1_nullability = T1_impl.nullabilitySuffix;
+ var T2_nullability = T2_impl.nullabilitySuffix;
+
+ // UP(T1*, T2*) = S* where S is UP(T1, T2)
+ // UP(T1*, T2?) = S? where S is UP(T1, T2)
+ // UP(T1?, T2*) = S? where S is UP(T1, T2)
+ // UP(T1*, T2) = S* where S is UP(T1, T2)
+ // UP(T1, T2*) = S* where S is UP(T1, T2)
+ // UP(T1?, T2?) = S? where S is UP(T1, T2)
+ // UP(T1?, T2) = S? where S is UP(T1, T2)
+ // UP(T1, T2?) = S? where S is UP(T1, T2)
+ if (T1_nullability != NullabilitySuffix.none ||
+ T2_nullability != NullabilitySuffix.none) {
+ var resultNullability = NullabilitySuffix.none;
+ if (T1_nullability == NullabilitySuffix.question ||
+ T2_nullability == NullabilitySuffix.question) {
+ resultNullability = NullabilitySuffix.question;
+ } else if (T1_nullability == NullabilitySuffix.star ||
+ T2_nullability == NullabilitySuffix.star) {
+ resultNullability = NullabilitySuffix.star;
+ }
+ var T1_none = T1_impl.withNullability(NullabilitySuffix.none);
+ var T2_none = T2_impl.withNullability(NullabilitySuffix.none);
+ var S = getLeastUpperBound(T1_none, T2_none);
+ return (S as TypeImpl).withNullability(resultNullability);
+ }
+
+ assert(T1_nullability == NullabilitySuffix.none);
+ assert(T2_nullability == NullabilitySuffix.none);
+
+ // UP(X1 extends B1, T2)
+ // UP(X1 & B1, T2)
+ if (T1 is TypeParameterType) {
+ // T2 if X1 <: T2
+ if (isSubtypeOf(T1, T2)) {
+ return T2;
+ }
+ // otherwise X1 if T2 <: X1
+ if (isSubtypeOf(T2, T1)) {
+ return T1;
+ }
+ // otherwise UP(B1[Object/X1], T2)
+ var T1_toObject = _typeParameterResolveToObjectBounds(T1);
+ return getLeastUpperBound(T1_toObject, T2);
+ }
+
+ // UP(T1, X2 extends B2)
+ // UP(T1, X2 & B2)
+ if (T2 is TypeParameterType) {
+ // X2 if T1 <: X2
+ if (isSubtypeOf(T1, T2)) {
+ // TODO(scheglov) How to get here?
+ return T2;
+ }
+ // otherwise T1 if X2 <: T1
+ if (isSubtypeOf(T2, T1)) {
+ return T1;
+ }
+ // otherwise UP(T1, B2[Object/X2])
+ var T2_toObject = _typeParameterResolveToObjectBounds(T2);
+ return getLeastUpperBound(T1, T2_toObject);
+ }
+
+ // UP(T Function<...>(...), Function) = Function
+ if (T1 is FunctionType && T2.isDartCoreFunction) {
+ return T2;
+ }
+
+ // UP(Function, T Function<...>(...)) = Function
+ if (T1.isDartCoreFunction && T2 is FunctionType) {
+ return T1;
+ }
+
+ // UP(T Function<...>(...), S Function<...>(...)) = Function
+ // And other, more interesting variants.
+ if (T1 is FunctionType && T2 is FunctionType) {
+ return _functionLeastUpperBound(T1, T2);
+ }
+
+ // UP(T Function<...>(...), T2) = Object
+ // UP(T1, T Function<...>(...)) = Object
+ if (T1 is FunctionType || T2 is FunctionType) {
+ return _objectNone;
+ }
+
+ // UP(T1, T2) = T2 if T1 <: T2
+ // UP(T1, T2) = T1 if T2 <: T1
+ // And other, more complex variants of interface types.
+ var helper = InterfaceLeastUpperBoundHelper(this);
+ return helper.compute(T1, T2);
+ }
+
+ /**
* Given a generic function type `F<T0, T1, ... Tn>` and a context type C,
* infer an instantiation of F, such that `F<S0, S1, ..., Sn>` <: C.
*
@@ -282,6 +526,7 @@
@required DartType declaredReturnType,
@required List<DartType> argumentTypes,
@required DartType contextReturnType,
+ @required bool isNonNullableByDefault,
ErrorReporter errorReporter,
AstNode errorNode,
bool downwards: false,
@@ -295,7 +540,12 @@
// inferred. It will optimistically assume these type parameters can be
// subtypes (or supertypes) as necessary, and track the constraints that
// are implied by this.
- var inferrer = new GenericInferrer(typeProvider, this, typeParameters);
+ var inferrer = new GenericInferrer(
+ typeProvider,
+ this,
+ typeParameters,
+ isNonNullableByDefault: isNonNullableByDefault,
+ );
if (contextReturnType != null) {
if (isConst) {
@@ -538,6 +788,24 @@
return false;
}
+ /// Return `true` for things in the equivalence class of `Never`.
+ bool isBottom(DartType type) {
+ // BOTTOM(Never) is true
+ if (identical(type, NeverTypeImpl.instance)) {
+ return true;
+ }
+
+ // BOTTOM(X&T) is true iff BOTTOM(T)
+ // BOTTOM(X extends T) is true iff BOTTOM(T)
+ if (type is TypeParameterType) {
+ var T = type.element.bound;
+ return isBottom(T);
+ }
+
+ // BOTTOM(T) is false otherwise
+ return false;
+ }
+
bool isGroundType(DartType t) {
// TODO(leafp): Revisit this.
if (t is TypeParameterType) {
@@ -573,9 +841,248 @@
return false;
}
+ /// Defines an (almost) total order on bottom and `Null` types. This does not
+ /// currently consistently order two different type variables with the same
+ /// bound.
+ bool isMoreBottom(DartType T, DartType S) {
+ var T_impl = T as TypeImpl;
+ var S_impl = S as TypeImpl;
+
+ var T_nullability = T_impl.nullabilitySuffix;
+ var S_nullability = S_impl.nullabilitySuffix;
+
+ // MOREBOTTOM(Never, T) = true
+ if (identical(T, NeverTypeImpl.instance)) {
+ return true;
+ }
+
+ // MOREBOTTOM(T, Never) = false
+ if (identical(S, NeverTypeImpl.instance)) {
+ return false;
+ }
+
+ // MOREBOTTOM(Null, T) = true
+ if (T_nullability == NullabilitySuffix.none && T.isDartCoreNull) {
+ return true;
+ }
+
+ // MOREBOTTOM(T, Null) = false
+ if (S_nullability == NullabilitySuffix.none && S.isDartCoreNull) {
+ return false;
+ }
+
+ // MOREBOTTOM(T?, S?) = MOREBOTTOM(T, S)
+ if (T_nullability == NullabilitySuffix.question &&
+ S_nullability == NullabilitySuffix.question) {
+ var T2 = T_impl.withNullability(NullabilitySuffix.none);
+ var S2 = S_impl.withNullability(NullabilitySuffix.none);
+ return isMoreBottom(T2, S2);
+ }
+
+ // MOREBOTTOM(T, S?) = true
+ if (S_nullability == NullabilitySuffix.question) {
+ return true;
+ }
+
+ // MOREBOTTOM(T?, S) = false
+ if (T_nullability == NullabilitySuffix.question) {
+ return false;
+ }
+
+ // MOREBOTTOM(T*, S*) = MOREBOTTOM(T, S)
+ if (T_nullability == NullabilitySuffix.star &&
+ S_nullability == NullabilitySuffix.star) {
+ var T2 = T_impl.withNullability(NullabilitySuffix.none);
+ var S2 = S_impl.withNullability(NullabilitySuffix.none);
+ return isMoreBottom(T2, S2);
+ }
+
+ // MOREBOTTOM(T, S*) = true
+ if (S_nullability == NullabilitySuffix.star) {
+ return true;
+ }
+
+ // MOREBOTTOM(T*, S) = false
+ if (T_nullability == NullabilitySuffix.star) {
+ return false;
+ }
+
+ // Type parameters.
+ if (T is TypeParameterType && S is TypeParameterType) {
+ // We have eliminated the possibility that T_nullability or S_nullability
+ // is anything except none by this point.
+ assert(T_nullability == NullabilitySuffix.none);
+ assert(S_nullability == NullabilitySuffix.none);
+ var T_element = T.element;
+ var S_element = S.element;
+ // MOREBOTTOM(X&T, Y&S) = MOREBOTTOM(T, S)
+ if (T_element is TypeParameterMember &&
+ S_element is TypeParameterMember) {
+ var T_bound = T_element.bound;
+ var S_bound = S_element.bound;
+ return isMoreBottom(T_bound, S_bound);
+ }
+ // MOREBOTTOM(X&T, S) = true
+ if (T_element is TypeParameterMember) {
+ return true;
+ }
+ // MOREBOTTOM(T, Y&S) = false
+ if (S_element is TypeParameterMember) {
+ return false;
+ }
+ // MOREBOTTOM(X extends T, Y extends S) = MOREBOTTOM(T, S)
+ var T_bound = T_element.bound;
+ var S_bound = S_element.bound;
+ // The invariant of the larger algorithm that this is only called with
+ // types that satisfy `BOTTOM(T)` or `NULL(T)`, and all such types, if
+ // they are type variables, have bounds which themselves are
+ // `BOTTOM` or `NULL` types.
+ assert(T_bound != null);
+ assert(S_bound != null);
+ return isMoreBottom(T_bound, S_bound);
+ }
+
+ return false;
+ }
+
@override
bool isMoreSpecificThan(DartType t1, DartType t2) => isSubtypeOf(t1, t2);
+ /// Defines a total order on top and Object types.
+ bool isMoreTop(DartType T, DartType S) {
+ var T_impl = T as TypeImpl;
+ var S_impl = S as TypeImpl;
+
+ var T_nullability = T_impl.nullabilitySuffix;
+ var S_nullability = S_impl.nullabilitySuffix;
+
+ // MORETOP(void, S) = true
+ if (identical(T, VoidTypeImpl.instance)) {
+ return true;
+ }
+
+ // MORETOP(T, void) = false
+ if (identical(S, VoidTypeImpl.instance)) {
+ return false;
+ }
+
+ // MORETOP(dynamic, S) = true
+ if (identical(T, DynamicTypeImpl.instance)) {
+ return true;
+ }
+
+ // MORETOP(T, dynamic) = false
+ if (identical(S, DynamicTypeImpl.instance)) {
+ return false;
+ }
+
+ // MORETOP(Object, S) = true
+ if (T_nullability == NullabilitySuffix.none && T.isDartCoreObject) {
+ return true;
+ }
+
+ // MORETOP(T, Object) = false
+ if (S_nullability == NullabilitySuffix.none && S.isDartCoreObject) {
+ return false;
+ }
+
+ // MORETOP(T*, S*) = MORETOP(T, S)
+ if (T_nullability == NullabilitySuffix.star &&
+ S_nullability == NullabilitySuffix.star) {
+ var T2 = T_impl.withNullability(NullabilitySuffix.none);
+ var S2 = S_impl.withNullability(NullabilitySuffix.none);
+ return isMoreTop(T2, S2);
+ }
+
+ // MORETOP(T, S*) = true
+ if (S_nullability == NullabilitySuffix.star) {
+ return true;
+ }
+
+ // MORETOP(T*, S) = false
+ if (T_nullability == NullabilitySuffix.star) {
+ return false;
+ }
+
+ // MORETOP(T?, S?) = MORETOP(T, S)
+ if (T_nullability == NullabilitySuffix.question &&
+ S_nullability == NullabilitySuffix.question) {
+ var T2 = T_impl.withNullability(NullabilitySuffix.none);
+ var S2 = S_impl.withNullability(NullabilitySuffix.none);
+ return isMoreTop(T2, S2);
+ }
+
+ // MORETOP(T, S?) = true
+ if (S_nullability == NullabilitySuffix.question) {
+ return true;
+ }
+
+ // MORETOP(T?, S) = false
+ if (T_nullability == NullabilitySuffix.question) {
+ return false;
+ }
+
+ // MORETOP(FutureOr<T>, FutureOr<S>) = MORETOP(T, S)
+ if (T is InterfaceType &&
+ T.isDartAsyncFutureOr &&
+ S is InterfaceType &&
+ S.isDartAsyncFutureOr) {
+ assert(T_nullability == NullabilitySuffix.none);
+ assert(S_nullability == NullabilitySuffix.none);
+ var T2 = T.typeArguments[0];
+ var S2 = S.typeArguments[0];
+ return isMoreTop(T2, S2);
+ }
+
+ return false;
+ }
+
+ /// Return `true` for things in the equivalence class of `Null`.
+ bool isNull(DartType type) {
+ var typeImpl = type as TypeImpl;
+ var nullabilitySuffix = typeImpl.nullabilitySuffix;
+
+ // NULL(Null) is true
+ // Also includes `Null?` and `Null*` from the rules below.
+ if (type.isDartCoreNull) {
+ return true;
+ }
+
+ // NULL(T?) is true iff NULL(T) or BOTTOM(T)
+ // NULL(T*) is true iff NULL(T) or BOTTOM(T)
+ // Cases for `Null?` and `Null*` are already checked above.
+ if (nullabilitySuffix == NullabilitySuffix.question ||
+ nullabilitySuffix == NullabilitySuffix.star) {
+ var T = typeImpl.withNullability(NullabilitySuffix.none);
+ return isBottom(T);
+ }
+
+ // NULL(T) is false otherwise
+ return false;
+ }
+
+ /// Return `true` for any type which is in the equivalence class of `Object`.
+ bool isObject(DartType type) {
+ TypeImpl typeImpl = type;
+ if (typeImpl.nullabilitySuffix != NullabilitySuffix.none) {
+ return false;
+ }
+
+ // OBJECT(Object) is true
+ if (type.isDartCoreObject) {
+ return true;
+ }
+
+ // OBJECT(FutureOr<T>) is OBJECT(T)
+ if (type is InterfaceType && type.isDartAsyncFutureOr) {
+ var T = type.typeArguments[0];
+ return isObject(T);
+ }
+
+ // OBJECT(T) is false otherwise
+ return false;
+ }
+
@override
bool isOverrideSubtypeOf(FunctionType f1, FunctionType f2) {
return FunctionTypeImpl.relate(f1, f2, isSubtypeOf,
@@ -840,6 +1347,40 @@
return false;
}
+ /// Return `true` for any type which is in the equivalence class of top types.
+ bool isTop(DartType type) {
+ // TOP(dynamic) is true
+ if (identical(type, DynamicTypeImpl.instance)) {
+ return true;
+ }
+
+ // TOP(void) is true
+ if (identical(type, VoidTypeImpl.instance)) {
+ return true;
+ }
+
+ var typeImpl = type as TypeImpl;
+ var nullabilitySuffix = typeImpl.nullabilitySuffix;
+
+ // TOP(T?) is true iff TOP(T) or OBJECT(T)
+ // TOP(T*) is true iff TOP(T) or OBJECT(T)
+ if (nullabilitySuffix == NullabilitySuffix.question ||
+ nullabilitySuffix == NullabilitySuffix.star) {
+ var T = typeImpl.withNullability(NullabilitySuffix.none);
+ return isTop(T) || isObject(T);
+ }
+
+ // TOP(FutureOr<T>) is TOP(T)
+ if (type is InterfaceType && type.isDartAsyncFutureOr) {
+ assert(nullabilitySuffix == NullabilitySuffix.none);
+ var T = type.typeArguments[0];
+ return isTop(T);
+ }
+
+ // TOP(T) is false otherwise
+ return false;
+ }
+
/// Given a [type] T that may have an unknown type `?`, returns a type
/// R such that R <: T for any type substituted for `?`.
///
@@ -1062,14 +1603,111 @@
return new FunctionElementImpl.synthetic(parameters, returnType).type;
}
- @override
- DartType _functionParameterBound(DartType f, DartType g) =>
- getGreatestLowerBound(f, g);
+ /**
+ * Compute the least upper bound of function types [f] and [g].
+ *
+ * https://github.com/dart-lang/language
+ * See `resources/type-system/upper-lower-bounds.md`
+ */
+ DartType _functionLeastUpperBound(FunctionType f, FunctionType g) {
+ var fTypeFormals = f.typeFormals;
+ var gTypeFormals = g.typeFormals;
- @override
- DartType _interfaceLeastUpperBound(InterfaceType type1, InterfaceType type2) {
- var helper = InterfaceLeastUpperBoundHelper(this);
- return helper.compute(type1, type2);
+ // The number of type parameters must be the same.
+ // Otherwise the result is `Function`.
+ if (fTypeFormals.length != gTypeFormals.length) {
+ return typeProvider.functionType.element.instantiate(
+ typeArguments: const [],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ // The bounds of type parameters must be equal.
+ // Otherwise the result is `Function`.
+ var freshTypeFormalTypes =
+ FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) => t == s);
+ if (freshTypeFormalTypes == null) {
+ return typeProvider.functionType.element.instantiate(
+ typeArguments: const [],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ var typeFormals = freshTypeFormalTypes
+ .map<TypeParameterElement>((t) => t.element)
+ .toList();
+
+ f = f.instantiate(freshTypeFormalTypes);
+ g = g.instantiate(freshTypeFormalTypes);
+
+ List<DartType> fRequired = f.normalParameterTypes;
+ List<DartType> gRequired = g.normalParameterTypes;
+
+ // The number of required parameters must be the same.
+ if (fRequired.length != gRequired.length) {
+ return typeProvider.functionType.element.instantiate(
+ typeArguments: const [],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ // We need some parameter names for the result, so arbitrarily use F's.
+ var fRequiredNames = f.normalParameterNames;
+ var fPositionalNames = f.optionalParameterNames;
+
+ // Calculate the DOWN of each corresponding pair of parameters.
+ var parameters = <ParameterElement>[];
+
+ for (int i = 0; i < fRequired.length; i++) {
+ parameters.add(
+ new ParameterElementImpl.synthetic(
+ fRequiredNames[i],
+ // TODO(scheglov) Update for NNBD aware DOWN.
+ getGreatestLowerBound(fRequired[i], gRequired[i]),
+ ParameterKind.REQUIRED,
+ ),
+ );
+ }
+
+ List<DartType> fPositional = f.optionalParameterTypes;
+ List<DartType> gPositional = g.optionalParameterTypes;
+
+ // Ignore any extra optional positional parameters.
+ int length = math.min(fPositional.length, gPositional.length);
+ for (int i = 0; i < length; i++) {
+ parameters.add(
+ new ParameterElementImpl.synthetic(
+ fPositionalNames[i],
+ // TODO(scheglov) Update for NNBD aware DOWN.
+ getGreatestLowerBound(fPositional[i], gPositional[i]),
+ ParameterKind.POSITIONAL,
+ ),
+ );
+ }
+
+ // TODO(brianwilkerson) Handle the fact that named parameters can now be
+ // required.
+ Map<String, DartType> fNamed = f.namedParameterTypes;
+ Map<String, DartType> gNamed = g.namedParameterTypes;
+ for (String name in fNamed.keys.toSet()..retainAll(gNamed.keys)) {
+ parameters.add(
+ new ParameterElementImpl.synthetic(
+ name,
+ // TODO(scheglov) Update for NNBD aware DOWN.
+ getGreatestLowerBound(fNamed[name], gNamed[name]),
+ ParameterKind.NAMED,
+ ),
+ );
+ }
+
+ var returnType = getLeastUpperBound(f.returnType, g.returnType);
+
+ return FunctionTypeImpl(
+ typeFormals: typeFormals,
+ parameters: parameters,
+ returnType: returnType,
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
}
/// Check that [f1] is a subtype of [f2].
@@ -1117,15 +1755,14 @@
DartType t1 = tArgs1[i];
DartType t2 = tArgs2[i];
- // TODO (kallentu) : Clean up TypeParameterElementImpl checks and
- // casting once variance is added to the interface.
- TypeParameterElement parameterElement = tParams[i];
- Variance variance = Variance.covariant;
- if (parameterElement is TypeParameterElementImpl) {
- variance = parameterElement.variance;
- }
-
- if (variance.isContravariant) {
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ Variance variance = (tParams[i] as TypeParameterElementImpl).variance;
+ if (variance.isCovariant) {
+ if (!isSubtypeOf(t1, t2)) {
+ return false;
+ }
+ } else if (variance.isContravariant) {
if (!isSubtypeOf(t2, t1)) {
return false;
}
@@ -1134,9 +1771,8 @@
return false;
}
} else {
- if (!isSubtypeOf(t1, t2)) {
- return false;
- }
+ throw new StateError('Type parameter ${tParams[i]} has unknown '
+ 'variance $variance for subtype checking.');
}
}
return true;
@@ -1254,59 +1890,6 @@
return type;
}
- /**
- * This currently just implements a simple least upper bound to
- * handle some common cases. It also avoids some termination issues
- * with the naive spec algorithm. The least upper bound of two types
- * (at least one of which is a type parameter) is computed here as:
- * 1. If either type is a supertype of the other, return it.
- * 2. If the first type is a type parameter, replace it with its bound,
- * with recursive occurrences of itself replaced with Object.
- * The second part of this should ensure termination. Informally,
- * each type variable instantiation in one of the arguments to the
- * least upper bound algorithm now strictly reduces the number
- * of bound variables in scope in that argument position.
- * 3. If the second type is a type parameter, do the symmetric operation
- * to #2.
- *
- * It's not immediately obvious why this is symmetric in the case that both
- * of them are type parameters. For #1, symmetry holds since subtype
- * is antisymmetric. For #2, it's clearly not symmetric if upper bounds of
- * bottom are allowed. Ignoring this (for various reasons, not least
- * of which that there's no way to write it), there's an informal
- * argument (that might even be right) that you will always either
- * end up expanding both of them or else returning the same result no matter
- * which order you expand them in. A key observation is that
- * identical(expand(type1), type2) => subtype(type1, type2)
- * and hence the contra-positive.
- *
- * TODO(leafp): Think this through and figure out what's the right
- * definition. Be careful about termination.
- *
- * I suspect in general a reasonable algorithm is to expand the innermost
- * type variable first. Alternatively, you could probably choose to treat
- * it as just an instance of the interface type upper bound problem, with
- * the "inheritance" chain extended by the bounds placed on the variables.
- */
- @override
- DartType _typeParameterLeastUpperBound(DartType type1, DartType type2) {
- if (isSubtypeOf(type1, type2)) {
- return type2;
- }
- if (isSubtypeOf(type2, type1)) {
- return type1;
- }
- if (type1 is TypeParameterType) {
- type1 = _typeParameterResolveToObjectBounds(type1);
- return getLeastUpperBound(type1, type2);
- }
- // We should only be called when at least one of the types is a
- // TypeParameterType
- type2 = _typeParameterResolveToObjectBounds(type2);
-
- return getLeastUpperBound(type1, type2);
- }
-
DartType _typeParameterResolveToObjectBounds(DartType type) {
var element = type.element;
type = type.resolveToBound(typeProvider.objectType);
@@ -1352,8 +1935,9 @@
/// As currently designed, an instance of this class should only be used to
/// infer a single call and discarded immediately afterwards.
class GenericInferrer {
- final Dart2TypeSystem _typeSystem;
+ final TypeSystemImpl _typeSystem;
final TypeProvider typeProvider;
+ final bool isNonNullableByDefault;
final Map<TypeParameterElement, List<_TypeConstraint>> constraints = {};
/// Buffer recording constraints recorded while performing a recursive call to
@@ -1362,7 +1946,8 @@
final _undoBuffer = <_TypeConstraint>[];
GenericInferrer(this.typeProvider, this._typeSystem,
- Iterable<TypeParameterElement> typeFormals) {
+ Iterable<TypeParameterElement> typeFormals,
+ {this.isNonNullableByDefault = false}) {
for (var formal in typeFormals) {
constraints[formal] = [];
}
@@ -1424,13 +2009,11 @@
// degradation for f-bounded type parameters.
var inferredTypes = new List<DartType>.filled(
typeFormals.length, UnknownInferredType.instance);
- var _inferTypeParameter = downwardsInferPhase
- ? _inferTypeParameterFromContext
- : _inferTypeParameterFromAll;
for (int i = 0; i < typeFormals.length; i++) {
- TypeParameterElement typeParam = typeFormals[i];
-
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ TypeParameterElementImpl typeParam = typeFormals[i];
_TypeConstraint extendsClause;
if (considerExtendsClause && typeParam.bound != null) {
extendsClause = new _TypeConstraint.fromExtends(
@@ -1439,8 +2022,12 @@
.substituteType(typeParam.bound));
}
- inferredTypes[i] =
- _inferTypeParameter(constraints[typeParam], extendsClause);
+ inferredTypes[i] = downwardsInferPhase || !typeParam.isLegacyCovariant
+ ? _inferTypeParameterFromContext(
+ constraints[typeParam], extendsClause,
+ isContravariant: typeParam.variance.isContravariant)
+ : _inferTypeParameterFromAll(constraints[typeParam], extendsClause,
+ isContravariant: typeParam.variance.isContravariant);
}
// If the downwards infer phase has failed, we'll catch this in the upwards
@@ -1581,8 +2168,12 @@
/// * `int <: T`
///
/// ... and no upper bound. Therefore the lower bound is the best choice.
+ ///
+ /// If [isContravariant] is `true`, then we are solving for a contravariant
+ /// type parameter which means we choose the upper bound rather than the
+ /// lower bound for normally covariant type parameters.
DartType _chooseTypeFromConstraints(Iterable<_TypeConstraint> constraints,
- {bool toKnownType: false}) {
+ {bool toKnownType: false, @required bool isContravariant}) {
DartType lower = UnknownInferredType.instance;
DartType upper = UnknownInferredType.instance;
for (var constraint in constraints) {
@@ -1601,25 +2192,44 @@
// will fail.
upper = _getGreatestLowerBound(upper, constraint.upperBound);
lower = _typeSystem.getLeastUpperBound(lower, constraint.lowerBound);
+ upper = _toLegacyType(upper);
+ lower = _toLegacyType(lower);
}
// Prefer the known bound, if any.
// Otherwise take whatever bound has partial information, e.g. `Iterable<?>`
//
- // For both of those, prefer the lower bound (arbitrary heuristic).
- if (UnknownInferredType.isKnown(lower)) {
+ // For both of those, prefer the lower bound (arbitrary heuristic) or upper
+ // bound if [isContravariant] is `true`
+ if (isContravariant) {
+ if (UnknownInferredType.isKnown(upper)) {
+ return upper;
+ }
+ if (UnknownInferredType.isKnown(lower)) {
+ return lower;
+ }
+ if (!identical(UnknownInferredType.instance, upper)) {
+ return toKnownType ? _typeSystem.upperBoundForType(upper) : upper;
+ }
+ if (!identical(UnknownInferredType.instance, lower)) {
+ return toKnownType ? _typeSystem.lowerBoundForType(lower) : lower;
+ }
+ return upper;
+ } else {
+ if (UnknownInferredType.isKnown(lower)) {
+ return lower;
+ }
+ if (UnknownInferredType.isKnown(upper)) {
+ return upper;
+ }
+ if (!identical(UnknownInferredType.instance, lower)) {
+ return toKnownType ? _typeSystem.lowerBoundForType(lower) : lower;
+ }
+ if (!identical(UnknownInferredType.instance, upper)) {
+ return toKnownType ? _typeSystem.upperBoundForType(upper) : upper;
+ }
return lower;
}
- if (UnknownInferredType.isKnown(upper)) {
- return upper;
- }
- if (!identical(UnknownInferredType.instance, lower)) {
- return toKnownType ? _typeSystem.lowerBoundForType(lower) : lower;
- }
- if (!identical(UnknownInferredType.instance, upper)) {
- return toKnownType ? _typeSystem.upperBoundForType(upper) : upper;
- }
- return lower;
}
String _formatError(TypeParameterElement typeParam, DartType inferred,
@@ -1693,11 +2303,13 @@
}
DartType _inferTypeParameterFromAll(
- List<_TypeConstraint> constraints, _TypeConstraint extendsClause) {
+ List<_TypeConstraint> constraints, _TypeConstraint extendsClause,
+ {@required bool isContravariant}) {
// See if we already fixed this type from downwards inference.
// If so, then we aren't allowed to change it based on argument types.
DartType t = _inferTypeParameterFromContext(
- constraints.where((c) => c.isDownwards), extendsClause);
+ constraints.where((c) => c.isDownwards), extendsClause,
+ isContravariant: isContravariant);
if (UnknownInferredType.isKnown(t)) {
// Remove constraints that aren't downward ones; we'll ignore these for
// error reporting, because inference already succeeded.
@@ -1709,13 +2321,16 @@
constraints = constraints.toList()..add(extendsClause);
}
- var choice = _chooseTypeFromConstraints(constraints, toKnownType: true);
+ var choice = _chooseTypeFromConstraints(constraints,
+ toKnownType: true, isContravariant: isContravariant);
return choice;
}
DartType _inferTypeParameterFromContext(
- Iterable<_TypeConstraint> constraints, _TypeConstraint extendsClause) {
- DartType t = _chooseTypeFromConstraints(constraints);
+ Iterable<_TypeConstraint> constraints, _TypeConstraint extendsClause,
+ {@required bool isContravariant}) {
+ DartType t = _chooseTypeFromConstraints(constraints,
+ isContravariant: isContravariant);
if (UnknownInferredType.isUnknown(t)) {
return t;
}
@@ -1729,7 +2344,8 @@
// If we consider the `T extends num` we conclude `<num>`, which works.
if (extendsClause != null) {
constraints = constraints.toList()..add(extendsClause);
- return _chooseTypeFromConstraints(constraints);
+ return _chooseTypeFromConstraints(constraints,
+ isContravariant: isContravariant);
}
return t;
}
@@ -1749,12 +2365,40 @@
if (i1.element == i2.element) {
List<DartType> tArgs1 = i1.typeArguments;
List<DartType> tArgs2 = i2.typeArguments;
+ List<TypeParameterElement> tParams = i1.element.typeParameters;
assert(tArgs1.length == tArgs2.length);
+ assert(tArgs1.length == tParams.length);
for (int i = 0; i < tArgs1.length; i++) {
- if (!_matchSubtypeOf(
- tArgs1[i], tArgs2[i], new HashSet<Element>(), origin,
- covariant: covariant)) {
- return false;
+ TypeParameterElement typeParameterElement = tParams[i];
+
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ Variance parameterVariance =
+ (typeParameterElement as TypeParameterElementImpl).variance;
+ if (parameterVariance.isCovariant) {
+ if (!_matchSubtypeOf(
+ tArgs1[i], tArgs2[i], new HashSet<Element>(), origin,
+ covariant: covariant)) {
+ return false;
+ }
+ } else if (parameterVariance.isContravariant) {
+ if (!_matchSubtypeOf(
+ tArgs2[i], tArgs1[i], new HashSet<Element>(), origin,
+ covariant: !covariant)) {
+ return false;
+ }
+ } else if (parameterVariance.isInvariant) {
+ if (!_matchSubtypeOf(
+ tArgs1[i], tArgs2[i], new HashSet<Element>(), origin,
+ covariant: covariant) ||
+ !_matchSubtypeOf(
+ tArgs2[i], tArgs1[i], new HashSet<Element>(), origin,
+ covariant: !covariant)) {
+ return false;
+ }
+ } else {
+ throw new StateError("Type parameter ${tParams[i]} has unknown "
+ "variance $parameterVariance for inference.");
}
}
return true;
@@ -1974,6 +2618,13 @@
}
}
+ /// If in a legacy library, return the legacy version of the [type].
+ /// Otherwise, return the original type.
+ DartType _toLegacyType(DartType type) {
+ if (isNonNullableByDefault) return type;
+ return NullabilityEliminator.perform(type);
+ }
+
static String _formatConstraints(Iterable<_TypeConstraint> constraints) {
List<List<String>> lineParts =
new Set<_TypeConstraintOrigin>.from(constraints.map((c) => c.origin))
@@ -2122,7 +2773,7 @@
}
class InterfaceLeastUpperBoundHelper {
- final TypeSystem typeSystem;
+ final TypeSystemImpl typeSystem;
InterfaceLeastUpperBoundHelper(this.typeSystem);
@@ -2173,18 +2824,15 @@
var args = List<DartType>(args1.length);
for (int i = 0; i < args1.length; i++) {
- // TODO (kallentu) : Clean up TypeParameterElementImpl checks and
- // casting once variance is added to the interface.
- TypeParameterElement parameter = params[i];
- Variance parameterVariance = Variance.covariant;
- if (parameter is TypeParameterElementImpl) {
- parameterVariance = parameter.variance;
- }
-
- if (parameterVariance.isContravariant) {
- if (typeSystem is Dart2TypeSystem) {
- args[i] = (typeSystem as Dart2TypeSystem)
- .getGreatestLowerBound(args1[i], args2[i]);
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ Variance parameterVariance =
+ (params[i] as TypeParameterElementImpl).variance;
+ if (parameterVariance.isCovariant) {
+ args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
+ } else if (parameterVariance.isContravariant) {
+ if (typeSystem is TypeSystemImpl) {
+ args[i] = typeSystem.getGreatestLowerBound(args1[i], args2[i]);
} else {
args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
}
@@ -2201,7 +2849,8 @@
// parameters.
args[i] = args1[i];
} else {
- args[i] = typeSystem.getLeastUpperBound(args1[i], args2[i]);
+ throw new StateError('Type parameter ${params[i]} has unknown '
+ 'variance $parameterVariance for bounds calculation.');
}
}
@@ -2499,73 +3148,7 @@
/**
* Compute the least upper bound of two types.
*/
- DartType getLeastUpperBound(DartType type1, DartType type2) {
- // The least upper bound relation is reflexive.
- if (identical(type1, type2)) {
- return type1;
- }
-
- // For any type T, LUB(?, T) == T.
- if (identical(type1, UnknownInferredType.instance)) {
- return type2;
- }
- if (identical(type2, UnknownInferredType.instance)) {
- return type1;
- }
-
- // For the purpose of LUB, we say some Tops are subtypes (less toppy) than
- // the others. Return the most toppy.
- // TODO(mfairhurst): switch legacy Top checks to true Top checks
- if (_isLegacyTop(type1, orTrueTop: true) &&
- _isLegacyTop(type2, orTrueTop: true)) {
- return _getTopiness(type1) > _getTopiness(type2) ? type1 : type2;
- }
-
- // The least upper bound of top and any type T is top.
- // The least upper bound of bottom and any type T is T.
- // TODO(mfairhurst): switch legacy Top checks to true Top checks
- // TODO(mfairhurst): switch legacy Bottom checks to true Bottom checks
- if (_isLegacyTop(type1, orTrueTop: true) ||
- _isLegacyBottom(type2, orTrueBottom: true)) {
- return type1;
- }
- // TODO(mfairhurst): switch legacy Top checks to true Top checks
- // TODO(mfairhurst): switch legacy Bottom checks to true Bottom checks
- if (_isLegacyTop(type2, orTrueTop: true) ||
- _isLegacyBottom(type1, orTrueBottom: true)) {
- return type2;
- }
-
- if (type1 is TypeParameterType || type2 is TypeParameterType) {
- return _typeParameterLeastUpperBound(type1, type2);
- }
-
- // In Dart 1, the least upper bound of a function type and an interface type
- // T is the least upper bound of Function and T.
- //
- // In Dart 2, the result is `Function` iff T is `Function`, otherwise the
- // result is `Object`.
- if (type1 is FunctionType && type2 is InterfaceType) {
- return type2.isDartCoreFunction ? type2 : typeProvider.objectType;
- }
- if (type2 is FunctionType && type1 is InterfaceType) {
- return type1.isDartCoreFunction ? type1 : typeProvider.objectType;
- }
-
- // At this point type1 and type2 should both either be interface types or
- // function types.
- if (type1 is InterfaceType && type2 is InterfaceType) {
- return _interfaceLeastUpperBound(type1, type2);
- }
-
- if (type1 is FunctionType && type2 is FunctionType) {
- return _functionLeastUpperBound(type1, type2);
- }
-
- // Should never happen. As a defensive measure, return the dynamic type.
- assert(false);
- return typeProvider.dynamicType;
- }
+ DartType getLeastUpperBound(DartType type1, DartType type2);
/**
* Given a [DartType] [type], instantiate it with its bounds.
@@ -2879,121 +3462,6 @@
}
/**
- * Compute the least upper bound of function types [f] and [g].
- *
- * The spec rules for LUB on function types, informally, are pretty simple
- * (though unsound):
- *
- * - If the functions don't have the same number of required parameters,
- * always return `Function`.
- *
- * - Discard any optional named or positional parameters the two types do not
- * have in common.
- *
- * - Compute the LUB of each corresponding pair of parameter and return types.
- * Return a function type with those types.
- */
- DartType _functionLeastUpperBound(FunctionType f, FunctionType g) {
- var fTypeFormals = f.typeFormals;
- var gTypeFormals = g.typeFormals;
-
- // If F and G differ in their number of type parameters, then the
- // least upper bound of F and G is Function.
- if (fTypeFormals.length != gTypeFormals.length) {
- return typeProvider.functionType;
- }
-
- // If F and G differ in bounds of their of type parameters, then the
- // least upper bound of F and G is Function.
- var freshTypeFormalTypes =
- FunctionTypeImpl.relateTypeFormals(f, g, (t, s, _, __) => t == s);
- if (freshTypeFormalTypes == null) {
- return typeProvider.functionType;
- }
-
- var typeFormals = freshTypeFormalTypes
- .map<TypeParameterElement>((t) => t.element)
- .toList();
-
- f = f.instantiate(freshTypeFormalTypes);
- g = g.instantiate(freshTypeFormalTypes);
-
- List<DartType> fRequired = f.normalParameterTypes;
- List<DartType> gRequired = g.normalParameterTypes;
-
- // We need some parameter names for in the synthesized function type, so
- // arbitrarily use f's.
- List<String> fRequiredNames = f.normalParameterNames;
- List<String> fPositionalNames = f.optionalParameterNames;
-
- // If F and G differ in their number of required parameters, then the
- // least upper bound of F and G is Function.
- if (fRequired.length != gRequired.length) {
- return typeProvider.functionType;
- }
-
- // Calculate the LUB of each corresponding pair of parameters.
- List<ParameterElement> parameters = [];
-
- for (int i = 0; i < fRequired.length; i++) {
- parameters.add(new ParameterElementImpl.synthetic(
- fRequiredNames[i],
- _functionParameterBound(fRequired[i], gRequired[i]),
- ParameterKind.REQUIRED));
- }
-
- List<DartType> fPositional = f.optionalParameterTypes;
- List<DartType> gPositional = g.optionalParameterTypes;
-
- // Ignore any extra optional positional parameters if one has more than the
- // other.
- int length = math.min(fPositional.length, gPositional.length);
- for (int i = 0; i < length; i++) {
- parameters.add(new ParameterElementImpl.synthetic(
- fPositionalNames[i],
- _functionParameterBound(fPositional[i], gPositional[i]),
- ParameterKind.POSITIONAL));
- }
-
- // TODO(brianwilkerson) Handle the fact that named parameters can now be
- // required.
- Map<String, DartType> fNamed = f.namedParameterTypes;
- Map<String, DartType> gNamed = g.namedParameterTypes;
- for (String name in fNamed.keys.toSet()..retainAll(gNamed.keys)) {
- parameters.add(new ParameterElementImpl.synthetic(
- name,
- _functionParameterBound(fNamed[name], gNamed[name]),
- ParameterKind.NAMED));
- }
-
- // Calculate the LUB of the return type.
- DartType returnType = getLeastUpperBound(f.returnType, g.returnType);
-
- return FunctionTypeImpl(
- typeFormals: typeFormals,
- parameters: parameters,
- returnType: returnType,
- nullabilitySuffix: (f as TypeImpl).nullabilitySuffix,
- );
- }
-
- /**
- * Calculates the appropriate upper or lower bound of a pair of parameters
- * for two function types whose least upper bound is being calculated.
- *
- * In spec mode, this uses least upper bound, which... doesn't really make
- * much sense. Strong mode overrides this to use greatest lower bound.
- */
- DartType _functionParameterBound(DartType f, DartType g) =>
- getLeastUpperBound(f, g);
-
- /**
- * Given two [InterfaceType]s [type1] and [type2] return their least upper
- * bound in a type system specific manner.
- */
- DartType _interfaceLeastUpperBound(InterfaceType type1, InterfaceType type2);
-
- /**
* Starting from the given [type], search its class hierarchy for types of the
* form Future<R>, and return a list of the resulting R's.
*/
@@ -3018,23 +3486,23 @@
recurse(type);
return result;
}
+}
- /**
- * Given two [DartType]s [type1] and [type2] at least one of which is a
- * [TypeParameterType], return their least upper bound in a type system
- * specific manner.
- */
- DartType _typeParameterLeastUpperBound(DartType type1, DartType type2);
-
- /**
- * Create either a strong mode or regular type system based on context.
- */
- static TypeSystem create(AnalysisContext context) {
- var options = context.analysisOptions as AnalysisOptionsImpl;
- return new Dart2TypeSystem(context.typeProvider,
- implicitCasts: options.implicitCasts,
- strictInference: options.strictInference);
- }
+/**
+ * The [public.TypeSystem] implementation.
+ */
+class TypeSystemImpl extends Dart2TypeSystem {
+ TypeSystemImpl({
+ @required bool implicitCasts,
+ @required bool isNonNullableByDefault,
+ @required bool strictInference,
+ @required TypeProvider typeProvider,
+ }) : super(
+ implicitCasts: implicitCasts,
+ isNonNullableByDefault: isNonNullableByDefault,
+ strictInference: strictInference,
+ typeProvider: typeProvider,
+ );
}
/// A type that is being inferred but is not currently known.
@@ -3062,8 +3530,7 @@
bool operator ==(Object object) => identical(object, this);
@override
- void appendTo(StringBuffer buffer, Set<TypeImpl> types,
- {bool withNullability = false}) {
+ void appendTo(StringBuffer buffer, {bool withNullability = false}) {
buffer.write('?');
}
@@ -3160,7 +3627,7 @@
bool get isDownwards => origin is! _TypeConstraintFromArgument;
- bool isSatisifedBy(TypeSystem ts, DartType type) =>
+ bool isSatisifedBy(TypeSystemImpl ts, DartType type) =>
ts.isSubtypeOf(lowerBound, type) && ts.isSubtypeOf(type, upperBound);
/// Converts this constraint to a message suitable for a type inference error.
diff --git a/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
index 2596ac9..f2fb192 100644
--- a/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
+++ b/pkg/analyzer/lib/src/ignore_comments/ignore_info.dart
@@ -36,26 +36,15 @@
final Set<String> _ignoreForFileSet = new HashSet<String>();
/// Whether this info object defines any ignores.
- bool get hasIgnores => ignores.isNotEmpty || _ignoreForFileSet.isNotEmpty;
-
- /// Iterable of error codes ignored for the whole file.
- Iterable<String> get ignoreForFiles => _ignoreForFileSet;
-
- /// Map of line numbers to associated ignored error codes.
- Map<int, Iterable<String>> get ignores => _ignoreMap;
-
- /// Ignore this [errorCode] at [line].
- void add(int line, String errorCode) {
- _ignoreMap.putIfAbsent(line, () => new List<String>()).add(errorCode);
- }
+ bool get hasIgnores => _ignoreMap.isNotEmpty || _ignoreForFileSet.isNotEmpty;
/// Ignore these [errorCodes] at [line].
- void addAll(int line, Iterable<String> errorCodes) {
+ void _addAll(int line, Iterable<String> errorCodes) {
_ignoreMap.putIfAbsent(line, () => new List<String>()).addAll(errorCodes);
}
/// Ignore these [errorCodes] in the whole file.
- void addAllForFile(Iterable<String> errorCodes) {
+ void _addAllForFile(Iterable<String> errorCodes) {
_ignoreForFileSet.addAll(errorCodes);
}
@@ -87,10 +76,10 @@
if (beforeMatch.trim().isEmpty) {
// The comment is on its own line, so it refers to the next line.
- ignoreInfo.addAll(lineNumber + 1, codes);
+ ignoreInfo._addAll(lineNumber + 1, codes);
} else {
// The comment sits next to code, so it refers to its own line.
- ignoreInfo.addAll(lineNumber, codes);
+ ignoreInfo._addAll(lineNumber, codes);
}
}
for (Match match in fileMatches) {
@@ -98,7 +87,7 @@
.group(1)
.split(',')
.map((String code) => code.trim().toLowerCase());
- ignoreInfo.addAllForFile(codes);
+ ignoreInfo._addAllForFile(codes);
}
return ignoreInfo;
}
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 6e51f55..319b9e9 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -8,19 +8,23 @@
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart' as file_system;
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/constant/potentially_constant.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/error/lint_codes.dart';
import 'package:analyzer/src/generated/engine.dart'
show AnalysisErrorInfo, AnalysisErrorInfoImpl, AnalysisOptions;
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/resolver.dart'
+ show ConstantVerifier, TypeProvider;
import 'package:analyzer/src/generated/source.dart' show LineInfo;
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/lint/analysis.dart';
@@ -201,6 +205,17 @@
String _emph(msg) => bold ? '<strong>$msg</strong>' : msg;
}
+/// The result of attempting to evaluate an expression.
+class LinterConstantEvaluationResult {
+ /// The value of the expression, or `null` if has [errors].
+ final DartObject value;
+
+ /// The errors reported during the evaluation.
+ final List<AnalysisError> errors;
+
+ LinterConstantEvaluationResult(this.value, this.errors);
+}
+
/// Provides access to information needed by lint rules that is not available
/// from AST nodes or the element model.
abstract class LinterContext {
@@ -239,6 +254,9 @@
/// Note that this method can cause constant evaluation to occur, which can be
/// computationally expensive.
bool canBeConstConstructor(ConstructorDeclaration node);
+
+ /// Return the result of evaluating the given expression.
+ LinterConstantEvaluationResult evaluateConstant(Expression node);
}
/// Implementation of [LinterContext]
@@ -323,6 +341,23 @@
}
}
+ @override
+ LinterConstantEvaluationResult evaluateConstant(Expression node) {
+ var source = currentUnit.unit.declaredElement.source;
+ var errorListener = RecordingErrorListener();
+ var visitor = ConstantVisitor(
+ ConstantEvaluationEngine(
+ typeProvider,
+ declaredVariables,
+ typeSystem: typeSystem,
+ ),
+ ErrorReporter(errorListener, source),
+ );
+
+ var value = node.accept(visitor);
+ return LinterConstantEvaluationResult(value, errorListener.errors);
+ }
+
/// Return `true` if [ConstantVerifier] reports an error for the [node].
bool _hasConstantVerifierError(AstNode node) {
var unitElement = currentUnit.unit.declaredElement;
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index 180e833..f1a916a 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -198,29 +198,34 @@
_addKnownLibraries(dependencyLibraries);
}
- _Package package;
- for (var candidatePackage in _packages) {
- if (candidatePackage.contains(path)) {
- package = candidatePackage;
- break;
- }
- }
-
var contextPathList = <String>[];
- if (package != null) {
- var containingFolder = package.folderInRootContaining(path);
- if (containingFolder != null) {
- for (var contextPath in _contextPathList) {
- // `lib/` can see only libraries in `lib/`.
- // `test/` can see libraries in `lib/` and in `test/`.
- if (package.containsInLib(contextPath) ||
- containingFolder.contains(contextPath)) {
- contextPathList.add(contextPath);
- }
+ if (!_analysisContext.workspace.isBazel) {
+ _Package package;
+ for (var candidatePackage in _packages) {
+ if (candidatePackage.contains(path)) {
+ package = candidatePackage;
+ break;
}
}
+
+ if (package != null) {
+ var containingFolder = package.folderInRootContaining(path);
+ if (containingFolder != null) {
+ for (var contextPath in _contextPathList) {
+ // `lib/` can see only libraries in `lib/`.
+ // `test/` can see libraries in `lib/` and in `test/`.
+ if (package.containsInLib(contextPath) ||
+ containingFolder.contains(contextPath)) {
+ contextPathList.add(contextPath);
+ }
+ }
+ }
+ } else {
+ // Not in a package, include all libraries of the context.
+ contextPathList = _contextPathList;
+ }
} else {
- // Not in a package, include all libraries of the context.
+ // In bazel workspaces, consider declarations from the entire context
contextPathList = _contextPathList;
}
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index f702e50..77fd089 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -1834,7 +1834,6 @@
List<String> _definedTopLevelNames;
List<String> _referencedNames;
List<String> _subtypedNames;
- UnlinkedUnitBuilder _unit;
UnlinkedUnit2Builder _unit2;
@override
@@ -1872,14 +1871,6 @@
}
@override
- UnlinkedUnitBuilder get unit => _unit;
-
- /// Unlinked information for the unit.
- set unit(UnlinkedUnitBuilder value) {
- this._unit = value;
- }
-
- @override
UnlinkedUnit2Builder get unit2 => _unit2;
/// Unlinked information for the unit.
@@ -1892,18 +1883,15 @@
List<String> definedTopLevelNames,
List<String> referencedNames,
List<String> subtypedNames,
- UnlinkedUnitBuilder unit,
UnlinkedUnit2Builder unit2})
: _definedClassMemberNames = definedClassMemberNames,
_definedTopLevelNames = definedTopLevelNames,
_referencedNames = referencedNames,
_subtypedNames = subtypedNames,
- _unit = unit,
_unit2 = unit2;
/// Flush [informative] data recursively.
void flushInformative() {
- _unit?.flushInformative();
_unit2?.flushInformative();
}
@@ -1917,8 +1905,6 @@
signature.addString(x);
}
}
- signature.addBool(this._unit != null);
- this._unit?.collectApiSignature(signature);
if (this._definedTopLevelNames == null) {
signature.addInt(0);
} else {
@@ -1957,7 +1943,6 @@
fb.Offset offset_definedTopLevelNames;
fb.Offset offset_referencedNames;
fb.Offset offset_subtypedNames;
- fb.Offset offset_unit;
fb.Offset offset_unit2;
if (!(_definedClassMemberNames == null ||
_definedClassMemberNames.isEmpty)) {
@@ -1978,30 +1963,24 @@
offset_subtypedNames = fbBuilder.writeList(
_subtypedNames.map((b) => fbBuilder.writeString(b)).toList());
}
- if (_unit != null) {
- offset_unit = _unit.finish(fbBuilder);
- }
if (_unit2 != null) {
offset_unit2 = _unit2.finish(fbBuilder);
}
fbBuilder.startTable();
if (offset_definedClassMemberNames != null) {
- fbBuilder.addOffset(3, offset_definedClassMemberNames);
+ fbBuilder.addOffset(2, offset_definedClassMemberNames);
}
if (offset_definedTopLevelNames != null) {
- fbBuilder.addOffset(2, offset_definedTopLevelNames);
+ fbBuilder.addOffset(1, offset_definedTopLevelNames);
}
if (offset_referencedNames != null) {
fbBuilder.addOffset(0, offset_referencedNames);
}
if (offset_subtypedNames != null) {
- fbBuilder.addOffset(4, offset_subtypedNames);
- }
- if (offset_unit != null) {
- fbBuilder.addOffset(1, offset_unit);
+ fbBuilder.addOffset(3, offset_subtypedNames);
}
if (offset_unit2 != null) {
- fbBuilder.addOffset(5, offset_unit2);
+ fbBuilder.addOffset(4, offset_unit2);
}
return fbBuilder.endTable();
}
@@ -2035,14 +2014,13 @@
List<String> _definedTopLevelNames;
List<String> _referencedNames;
List<String> _subtypedNames;
- idl.UnlinkedUnit _unit;
idl.UnlinkedUnit2 _unit2;
@override
List<String> get definedClassMemberNames {
_definedClassMemberNames ??=
const fb.ListReader<String>(const fb.StringReader())
- .vTableGet(_bc, _bcOffset, 3, const <String>[]);
+ .vTableGet(_bc, _bcOffset, 2, const <String>[]);
return _definedClassMemberNames;
}
@@ -2050,7 +2028,7 @@
List<String> get definedTopLevelNames {
_definedTopLevelNames ??=
const fb.ListReader<String>(const fb.StringReader())
- .vTableGet(_bc, _bcOffset, 2, const <String>[]);
+ .vTableGet(_bc, _bcOffset, 1, const <String>[]);
return _definedTopLevelNames;
}
@@ -2064,19 +2042,13 @@
@override
List<String> get subtypedNames {
_subtypedNames ??= const fb.ListReader<String>(const fb.StringReader())
- .vTableGet(_bc, _bcOffset, 4, const <String>[]);
+ .vTableGet(_bc, _bcOffset, 3, const <String>[]);
return _subtypedNames;
}
@override
- idl.UnlinkedUnit get unit {
- _unit ??= const _UnlinkedUnitReader().vTableGet(_bc, _bcOffset, 1, null);
- return _unit;
- }
-
- @override
idl.UnlinkedUnit2 get unit2 {
- _unit2 ??= const _UnlinkedUnit2Reader().vTableGet(_bc, _bcOffset, 5, null);
+ _unit2 ??= const _UnlinkedUnit2Reader().vTableGet(_bc, _bcOffset, 4, null);
return _unit2;
}
}
@@ -2093,7 +2065,6 @@
if (referencedNames.isNotEmpty)
_result["referencedNames"] = referencedNames;
if (subtypedNames.isNotEmpty) _result["subtypedNames"] = subtypedNames;
- if (unit != null) _result["unit"] = unit.toJson();
if (unit2 != null) _result["unit2"] = unit2.toJson();
return _result;
}
@@ -2104,7 +2075,6 @@
"definedTopLevelNames": definedTopLevelNames,
"referencedNames": referencedNames,
"subtypedNames": subtypedNames,
- "unit": unit,
"unit2": unit2,
};
@@ -3675,80 +3645,6 @@
String toString() => convert.json.encode(toJson());
}
-class LinkedLibraryBuilder extends Object
- with _LinkedLibraryMixin
- implements idl.LinkedLibrary {
- int _placeholder;
-
- @override
- int get placeholder => _placeholder ??= 0;
-
- set placeholder(int value) {
- assert(value == null || value >= 0);
- this._placeholder = value;
- }
-
- LinkedLibraryBuilder({int placeholder}) : _placeholder = placeholder;
-
- /// Flush [informative] data recursively.
- void flushInformative() {}
-
- /// Accumulate non-[informative] data into [signature].
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addInt(this._placeholder ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fbBuilder.startTable();
- if (_placeholder != null && _placeholder != 0) {
- fbBuilder.addUint32(0, _placeholder);
- }
- return fbBuilder.endTable();
- }
-}
-
-class _LinkedLibraryReader extends fb.TableReader<_LinkedLibraryImpl> {
- const _LinkedLibraryReader();
-
- @override
- _LinkedLibraryImpl createObject(fb.BufferContext bc, int offset) =>
- new _LinkedLibraryImpl(bc, offset);
-}
-
-class _LinkedLibraryImpl extends Object
- with _LinkedLibraryMixin
- implements idl.LinkedLibrary {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- _LinkedLibraryImpl(this._bc, this._bcOffset);
-
- int _placeholder;
-
- @override
- int get placeholder {
- _placeholder ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 0, 0);
- return _placeholder;
- }
-}
-
-abstract class _LinkedLibraryMixin implements idl.LinkedLibrary {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (placeholder != 0) _result["placeholder"] = placeholder;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "placeholder": placeholder,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
class LinkedNodeBuilder extends Object
with _LinkedNodeMixin
implements idl.LinkedNode {
@@ -6110,6 +6006,12 @@
return _variantField_28 ??= idl.UnlinkedTokenType.NOTHING;
}
+ @override
+ idl.UnlinkedTokenType get typeParameter_variance {
+ assert(kind == idl.LinkedNodeKind.typeParameter);
+ return _variantField_28 ??= idl.UnlinkedTokenType.NOTHING;
+ }
+
set assignmentExpression_operator(idl.UnlinkedTokenType value) {
assert(kind == idl.LinkedNodeKind.assignmentExpression);
_variantField_28 = value;
@@ -6135,6 +6037,11 @@
_variantField_28 = value;
}
+ set typeParameter_variance(idl.UnlinkedTokenType value) {
+ assert(kind == idl.LinkedNodeKind.typeParameter);
+ _variantField_28 = value;
+ }
+
@override
bool get booleanLiteral_value {
assert(kind == idl.LinkedNodeKind.booleanLiteral);
@@ -7881,11 +7788,13 @@
LinkedNodeBuilder.typeParameter({
List<LinkedNodeBuilder> annotatedNode_metadata,
LinkedNodeBuilder typeParameter_bound,
+ idl.UnlinkedTokenType typeParameter_variance,
int informativeId,
LinkedNodeTypeBuilder typeParameter_defaultType,
}) : _kind = idl.LinkedNodeKind.typeParameter,
_variantField_4 = annotatedNode_metadata,
_variantField_6 = typeParameter_bound,
+ _variantField_28 = typeParameter_variance,
_variantField_36 = informativeId,
_variantField_23 = typeParameter_defaultType;
@@ -9917,6 +9826,9 @@
signature.addInt(this.flags ?? 0);
signature.addBool(this.typeParameter_defaultType != null);
this.typeParameter_defaultType?.collectApiSignature(signature);
+ signature.addInt(this.typeParameter_variance == null
+ ? 0
+ : this.typeParameter_variance.index);
signature.addString(this.name ?? '');
} else if (kind == idl.LinkedNodeKind.typeParameterList) {
signature.addInt(this.kind == null ? 0 : this.kind.index);
@@ -12008,6 +11920,14 @@
}
@override
+ idl.UnlinkedTokenType get typeParameter_variance {
+ assert(kind == idl.LinkedNodeKind.typeParameter);
+ _variantField_28 ??= const _UnlinkedTokenTypeReader()
+ .vTableGet(_bc, _bcOffset, 28, idl.UnlinkedTokenType.NOTHING);
+ return _variantField_28;
+ }
+
+ @override
bool get booleanLiteral_value {
assert(kind == idl.LinkedNodeKind.booleanLiteral);
_variantField_27 ??=
@@ -13636,6 +13556,9 @@
annotatedNode_metadata.map((_value) => _value.toJson()).toList();
if (typeParameter_bound != null)
_result["typeParameter_bound"] = typeParameter_bound.toJson();
+ if (typeParameter_variance != idl.UnlinkedTokenType.NOTHING)
+ _result["typeParameter_variance"] =
+ typeParameter_variance.toString().split('.')[1];
if (informativeId != 0) _result["informativeId"] = informativeId;
if (typeParameter_defaultType != null)
_result["typeParameter_defaultType"] =
@@ -14887,6 +14810,7 @@
return {
"annotatedNode_metadata": annotatedNode_metadata,
"typeParameter_bound": typeParameter_bound,
+ "typeParameter_variance": typeParameter_variance,
"flags": flags,
"informativeId": informativeId,
"kind": kind,
@@ -16256,7 +16180,6 @@
bool _isSynthetic;
LinkedNodeBuilder _node;
String _partUriStr;
- UnlinkedTokensBuilder _tokens;
String _uriStr;
@override
@@ -16290,13 +16213,6 @@
}
@override
- UnlinkedTokensBuilder get tokens => _tokens;
-
- set tokens(UnlinkedTokensBuilder value) {
- this._tokens = value;
- }
-
- @override
String get uriStr => _uriStr ??= '';
/// The absolute URI.
@@ -16309,26 +16225,21 @@
bool isSynthetic,
LinkedNodeBuilder node,
String partUriStr,
- UnlinkedTokensBuilder tokens,
String uriStr})
: _isNNBD = isNNBD,
_isSynthetic = isSynthetic,
_node = node,
_partUriStr = partUriStr,
- _tokens = tokens,
_uriStr = uriStr;
/// Flush [informative] data recursively.
void flushInformative() {
_node?.flushInformative();
- _tokens?.flushInformative();
}
/// Accumulate non-[informative] data into [signature].
void collectApiSignature(api_sig.ApiSignature signature) {
signature.addString(this._uriStr ?? '');
- signature.addBool(this._tokens != null);
- this._tokens?.collectApiSignature(signature);
signature.addBool(this._node != null);
this._node?.collectApiSignature(signature);
signature.addBool(this._isSynthetic == true);
@@ -16339,7 +16250,6 @@
fb.Offset finish(fb.Builder fbBuilder) {
fb.Offset offset_node;
fb.Offset offset_partUriStr;
- fb.Offset offset_tokens;
fb.Offset offset_uriStr;
if (_node != null) {
offset_node = _node.finish(fbBuilder);
@@ -16347,27 +16257,21 @@
if (_partUriStr != null) {
offset_partUriStr = fbBuilder.writeString(_partUriStr);
}
- if (_tokens != null) {
- offset_tokens = _tokens.finish(fbBuilder);
- }
if (_uriStr != null) {
offset_uriStr = fbBuilder.writeString(_uriStr);
}
fbBuilder.startTable();
if (_isNNBD == true) {
- fbBuilder.addBool(4, true);
- }
- if (_isSynthetic == true) {
fbBuilder.addBool(3, true);
}
+ if (_isSynthetic == true) {
+ fbBuilder.addBool(2, true);
+ }
if (offset_node != null) {
- fbBuilder.addOffset(2, offset_node);
+ fbBuilder.addOffset(1, offset_node);
}
if (offset_partUriStr != null) {
- fbBuilder.addOffset(5, offset_partUriStr);
- }
- if (offset_tokens != null) {
- fbBuilder.addOffset(1, offset_tokens);
+ fbBuilder.addOffset(4, offset_partUriStr);
}
if (offset_uriStr != null) {
fbBuilder.addOffset(0, offset_uriStr);
@@ -16396,41 +16300,33 @@
bool _isSynthetic;
idl.LinkedNode _node;
String _partUriStr;
- idl.UnlinkedTokens _tokens;
String _uriStr;
@override
bool get isNNBD {
- _isNNBD ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 4, false);
+ _isNNBD ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
return _isNNBD;
}
@override
bool get isSynthetic {
- _isSynthetic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
+ _isSynthetic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
return _isSynthetic;
}
@override
idl.LinkedNode get node {
- _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
+ _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 1, null);
return _node;
}
@override
String get partUriStr {
- _partUriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 5, '');
+ _partUriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 4, '');
return _partUriStr;
}
@override
- idl.UnlinkedTokens get tokens {
- _tokens ??=
- const _UnlinkedTokensReader().vTableGet(_bc, _bcOffset, 1, null);
- return _tokens;
- }
-
- @override
String get uriStr {
_uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
return _uriStr;
@@ -16445,7 +16341,6 @@
if (isSynthetic != false) _result["isSynthetic"] = isSynthetic;
if (node != null) _result["node"] = node.toJson();
if (partUriStr != '') _result["partUriStr"] = partUriStr;
- if (tokens != null) _result["tokens"] = tokens.toJson();
if (uriStr != '') _result["uriStr"] = uriStr;
return _result;
}
@@ -16456,7 +16351,6 @@
"isSynthetic": isSynthetic,
"node": node,
"partUriStr": partUriStr,
- "tokens": tokens,
"uriStr": uriStr,
};
@@ -16468,12 +16362,6 @@
with _PackageBundleMixin
implements idl.PackageBundle {
LinkedNodeBundleBuilder _bundle2;
- int _majorVersion;
- int _minorVersion;
-
- @override
- Null get apiSignature =>
- throw new UnimplementedError('attempt to access deprecated field');
@override
LinkedNodeBundleBuilder get bundle2 => _bundle2;
@@ -16483,55 +16371,7 @@
this._bundle2 = value;
}
- @override
- Null get dependencies =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- @override
- Null get linkedLibraries =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- @override
- Null get linkedLibraryUris =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- @override
- int get majorVersion => _majorVersion ??= 0;
-
- /// Major version of the summary format. See
- /// [PackageBundleAssembler.currentMajorVersion].
- set majorVersion(int value) {
- assert(value == null || value >= 0);
- this._majorVersion = value;
- }
-
- @override
- int get minorVersion => _minorVersion ??= 0;
-
- /// Minor version of the summary format. See
- /// [PackageBundleAssembler.currentMinorVersion].
- set minorVersion(int value) {
- assert(value == null || value >= 0);
- this._minorVersion = value;
- }
-
- @override
- Null get unlinkedUnitHashes =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- @override
- Null get unlinkedUnits =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- @override
- Null get unlinkedUnitUris =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- PackageBundleBuilder(
- {LinkedNodeBundleBuilder bundle2, int majorVersion, int minorVersion})
- : _bundle2 = bundle2,
- _majorVersion = majorVersion,
- _minorVersion = minorVersion;
+ PackageBundleBuilder({LinkedNodeBundleBuilder bundle2}) : _bundle2 = bundle2;
/// Flush [informative] data recursively.
void flushInformative() {
@@ -16540,8 +16380,6 @@
/// Accumulate non-[informative] data into [signature].
void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addInt(this._majorVersion ?? 0);
- signature.addInt(this._minorVersion ?? 0);
signature.addBool(this._bundle2 != null);
this._bundle2?.collectApiSignature(signature);
}
@@ -16558,13 +16396,7 @@
}
fbBuilder.startTable();
if (offset_bundle2 != null) {
- fbBuilder.addOffset(9, offset_bundle2);
- }
- if (_majorVersion != null && _majorVersion != 0) {
- fbBuilder.addUint32(5, _majorVersion);
- }
- if (_minorVersion != null && _minorVersion != 0) {
- fbBuilder.addUint32(6, _minorVersion);
+ fbBuilder.addOffset(0, offset_bundle2);
}
return fbBuilder.endTable();
}
@@ -16592,55 +16424,13 @@
_PackageBundleImpl(this._bc, this._bcOffset);
idl.LinkedNodeBundle _bundle2;
- int _majorVersion;
- int _minorVersion;
-
- @override
- Null get apiSignature =>
- throw new UnimplementedError('attempt to access deprecated field');
@override
idl.LinkedNodeBundle get bundle2 {
_bundle2 ??=
- const _LinkedNodeBundleReader().vTableGet(_bc, _bcOffset, 9, null);
+ const _LinkedNodeBundleReader().vTableGet(_bc, _bcOffset, 0, null);
return _bundle2;
}
-
- @override
- Null get dependencies =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- @override
- Null get linkedLibraries =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- @override
- Null get linkedLibraryUris =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- @override
- int get majorVersion {
- _majorVersion ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 5, 0);
- return _majorVersion;
- }
-
- @override
- int get minorVersion {
- _minorVersion ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 6, 0);
- return _minorVersion;
- }
-
- @override
- Null get unlinkedUnitHashes =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- @override
- Null get unlinkedUnits =>
- throw new UnimplementedError('attempt to access deprecated field');
-
- @override
- Null get unlinkedUnitUris =>
- throw new UnimplementedError('attempt to access deprecated field');
}
abstract class _PackageBundleMixin implements idl.PackageBundle {
@@ -16648,92 +16438,12 @@
Map<String, Object> toJson() {
Map<String, Object> _result = <String, Object>{};
if (bundle2 != null) _result["bundle2"] = bundle2.toJson();
- if (majorVersion != 0) _result["majorVersion"] = majorVersion;
- if (minorVersion != 0) _result["minorVersion"] = minorVersion;
return _result;
}
@override
Map<String, Object> toMap() => {
"bundle2": bundle2,
- "majorVersion": majorVersion,
- "minorVersion": minorVersion,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class PackageDependencyInfoBuilder extends Object
- with _PackageDependencyInfoMixin
- implements idl.PackageDependencyInfo {
- int _placeholder;
-
- @override
- int get placeholder => _placeholder ??= 0;
-
- set placeholder(int value) {
- assert(value == null || value >= 0);
- this._placeholder = value;
- }
-
- PackageDependencyInfoBuilder({int placeholder}) : _placeholder = placeholder;
-
- /// Flush [informative] data recursively.
- void flushInformative() {}
-
- /// Accumulate non-[informative] data into [signature].
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addInt(this._placeholder ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fbBuilder.startTable();
- if (_placeholder != null && _placeholder != 0) {
- fbBuilder.addUint32(0, _placeholder);
- }
- return fbBuilder.endTable();
- }
-}
-
-class _PackageDependencyInfoReader
- extends fb.TableReader<_PackageDependencyInfoImpl> {
- const _PackageDependencyInfoReader();
-
- @override
- _PackageDependencyInfoImpl createObject(fb.BufferContext bc, int offset) =>
- new _PackageDependencyInfoImpl(bc, offset);
-}
-
-class _PackageDependencyInfoImpl extends Object
- with _PackageDependencyInfoMixin
- implements idl.PackageDependencyInfo {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- _PackageDependencyInfoImpl(this._bc, this._bcOffset);
-
- int _placeholder;
-
- @override
- int get placeholder {
- _placeholder ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 0, 0);
- return _placeholder;
- }
-}
-
-abstract class _PackageDependencyInfoMixin
- implements idl.PackageDependencyInfo {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (placeholder != 0) _result["placeholder"] = placeholder;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "placeholder": placeholder,
};
@override
@@ -18347,154 +18057,6 @@
String toString() => convert.json.encode(toJson());
}
-class UnlinkedTokensBuilder extends Object
- with _UnlinkedTokensMixin
- implements idl.UnlinkedTokens {
- int _placeholder;
-
- @override
- int get placeholder => _placeholder ??= 0;
-
- set placeholder(int value) {
- assert(value == null || value >= 0);
- this._placeholder = value;
- }
-
- UnlinkedTokensBuilder({int placeholder}) : _placeholder = placeholder;
-
- /// Flush [informative] data recursively.
- void flushInformative() {}
-
- /// Accumulate non-[informative] data into [signature].
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addInt(this._placeholder ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fbBuilder.startTable();
- if (_placeholder != null && _placeholder != 0) {
- fbBuilder.addUint32(0, _placeholder);
- }
- return fbBuilder.endTable();
- }
-}
-
-class _UnlinkedTokensReader extends fb.TableReader<_UnlinkedTokensImpl> {
- const _UnlinkedTokensReader();
-
- @override
- _UnlinkedTokensImpl createObject(fb.BufferContext bc, int offset) =>
- new _UnlinkedTokensImpl(bc, offset);
-}
-
-class _UnlinkedTokensImpl extends Object
- with _UnlinkedTokensMixin
- implements idl.UnlinkedTokens {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- _UnlinkedTokensImpl(this._bc, this._bcOffset);
-
- int _placeholder;
-
- @override
- int get placeholder {
- _placeholder ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 0, 0);
- return _placeholder;
- }
-}
-
-abstract class _UnlinkedTokensMixin implements idl.UnlinkedTokens {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (placeholder != 0) _result["placeholder"] = placeholder;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "placeholder": placeholder,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class UnlinkedUnitBuilder extends Object
- with _UnlinkedUnitMixin
- implements idl.UnlinkedUnit {
- int _placeholder;
-
- @override
- int get placeholder => _placeholder ??= 0;
-
- set placeholder(int value) {
- assert(value == null || value >= 0);
- this._placeholder = value;
- }
-
- UnlinkedUnitBuilder({int placeholder}) : _placeholder = placeholder;
-
- /// Flush [informative] data recursively.
- void flushInformative() {}
-
- /// Accumulate non-[informative] data into [signature].
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addInt(this._placeholder ?? 0);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fbBuilder.startTable();
- if (_placeholder != null && _placeholder != 0) {
- fbBuilder.addUint32(0, _placeholder);
- }
- return fbBuilder.endTable();
- }
-}
-
-class _UnlinkedUnitReader extends fb.TableReader<_UnlinkedUnitImpl> {
- const _UnlinkedUnitReader();
-
- @override
- _UnlinkedUnitImpl createObject(fb.BufferContext bc, int offset) =>
- new _UnlinkedUnitImpl(bc, offset);
-}
-
-class _UnlinkedUnitImpl extends Object
- with _UnlinkedUnitMixin
- implements idl.UnlinkedUnit {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- _UnlinkedUnitImpl(this._bc, this._bcOffset);
-
- int _placeholder;
-
- @override
- int get placeholder {
- _placeholder ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 0, 0);
- return _placeholder;
- }
-}
-
-abstract class _UnlinkedUnitMixin implements idl.UnlinkedUnit {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (placeholder != 0) _result["placeholder"] = placeholder;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "placeholder": placeholder,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
class UnlinkedUnit2Builder extends Object
with _UnlinkedUnit2Mixin
implements idl.UnlinkedUnit2 {
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index f65b42b..be47572 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -442,7 +442,7 @@
overrideConflictParameterType
}
-/// TODO(scheglov) document
+/// Enum of token types, corresponding to AST token types.
enum UnlinkedTokenType : byte {
NOTHING,
@@ -724,7 +724,11 @@
WITH,
- YIELD
+ YIELD,
+
+ INOUT,
+
+ OUT
}
/// Information about the context of an exception in analysis driver.
@@ -890,23 +894,20 @@
/// Information about an unlinked unit.
table AnalysisDriverUnlinkedUnit {
/// List of class member names defined by the unit.
- definedClassMemberNames:[string] (id: 3);
+ definedClassMemberNames:[string] (id: 2);
/// List of top-level names defined by the unit.
- definedTopLevelNames:[string] (id: 2);
+ definedTopLevelNames:[string] (id: 1);
/// List of external names referenced by the unit.
referencedNames:[string] (id: 0);
/// List of names which are used in `extends`, `with` or `implements` clauses
/// in the file. Import prefixes and type arguments are not included.
- subtypedNames:[string] (id: 4);
+ subtypedNames:[string] (id: 3);
/// Unlinked information for the unit.
- unit:UnlinkedUnit (id: 1);
-
- /// Unlinked information for the unit.
- unit2:UnlinkedUnit2 (id: 5);
+ unit2:UnlinkedUnit2 (id: 4);
}
/// Information about a single declaration.
@@ -1033,11 +1034,6 @@
templateValues:[string] (id: 1);
}
-/// TODO(scheglov) Remove it.
-table LinkedLibrary {
- placeholder:uint (id: 0);
-}
-
/// Information about a linked AST node.
table LinkedNode {
/// The explicit or inferred return type of a function typed node.
@@ -1205,17 +1201,15 @@
/// Information about a single library in a [LinkedNodeLibrary].
table LinkedNodeUnit {
- isNNBD:bool (id: 4);
+ isNNBD:bool (id: 3);
- isSynthetic:bool (id: 3);
+ isSynthetic:bool (id: 2);
- node:LinkedNode (id: 2);
+ node:LinkedNode (id: 1);
/// If the unit is a part, the URI specified in the `part` directive.
/// Otherwise empty.
- partUriStr:string (id: 5);
-
- tokens:UnlinkedTokens (id: 1);
+ partUriStr:string (id: 4);
/// The absolute URI.
uriStr:string (id: 0);
@@ -1223,46 +1217,8 @@
/// Summary information about a package.
table PackageBundle {
- /// MD5 hash of the non-informative fields of the [PackageBundle] (not
- /// including this one). This can be used to identify when the API of a
- /// package may have changed.
- apiSignature:string (id: 7, deprecated);
-
/// The version 2 of the summary.
- bundle2:LinkedNodeBundle (id: 9);
-
- /// Information about the packages this package depends on, if known.
- dependencies:[PackageDependencyInfo] (id: 8, deprecated);
-
- /// Linked libraries.
- linkedLibraries:[LinkedLibrary] (id: 0, deprecated);
-
- /// The list of URIs of items in [linkedLibraries], e.g. `dart:core` or
- /// `package:foo/bar.dart`.
- linkedLibraryUris:[string] (id: 1, deprecated);
-
- /// Major version of the summary format. See
- /// [PackageBundleAssembler.currentMajorVersion].
- majorVersion:uint (id: 5);
-
- /// Minor version of the summary format. See
- /// [PackageBundleAssembler.currentMinorVersion].
- minorVersion:uint (id: 6);
-
- /// List of MD5 hashes of the files listed in [unlinkedUnitUris]. Each hash
- /// is encoded as a hexadecimal string using lower case letters.
- unlinkedUnitHashes:[string] (id: 4, deprecated);
-
- /// Unlinked information for the compilation units constituting the package.
- unlinkedUnits:[UnlinkedUnit] (id: 2, deprecated);
-
- /// The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
- unlinkedUnitUris:[string] (id: 3, deprecated);
-}
-
-/// TODO(scheglov) Remove it.
-table PackageDependencyInfo {
- placeholder:uint (id: 0);
+ bundle2:LinkedNodeBundle (id: 0);
}
/// Summary information about a top-level type inference error.
@@ -1307,16 +1263,6 @@
kind:LinkedNodeKind (id: 0);
}
-/// TODO(scheglov) Remove it.
-table UnlinkedTokens {
- placeholder:uint (id: 0);
-}
-
-/// TODO(scheglov) Remove it.
-table UnlinkedUnit {
- placeholder:uint (id: 0);
-}
-
/// Unlinked summary information about a compilation unit.
table UnlinkedUnit2 {
/// The MD5 hash signature of the API portion of this unit. It depends on all
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index d6a9a31..a7259a1 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -229,11 +229,11 @@
generated.readAnalysisDriverUnlinkedUnit(buffer);
/// List of class member names defined by the unit.
- @Id(3)
+ @Id(2)
List<String> get definedClassMemberNames;
/// List of top-level names defined by the unit.
- @Id(2)
+ @Id(1)
List<String> get definedTopLevelNames;
/// List of external names referenced by the unit.
@@ -242,15 +242,11 @@
/// List of names which are used in `extends`, `with` or `implements` clauses
/// in the file. Import prefixes and type arguments are not included.
- @Id(4)
+ @Id(3)
List<String> get subtypedNames;
/// Unlinked information for the unit.
- @Id(1)
- UnlinkedUnit get unit;
-
- /// Unlinked information for the unit.
- @Id(5)
+ @Id(4)
UnlinkedUnit2 get unit2;
}
@@ -552,12 +548,6 @@
unit
}
-/// TODO(scheglov) Remove it.
-abstract class LinkedLibrary extends base.SummaryClass {
- @Id(0)
- int get placeholder;
-}
-
/// Information about a linked AST node.
@Variant('kind')
abstract class LinkedNode extends base.SummaryClass {
@@ -1456,6 +1446,9 @@
@VariantId(23, variant: LinkedNodeKind.typeParameter)
LinkedNodeType get typeParameter_defaultType;
+ @VariantId(28, variant: LinkedNodeKind.typeParameter)
+ UnlinkedTokenType get typeParameter_variance;
+
@VariantId(2, variant: LinkedNodeKind.typeParameterList)
List<LinkedNode> get typeParameterList_typeParameters;
@@ -1516,7 +1509,6 @@
abstract class LinkedNodeBundle extends base.SummaryClass {
factory LinkedNodeBundle.fromBuffer(List<int> buffer) =>
generated.readLinkedNodeBundle(buffer);
-
@Id(1)
List<LinkedNodeLibrary> get libraries;
@@ -1770,23 +1762,20 @@
/// Information about a single library in a [LinkedNodeLibrary].
abstract class LinkedNodeUnit extends base.SummaryClass {
- @Id(4)
+ @Id(3)
bool get isNNBD;
- @Id(3)
+ @Id(2)
bool get isSynthetic;
- @Id(2)
+ @Id(1)
LinkedNode get node;
/// If the unit is a part, the URI specified in the `part` directive.
/// Otherwise empty.
- @Id(5)
+ @Id(4)
String get partUriStr;
- @Id(1)
- UnlinkedTokens get tokens;
-
/// The absolute URI.
@Id(0)
String get uriStr;
@@ -1798,66 +1787,9 @@
factory PackageBundle.fromBuffer(List<int> buffer) =>
generated.readPackageBundle(buffer);
- /// MD5 hash of the non-informative fields of the [PackageBundle] (not
- /// including this one). This can be used to identify when the API of a
- /// package may have changed.
- @Id(7)
- @deprecated
- String get apiSignature;
-
/// The version 2 of the summary.
- @Id(9)
+ @Id(0)
LinkedNodeBundle get bundle2;
-
- /// Information about the packages this package depends on, if known.
- @Id(8)
- @informative
- @deprecated
- List<PackageDependencyInfo> get dependencies;
-
- /// Linked libraries.
- @Id(0)
- @deprecated
- List<LinkedLibrary> get linkedLibraries;
-
- /// The list of URIs of items in [linkedLibraries], e.g. `dart:core` or
- /// `package:foo/bar.dart`.
- @Id(1)
- @deprecated
- List<String> get linkedLibraryUris;
-
- /// Major version of the summary format. See
- /// [PackageBundleAssembler.currentMajorVersion].
- @Id(5)
- int get majorVersion;
-
- /// Minor version of the summary format. See
- /// [PackageBundleAssembler.currentMinorVersion].
- @Id(6)
- int get minorVersion;
-
- /// List of MD5 hashes of the files listed in [unlinkedUnitUris]. Each hash
- /// is encoded as a hexadecimal string using lower case letters.
- @Id(4)
- @deprecated
- @informative
- List<String> get unlinkedUnitHashes;
-
- /// Unlinked information for the compilation units constituting the package.
- @Id(2)
- @deprecated
- List<UnlinkedUnit> get unlinkedUnits;
-
- /// The list of URIs of items in [unlinkedUnits], e.g. `dart:core/bool.dart`.
- @Id(3)
- @deprecated
- List<String> get unlinkedUnitUris;
-}
-
-/// TODO(scheglov) Remove it.
-abstract class PackageDependencyInfo extends base.SummaryClass {
- @Id(0)
- int get placeholder;
}
/// Summary information about a top-level type inference error.
@@ -2015,13 +1947,7 @@
int get nameOffset;
}
-/// TODO(scheglov) Remove it.
-abstract class UnlinkedTokens extends base.SummaryClass {
- @Id(0)
- int get placeholder;
-}
-
-/// TODO(scheglov) document
+/// Enum of token types, corresponding to AST token types.
enum UnlinkedTokenType {
NOTHING,
ABSTRACT,
@@ -2164,12 +2090,8 @@
WHILE,
WITH,
YIELD,
-}
-
-/// TODO(scheglov) Remove it.
-abstract class UnlinkedUnit extends base.SummaryClass {
- @Id(0)
- int get placeholder;
+ INOUT,
+ OUT,
}
/// Unlinked summary information about a compilation unit.
diff --git a/pkg/analyzer/lib/src/summary/summarize_elements.dart b/pkg/analyzer/lib/src/summary/summarize_elements.dart
index 95911cd..1228ab8 100644
--- a/pkg/analyzer/lib/src/summary/summarize_elements.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_elements.dart
@@ -3,40 +3,19 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
/**
* Object that gathers information uses it to assemble a new
* [PackageBundleBuilder].
*/
class PackageBundleAssembler {
- /**
- * Value that will be stored in [PackageBundle.majorVersion] for any summaries
- * created by this code. When making a breaking change to the summary format,
- * this value should be incremented by 1 and [currentMinorVersion] should be
- * reset to zero.
- */
- static const int currentMajorVersion = 1;
-
- /**
- * Value that will be stored in [PackageBundle.minorVersion] for any summaries
- * created by this code. When making a non-breaking change to the summary
- * format that clients might need to be aware of (such as adding a kind of
- * data that was previously not summarized), this value should be incremented
- * by 1.
- */
- static const int currentMinorVersion = 1;
-
LinkedNodeBundleBuilder _bundle2;
/**
* Assemble a new [PackageBundleBuilder] using the gathered information.
*/
PackageBundleBuilder assemble() {
- return new PackageBundleBuilder(
- majorVersion: currentMajorVersion,
- minorVersion: currentMinorVersion,
- bundle2: _bundle2);
+ return new PackageBundleBuilder(bundle2: _bundle2);
}
void setBundle2(LinkedNodeBundleBuilder bundle2) {
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index 9cf52b7..f5be007 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -51,11 +51,13 @@
@override
AnalysisContext get context {
if (_analysisContext == null) {
- AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
- _analysisContext = new SdkAnalysisContext(analysisOptions);
- SourceFactory factory = new SourceFactory(
- [new DartUriResolver(this)], null, resourceProvider);
- _analysisContext.sourceFactory = factory;
+ var analysisOptions = AnalysisOptionsImpl();
+ var factory = SourceFactory(
+ [DartUriResolver(this)],
+ null,
+ resourceProvider,
+ );
+ _analysisContext = new SdkAnalysisContext(analysisOptions, factory);
}
return _analysisContext;
}
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 5677f4b9..9774971 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
@@ -93,6 +94,13 @@
return def;
}
+ Token _varianceKeyword(LinkedNode data) {
+ if (data.typeParameter_variance != UnlinkedTokenType.NOTHING) {
+ return _Tokens.fromType(data.typeParameter_variance);
+ }
+ return null;
+ }
+
Element _elementOfComponents(
int rawElementIndex,
LinkedNodeTypeSubstitution substitutionNode,
@@ -1572,13 +1580,15 @@
}
TypeParameter _read_typeParameter(LinkedNode data) {
- var node = astFactory.typeParameter(
- _readDocumentationComment(data),
- _readNodeListLazy(data.annotatedNode_metadata),
- _declaredIdentifier(data),
- _Tokens.EXTENDS,
- _readNodeLazy(data.typeParameter_bound),
- );
+ // TODO (kallentu) : Clean up AstFactoryImpl casting once variance is
+ // added to the interface.
+ var node = (astFactory as AstFactoryImpl).typeParameter2(
+ comment: _readDocumentationComment(data),
+ metadata: _readNodeListLazy(data.annotatedNode_metadata),
+ name: _declaredIdentifier(data),
+ extendsKeyword: _Tokens.EXTENDS,
+ bound: _readNodeLazy(data.typeParameter_bound),
+ varianceKeyword: _varianceKeyword(data));
LazyTypeParameter.setData(node, data);
return node;
}
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index a1cb51c..37aa5f7 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -1354,6 +1354,7 @@
var builder = LinkedNodeBuilder.typeParameter(
typeParameter_bound: node.bound?.accept(this),
typeParameter_defaultType: _writeType(LazyAst.getDefaultType(node)),
+ typeParameter_variance: _getVarianceToken(node),
informativeId: getInformativeId(node),
);
builder.name = node.name.name;
@@ -1678,6 +1679,15 @@
return _linkingContext.writeType(type);
}
+ UnlinkedTokenType _getVarianceToken(TypeParameter parameter) {
+ // TODO (kallentu) : Clean up TypeParameterImpl casting once variance is
+ // added to the interface.
+ var parameterImpl = parameter as TypeParameterImpl;
+ return parameterImpl.varianceKeyword != null
+ ? TokensWriter.astToBinaryTokenType(parameterImpl.varianceKeyword.type)
+ : null;
+ }
+
/// Return `true` if the expression might be successfully serialized.
///
/// This does not mean that the expression is constant, it just means that
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
index fc4908c..54a07fc 100644
--- a/pkg/analyzer/lib/src/summary2/ast_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -5,6 +5,7 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
import 'package:analyzer/src/dart/resolver/resolution_visitor.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/summary2/link.dart';
@@ -15,7 +16,17 @@
final CompilationUnitElement _unitElement;
final Scope _nameScope;
- AstResolver(this._linker, this._unitElement, this._nameScope);
+ /// This field is set if the library is non-nullable by default.
+ FlowAnalysisHelper flowAnalysis;
+
+ AstResolver(this._linker, this._unitElement, this._nameScope) {
+ if (_unitElement.library.isNonNullableByDefault) {
+ flowAnalysis = FlowAnalysisHelper(
+ _unitElement.library.typeSystem,
+ false,
+ );
+ }
+ }
void resolve(
AstNode node,
@@ -56,6 +67,7 @@
nameScope: _nameScope,
propagateTypes: false,
reportConstEvaluationErrors: false,
+ flowAnalysisHelper: flowAnalysis,
);
resolverVisitor.prepareEnclosingDeclarations(
enclosingClassElement: enclosingClassElement,
diff --git a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
index 426c86f..6b19881 100644
--- a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
/// AST visitor that prints tokens into their original positions.
class AstTextPrinter extends ThrowingAstVisitor<void> {
@@ -931,6 +932,9 @@
@override
void visitTypeParameter(TypeParameter node) {
_declaration(node);
+ // TODO (kallentu) : Clean up TypeParameterImpl casting once variance is
+ // added to the interface.
+ _token((node as TypeParameterImpl).varianceKeyword);
node.name?.accept(this);
_token(node.extendsKeyword);
node.bound?.accept(this);
diff --git a/pkg/analyzer/lib/src/summary2/default_types_builder.dart b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
index 18a4fcb3..888b899 100644
--- a/pkg/analyzer/lib/src/summary2/default_types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
@@ -16,7 +16,7 @@
import 'package:kernel/util/graph.dart' show Graph, computeStrongComponents;
class DefaultTypesBuilder {
- final Dart2TypeSystem typeSystem;
+ final TypeSystemImpl typeSystem;
DefaultTypesBuilder(this.typeSystem);
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index 8e91cf7..7ad79b3 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -6,7 +6,6 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -71,7 +70,7 @@
TypeProvider get typeProvider => analysisContext.typeProvider;
- Dart2TypeSystem get typeSystem => analysisContext.typeSystem;
+ TypeSystemImpl get typeSystem => analysisContext.typeSystem;
void link(List<LinkInputLibrary> inputLibraries) {
for (var inputLibrary in inputLibraries) {
@@ -206,15 +205,15 @@
void _createTypeSystem() {
if (typeProvider != null) {
- inheritance = InheritanceManager3(typeSystem);
+ inheritance = InheritanceManager3();
return;
}
var coreLib = elementFactory.libraryOfUri('dart:core');
var asyncLib = elementFactory.libraryOfUri('dart:async');
- analysisContext.typeProvider = TypeProviderImpl(coreLib, asyncLib);
+ elementFactory.createTypeProviders(coreLib, asyncLib);
- inheritance = InheritanceManager3(typeSystem);
+ inheritance = InheritanceManager3();
}
void _performTopLevelInference() {
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index ff48204..c07abb7 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -5,9 +5,10 @@
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary2/core_types.dart';
import 'package:analyzer/src/summary2/lazy_ast.dart';
@@ -16,7 +17,7 @@
import 'package:analyzer/src/summary2/reference.dart';
class LinkedElementFactory {
- final AnalysisContext analysisContext;
+ final AnalysisContextImpl analysisContext;
final AnalysisSession analysisSession;
final Reference rootReference;
final Map<String, LinkedLibraryContext> libraryMap = {};
@@ -61,6 +62,36 @@
return Namespace(exportedNames);
}
+ void createTypeProviders(
+ LibraryElementImpl dartCore,
+ LibraryElementImpl dartAsync,
+ ) {
+ analysisContext.setTypeProviders(
+ legacy: TypeProviderImpl(
+ coreLibrary: dartCore,
+ asyncLibrary: dartAsync,
+ isNonNullableByDefault: false,
+ ),
+ nonNullableByDefault: TypeProviderImpl(
+ coreLibrary: dartCore,
+ asyncLibrary: dartAsync,
+ isNonNullableByDefault: true,
+ ),
+ );
+
+ // During linking we create libraries when typeProvider is not ready.
+ // Update these libraries now, when typeProvider is ready.
+ for (var reference in rootReference.children) {
+ var libraryElement = reference.element as LibraryElementImpl;
+ if (libraryElement != null && libraryElement.typeProvider == null) {
+ _setLibraryTypeSystem(libraryElement);
+ }
+ }
+
+ dartCore.createLoadLibraryFunction(dartCore.typeProvider);
+ dartAsync.createLoadLibraryFunction(dartAsync.typeProvider);
+ }
+
Element elementOfReference(Reference reference) {
if (reference.element != null) {
return reference.element;
@@ -129,6 +160,23 @@
}
}
}
+
+ void _setLibraryTypeSystem(LibraryElementImpl libraryElement) {
+ // During linking we create libraries when typeProvider is not ready.
+ // And if we link dart:core and dart:async, we cannot create it.
+ // We will set typeProvider later, during [createTypeProviders].
+ if (analysisContext.typeProviderLegacy == null) {
+ return;
+ }
+
+ var isNonNullable = libraryElement.isNonNullableByDefault;
+ libraryElement.typeProvider = isNonNullable
+ ? analysisContext.typeProviderNonNullableByDefault
+ : analysisContext.typeProviderLegacy;
+ libraryElement.typeSystem = isNonNullable
+ ? analysisContext.typeSystemNonNullableByDefault
+ : analysisContext.typeSystemLegacy;
+ }
}
class _ElementRequest {
@@ -240,24 +288,18 @@
ElementImpl enclosing, Reference reference) {
if (enclosing is ClassElementImpl) {
enclosing.accessors;
- // Requesting accessors sets elements for accessors and fields.
- assert(reference.element != null);
- return reference.element;
- }
- if (enclosing is CompilationUnitElementImpl) {
+ } else if (enclosing is CompilationUnitElementImpl) {
enclosing.accessors;
- // Requesting accessors sets elements for accessors and variables.
- assert(reference.element != null);
- return reference.element;
- }
- if (enclosing is EnumElementImpl) {
+ } else if (enclosing is EnumElementImpl) {
enclosing.accessors;
- // Requesting accessors sets elements for accessors and variables.
- assert(reference.element != null);
- return reference.element;
+ } else if (enclosing is ExtensionElementImpl) {
+ enclosing.accessors;
+ } else {
+ throw StateError('${enclosing.runtimeType}');
}
- // Only classes and units have accessors.
- throw StateError('${enclosing.runtimeType}');
+ // Requesting accessors sets elements for accessors and variables.
+ assert(reference.element != null);
+ return reference.element;
}
ClassElementImpl _class(
@@ -309,6 +351,7 @@
reference,
definingUnitContext.unit_withDeclarations,
);
+ elementFactory._setLibraryTypeSystem(libraryElement);
var units = <CompilationUnitElementImpl>[];
var unitContainerRef = reference.getChild('@unit');
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 8a60db6..890ad24f 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -5,6 +5,7 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -646,6 +647,12 @@
return node.bound;
}
+ Token getTypeParameterVariance(TypeParameter node) {
+ // TODO (kallentu) : Clean up TypeParameterImpl casting once variance is
+ // added to the interface.
+ return (node as TypeParameterImpl).varianceKeyword;
+ }
+
TypeParameterList getTypeParameters2(AstNode node) {
if (node is ClassDeclaration) {
return node.typeParameters;
diff --git a/pkg/analyzer/lib/src/summary2/tokens_context.dart b/pkg/analyzer/lib/src/summary2/tokens_context.dart
index bae4d3bc..ab8ad17 100644
--- a/pkg/analyzer/lib/src/summary2/tokens_context.dart
+++ b/pkg/analyzer/lib/src/summary2/tokens_context.dart
@@ -147,6 +147,8 @@
return TokenType.INDEX;
case UnlinkedTokenType.INDEX_EQ:
return TokenType.INDEX_EQ;
+ case UnlinkedTokenType.INOUT:
+ return Keyword.INOUT;
case UnlinkedTokenType.INT:
return TokenType.INT;
case UnlinkedTokenType.INTERFACE:
@@ -193,6 +195,8 @@
return TokenType.OPEN_SQUARE_BRACKET;
case UnlinkedTokenType.OPERATOR:
return Keyword.OPERATOR;
+ case UnlinkedTokenType.OUT:
+ return Keyword.OUT;
case UnlinkedTokenType.PART:
return Keyword.PART;
case UnlinkedTokenType.PATCH:
diff --git a/pkg/analyzer/lib/src/summary2/tokens_writer.dart b/pkg/analyzer/lib/src/summary2/tokens_writer.dart
index 859e2ef..3e8bc74 100644
--- a/pkg/analyzer/lib/src/summary2/tokens_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/tokens_writer.dart
@@ -145,6 +145,8 @@
return UnlinkedTokenType.INDEX;
} else if (type == TokenType.INDEX_EQ) {
return UnlinkedTokenType.INDEX_EQ;
+ } else if (type == Keyword.INOUT) {
+ return UnlinkedTokenType.INOUT;
} else if (type == TokenType.INT) {
return UnlinkedTokenType.INT;
} else if (type == Keyword.INTERFACE) {
@@ -191,6 +193,8 @@
return UnlinkedTokenType.OPEN_SQUARE_BRACKET;
} else if (type == Keyword.OPERATOR) {
return UnlinkedTokenType.OPERATOR;
+ } else if (type == Keyword.OUT) {
+ return UnlinkedTokenType.OUT;
} else if (type == Keyword.PART) {
return UnlinkedTokenType.PART;
} else if (type == Keyword.PATCH) {
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index 4914569..4abdf96 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -456,6 +456,7 @@
void _resolveInitializer() {
var astResolver = AstResolver(_walker._linker, _unitElement, _scope);
+ astResolver.flowAnalysis?.topLevelDeclaration_enter(_node, null, null);
astResolver.resolve(_node.initializer, () => _node.initializer);
}
}
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart
index bc7fe97..54ec8cf 100644
--- a/pkg/analyzer/lib/src/summary2/types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -28,7 +28,7 @@
}
class TypesBuilder {
- final Dart2TypeSystem typeSystem;
+ final TypeSystemImpl typeSystem;
TypesBuilder(this.typeSystem);
@@ -174,12 +174,6 @@
LazyAst.setType(node, type);
}
- NullabilitySuffix _noneOrStarSuffix(AstNode node) {
- return _nonNullableEnabled(node)
- ? NullabilitySuffix.none
- : NullabilitySuffix.star;
- }
-
bool _nonNullableEnabled(AstNode node) {
var unit = node.thisOrAncestorOfType<CompilationUnit>();
return unit.featureSet.isEnabled(Feature.non_nullable);
@@ -207,7 +201,7 @@
/// Performs mixins inference in a [ClassDeclaration].
class _MixinInference {
- final Dart2TypeSystem typeSystem;
+ final TypeSystemImpl typeSystem;
final FeatureSet featureSet;
final InterfaceType classType;
@@ -347,7 +341,7 @@
/// Performs mixin inference for all declarations.
class _MixinsInference {
- final Dart2TypeSystem typeSystem;
+ final TypeSystemImpl typeSystem;
_MixinsInference(this.typeSystem);
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 2f88f6f..4be1702 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -35,7 +35,7 @@
/// Given an [expression] and a corresponding [typeSystem] and [typeProvider],
/// gets the known static type of the expression.
DartType getExpressionType(
- Expression expression, TypeSystem typeSystem, TypeProvider typeProvider,
+ Expression expression, TypeSystemImpl typeSystem, TypeProvider typeProvider,
{bool read: false}) {
DartType type;
if (read) {
@@ -118,7 +118,7 @@
/// Checks the body of functions and properties.
class CodeChecker extends RecursiveAstVisitor {
- final Dart2TypeSystem rules;
+ final TypeSystemImpl rules;
final TypeProvider typeProvider;
final InheritanceManager3 inheritance;
final AnalysisErrorListener reporter;
@@ -131,8 +131,8 @@
bool _hasImplicitCasts;
HashSet<ExecutableElement> _covariantPrivateMembers;
- CodeChecker(TypeProvider typeProvider, Dart2TypeSystem rules,
- this.inheritance, AnalysisErrorListener reporter, this._options)
+ CodeChecker(TypeProvider typeProvider, TypeSystemImpl rules, this.inheritance,
+ AnalysisErrorListener reporter, this._options)
: typeProvider = typeProvider,
rules = rules,
reporter = reporter {
@@ -1408,7 +1408,7 @@
/// check overrides between classes and superclasses, interfaces, and mixin
/// applications.
class _OverrideChecker {
- final Dart2TypeSystem rules;
+ final TypeSystemImpl rules;
_OverrideChecker(CodeChecker checker) : rules = checker.rules;
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index de58249..d707a19eb 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -7,66 +7,14 @@
import 'package:analyzer/src/test_utilities/function_ast_visitor.dart';
/// Helper for finding elements declared in the resolved [unit].
-class FindElement {
+class FindElement extends _FindElementBase {
final CompilationUnit unit;
FindElement(this.unit);
+ @override
CompilationUnitElement get unitElement => unit.declaredElement;
- ClassElement class_(String name) {
- for (var class_ in unitElement.types) {
- if (class_.name == name) {
- return class_;
- }
- }
- throw StateError('Not found: $name');
- }
-
- ClassElement classOrMixin(String name) {
- for (var class_ in unitElement.types) {
- if (class_.name == name) {
- return class_;
- }
- }
- for (var mixin in unitElement.mixins) {
- if (mixin.name == name) {
- return mixin;
- }
- }
- throw StateError('Not found: $name');
- }
-
- ConstructorElement constructor(String name, {String of}) {
- assert(name != '');
- ConstructorElement result;
- for (var class_ in unitElement.types) {
- if (of == null || class_.name == of) {
- for (var constructor in class_.constructors) {
- if (constructor.name == name) {
- if (result != null) {
- throw StateError('Not unique: $name');
- }
- result = constructor;
- }
- }
- }
- }
- if (result != null) {
- return result;
- }
- throw StateError('Not found: $name');
- }
-
- ClassElement enum_(String name) {
- for (var enum_ in unitElement.enums) {
- if (enum_.name == name) {
- return enum_;
- }
- }
- throw StateError('Not found: $name');
- }
-
ExportElement export(String targetUri) {
ExportElement result;
@@ -86,63 +34,6 @@
throw StateError('Not found: $targetUri');
}
- ExtensionElement extension_(String name) {
- for (var extension_ in unitElement.extensions) {
- if (extension_.name == name) {
- return extension_;
- }
- }
- throw StateError('Not found: $name');
- }
-
- FieldElement field(String name, {String of}) {
- FieldElement result;
-
- void findIn(List<FieldElement> fields) {
- for (var field in fields) {
- if (field.name == name) {
- if (result != null) {
- throw StateError('Not unique: $name');
- }
- result = field;
- }
- }
- }
-
- for (var enum_ in unitElement.enums) {
- if (of != null && enum_.name != of) {
- continue;
- }
- findIn(enum_.fields);
- }
-
- for (var class_ in unitElement.types) {
- if (of != null && class_.name != of) {
- continue;
- }
- findIn(class_.fields);
- }
-
- for (var mixin in unitElement.mixins) {
- if (of != null && mixin.name != of) {
- continue;
- }
- findIn(mixin.fields);
- }
-
- for (var extension in unitElement.extensions) {
- if (of != null && extension.name != of) {
- continue;
- }
- findIn(extension.fields);
- }
-
- if (result != null) {
- return result;
- }
- throw StateError('Not found: $name');
- }
-
FieldFormalParameterElement fieldFormalParameter(String name) {
return parameter(name) as FieldFormalParameterElement;
}
@@ -156,63 +47,6 @@
throw StateError('Not found: $name');
}
- GenericTypeAliasElement genericTypeAlias(String name) {
- for (var element in unitElement.functionTypeAliases) {
- if (element is GenericTypeAliasElement && element.name == name) {
- return element;
- }
- }
- throw StateError('Not found: $name');
- }
-
- PropertyAccessorElement getter(String name, {String of}) {
- PropertyAccessorElement result;
-
- void findIn(List<PropertyAccessorElement> accessors) {
- for (var accessor in accessors) {
- if (accessor.isGetter && accessor.displayName == name) {
- if (result != null) {
- throw StateError('Not unique: $name');
- }
- result = accessor;
- }
- }
- }
-
- for (var enum_ in unitElement.enums) {
- if (of != null && enum_.name != of) {
- continue;
- }
- findIn(enum_.accessors);
- }
-
- for (var extension_ in unitElement.extensions) {
- if (of != null && extension_.name != of) {
- continue;
- }
- findIn(extension_.accessors);
- }
-
- for (var class_ in unitElement.types) {
- if (of != null && class_.name != of) {
- continue;
- }
- findIn(class_.accessors);
- }
-
- for (var mixin in unitElement.mixins) {
- if (of != null && mixin.name != of) {
- continue;
- }
- findIn(mixin.accessors);
- }
-
- if (result != null) {
- return result;
- }
- throw StateError('Not found: $name');
- }
-
ImportElement import(String targetUri) {
ImportElement importElement;
@@ -285,56 +119,6 @@
return result;
}
- MethodElement method(String name, {String of}) {
- MethodElement result;
-
- void findIn(List<MethodElement> methods) {
- for (var method in methods) {
- if (method.name == name) {
- if (result != null) {
- throw StateError('Not unique: $name');
- }
- result = method;
- }
- }
- }
-
- for (var extension_ in unitElement.extensions) {
- if (of != null && extension_.name != of) {
- continue;
- }
- findIn(extension_.methods);
- }
-
- for (var class_ in unitElement.types) {
- if (of != null && class_.name != of) {
- continue;
- }
- findIn(class_.methods);
- }
-
- for (var mixin in unitElement.mixins) {
- if (of != null && mixin.name != of) {
- continue;
- }
- findIn(mixin.methods);
- }
-
- if (result != null) {
- return result;
- }
- throw StateError('Not found: $name');
- }
-
- ClassElement mixin(String name) {
- for (var mixin in unitElement.mixins) {
- if (mixin.name == name) {
- return mixin;
- }
- }
- throw StateError('Not found: $name');
- }
-
ParameterElement parameter(String name) {
ParameterElement result;
@@ -405,6 +189,277 @@
throw StateError('Not found: $name');
}
+ TypeParameterElement typeParameter(String name) {
+ TypeParameterElement result;
+
+ void findIn(List<TypeParameterElement> typeParameters) {
+ for (var typeParameter in typeParameters) {
+ if (typeParameter.name == name) {
+ if (result != null) {
+ throw StateError('Not unique: $name');
+ }
+ result = typeParameter;
+ }
+ }
+ }
+
+ for (var type in unitElement.functionTypeAliases) {
+ findIn(type.typeParameters);
+ if (type is GenericTypeAliasElement) {
+ findIn(type.function.typeParameters);
+ }
+ }
+
+ for (var class_ in unitElement.types) {
+ findIn(class_.typeParameters);
+ }
+
+ for (var mixin in unitElement.mixins) {
+ findIn(mixin.typeParameters);
+ }
+
+ if (result != null) {
+ return result;
+ }
+ throw StateError('Not found: $name');
+ }
+}
+
+/// Helper for searching imported elements.
+class ImportFindElement extends _FindElementBase {
+ final ImportElement import;
+
+ ImportFindElement(this.import);
+
+ LibraryElement get importedLibrary => import.importedLibrary;
+
+ PrefixElement get prefix => import.prefix;
+
+ CompilationUnitElement get unitElement {
+ return importedLibrary.definingCompilationUnit;
+ }
+}
+
+abstract class _FindElementBase {
+ CompilationUnitElement get unitElement;
+
+ ClassElement class_(String name) {
+ for (var class_ in unitElement.types) {
+ if (class_.name == name) {
+ return class_;
+ }
+ }
+ throw StateError('Not found: $name');
+ }
+
+ ClassElement classOrMixin(String name) {
+ for (var class_ in unitElement.types) {
+ if (class_.name == name) {
+ return class_;
+ }
+ }
+ for (var mixin in unitElement.mixins) {
+ if (mixin.name == name) {
+ return mixin;
+ }
+ }
+ throw StateError('Not found: $name');
+ }
+
+ ConstructorElement constructor(String name, {String of}) {
+ assert(name != '');
+ ConstructorElement result;
+ for (var class_ in unitElement.types) {
+ if (of == null || class_.name == of) {
+ for (var constructor in class_.constructors) {
+ if (constructor.name == name) {
+ if (result != null) {
+ throw StateError('Not unique: $name');
+ }
+ result = constructor;
+ }
+ }
+ }
+ }
+ if (result != null) {
+ return result;
+ }
+ throw StateError('Not found: $name');
+ }
+
+ ClassElement enum_(String name) {
+ for (var enum_ in unitElement.enums) {
+ if (enum_.name == name) {
+ return enum_;
+ }
+ }
+ throw StateError('Not found: $name');
+ }
+
+ ExtensionElement extension_(String name) {
+ for (var extension_ in unitElement.extensions) {
+ if (extension_.name == name) {
+ return extension_;
+ }
+ }
+ throw StateError('Not found: $name');
+ }
+
+ FieldElement field(String name, {String of}) {
+ FieldElement result;
+
+ void findIn(List<FieldElement> fields) {
+ for (var field in fields) {
+ if (field.name == name) {
+ if (result != null) {
+ throw StateError('Not unique: $name');
+ }
+ result = field;
+ }
+ }
+ }
+
+ for (var enum_ in unitElement.enums) {
+ if (of != null && enum_.name != of) {
+ continue;
+ }
+ findIn(enum_.fields);
+ }
+
+ for (var class_ in unitElement.types) {
+ if (of != null && class_.name != of) {
+ continue;
+ }
+ findIn(class_.fields);
+ }
+
+ for (var mixin in unitElement.mixins) {
+ if (of != null && mixin.name != of) {
+ continue;
+ }
+ findIn(mixin.fields);
+ }
+
+ for (var extension in unitElement.extensions) {
+ if (of != null && extension.name != of) {
+ continue;
+ }
+ findIn(extension.fields);
+ }
+
+ if (result != null) {
+ return result;
+ }
+ throw StateError('Not found: $name');
+ }
+
+ FunctionTypeAliasElement functionTypeAlias(String name) {
+ for (var element in unitElement.functionTypeAliases) {
+ if (element is GenericTypeAliasElement && element.name == name) {
+ return element;
+ }
+ }
+ throw StateError('Not found: $name');
+ }
+
+ PropertyAccessorElement getter(String name, {String of}) {
+ PropertyAccessorElement result;
+
+ void findIn(List<PropertyAccessorElement> accessors) {
+ for (var accessor in accessors) {
+ if (accessor.isGetter && accessor.displayName == name) {
+ if (result != null) {
+ throw StateError('Not unique: $name');
+ }
+ result = accessor;
+ }
+ }
+ }
+
+ for (var enum_ in unitElement.enums) {
+ if (of != null && enum_.name != of) {
+ continue;
+ }
+ findIn(enum_.accessors);
+ }
+
+ for (var extension_ in unitElement.extensions) {
+ if (of != null && extension_.name != of) {
+ continue;
+ }
+ findIn(extension_.accessors);
+ }
+
+ for (var class_ in unitElement.types) {
+ if (of != null && class_.name != of) {
+ continue;
+ }
+ findIn(class_.accessors);
+ }
+
+ for (var mixin in unitElement.mixins) {
+ if (of != null && mixin.name != of) {
+ continue;
+ }
+ findIn(mixin.accessors);
+ }
+
+ if (result != null) {
+ return result;
+ }
+ throw StateError('Not found: $name');
+ }
+
+ MethodElement method(String name, {String of}) {
+ MethodElement result;
+
+ void findIn(List<MethodElement> methods) {
+ for (var method in methods) {
+ if (method.name == name) {
+ if (result != null) {
+ throw StateError('Not unique: $name');
+ }
+ result = method;
+ }
+ }
+ }
+
+ for (var extension_ in unitElement.extensions) {
+ if (of != null && extension_.name != of) {
+ continue;
+ }
+ findIn(extension_.methods);
+ }
+
+ for (var class_ in unitElement.types) {
+ if (of != null && class_.name != of) {
+ continue;
+ }
+ findIn(class_.methods);
+ }
+
+ for (var mixin in unitElement.mixins) {
+ if (of != null && mixin.name != of) {
+ continue;
+ }
+ findIn(mixin.methods);
+ }
+
+ if (result != null) {
+ return result;
+ }
+ throw StateError('Not found: $name');
+ }
+
+ ClassElement mixin(String name) {
+ for (var mixin in unitElement.mixins) {
+ if (mixin.name == name) {
+ return mixin;
+ }
+ }
+ throw StateError('Not found: $name');
+ }
+
PropertyAccessorElement setter(String name, {String of}) {
PropertyAccessorElement result;
@@ -472,111 +527,7 @@
throw StateError('Not found: $name');
}
- TypeParameterElement typeParameter(String name) {
- TypeParameterElement result;
-
- void findIn(List<TypeParameterElement> typeParameters) {
- for (var typeParameter in typeParameters) {
- if (typeParameter.name == name) {
- if (result != null) {
- throw StateError('Not unique: $name');
- }
- result = typeParameter;
- }
- }
- }
-
- for (var type in unitElement.functionTypeAliases) {
- findIn(type.typeParameters);
- if (type is GenericTypeAliasElement) {
- findIn(type.function.typeParameters);
- }
- }
-
- for (var class_ in unitElement.types) {
- findIn(class_.typeParameters);
- }
-
- for (var mixin in unitElement.mixins) {
- findIn(mixin.typeParameters);
- }
-
- if (result != null) {
- return result;
- }
- throw StateError('Not found: $name');
- }
-
ConstructorElement unnamedConstructor(String name) {
return class_(name).unnamedConstructor;
}
}
-
-/// Helper for searching imported elements.
-class ImportFindElement {
- final ImportElement import;
-
- ImportFindElement(this.import);
-
- CompilationUnitElement get definingUnit {
- return importedLibrary.definingCompilationUnit;
- }
-
- LibraryElement get importedLibrary => import.importedLibrary;
-
- PrefixElement get prefix => import.prefix;
-
- ClassElement class_(String name) {
- for (var class_ in definingUnit.types) {
- if (class_.name == name) {
- return class_;
- }
- }
- throw StateError('Not found: $name');
- }
-
- ExtensionElement extension_(String name) {
- for (var element in definingUnit.extensions) {
- if (element.name == name) {
- return element;
- }
- }
- throw StateError('Not found: $name');
- }
-
- GenericTypeAliasElement functionTypeAlias(String name) {
- for (var element in definingUnit.functionTypeAliases) {
- if (element.name == name) {
- return element;
- }
- }
- throw StateError('Not found: $name');
- }
-
- FunctionElement topFunction(String name) {
- for (var function in definingUnit.functions) {
- if (function.name == name) {
- return function;
- }
- }
- throw StateError('Not found: $name');
- }
-
- PropertyAccessorElement topGetter(String name) {
- for (var accessor in definingUnit.accessors) {
- if (accessor.name == name && accessor.isGetter) {
- return accessor;
- }
- }
- throw StateError('Not found: $name');
- }
-
- TopLevelVariableElement topVar(String name) {
- for (var variable in definingUnit.topLevelVariables) {
- if (variable.name == name) {
- return variable;
- }
- }
- throw StateError('Not found: $name');
- }
-}
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index 87a5af6..b862a58 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -247,6 +247,10 @@
return _node(search, (n) => n is SuperExpression);
}
+ SuperConstructorInvocation superConstructorInvocation(String search) {
+ return _node(search, (n) => n is SuperConstructorInvocation);
+ }
+
SwitchStatement switchStatement(String search) {
return _node(search, (n) => n is SwitchStatement);
}
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 2ae5993..eb7bc31 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -5,6 +5,7 @@
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart' show PackageBundle;
@@ -869,6 +870,8 @@
final Map<String, String> uriMap = {};
+ final AnalysisOptionsImpl _analysisOptions;
+
/**
* The [AnalysisContextImpl] which is used for all of the sources.
*/
@@ -887,8 +890,9 @@
MockSdk({
bool generateSummaryFiles: false,
@required this.resourceProvider,
+ AnalysisOptionsImpl analysisOptions,
List<MockSdkLibrary> additionalLibraries = const [],
- }) {
+ }) : _analysisOptions = analysisOptions ?? AnalysisOptionsImpl() {
for (MockSdkLibrary library in _LIBRARIES) {
var convertedLibrary = library._toProvider(resourceProvider);
sdkLibraries.add(convertedLibrary);
@@ -943,9 +947,8 @@
@override
AnalysisContextImpl get context {
if (_analysisContext == null) {
- _analysisContext = new _SdkAnalysisContext(this);
- SourceFactory factory = new SourceFactory([new DartUriResolver(this)]);
- _analysisContext.sourceFactory = factory;
+ var factory = SourceFactory([DartUriResolver(this)]);
+ _analysisContext = SdkAnalysisContext(_analysisOptions, factory);
}
return _analysisContext;
}
@@ -1096,12 +1099,3 @@
);
}
}
-
-/**
- * An [AnalysisContextImpl] that only contains sources for a Dart SDK.
- */
-class _SdkAnalysisContext extends AnalysisContextImpl {
- final DartSdk sdk;
-
- _SdkAnalysisContext(this.sdk);
-}
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index 5209ea3..ea670ae 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -101,7 +101,7 @@
// Search in each root.
for (String root in [
- _workspace.bin,
+ ..._workspace.binPaths,
_workspace.genfiles,
_workspace.readonly,
_workspace.root
@@ -181,10 +181,11 @@
*/
final String readonly;
- /**
- * The absolute path to the `bazel-bin` folder.
- */
- final String bin;
+ /// The absolute paths to all `bazel-bin` folders.
+ ///
+ /// In practice, there is usually one "bin" path, and sometimes there are two,
+ /// on distributed build systems. It is very rare to have more than two.
+ final List<String> binPaths;
/**
* The absolute path to the `bazel-genfiles` folder.
@@ -192,7 +193,10 @@
final String genfiles;
BazelWorkspace._(
- this.provider, this.root, this.readonly, this.bin, this.genfiles);
+ this.provider, this.root, this.readonly, this.binPaths, this.genfiles);
+
+ @override
+ bool get isBazel => true;
@override
Map<String, List<Folder>> get packageMap => null;
@@ -236,7 +240,7 @@
}
}
// bin
- if (bin != null) {
+ for (String bin in binPaths) {
File file = provider.getFile(context.join(bin, relative));
if (file.exists) {
return file;
@@ -291,18 +295,20 @@
// In some distributed build environments, BUILD files are not preserved.
// We can still look for a ".packages" file in order to determine a
// package's root. A ".packages" file found in [folder]'s sister path
- // under [bin] denotes a Dart package.
+ // under a "bin" path among [binPaths] denotes a Dart package.
//
// For example, if this BazelWorkspace's [root] is
- // "/build/work/abc123/workspace" with a [bin] folder of
+ // "/build/work/abc123/workspace" with two "bin" folders,
+ // "/build/work/abc123/workspace/blaze-out/host/bin/" and
// "/build/work/abc123/workspace/blaze-out/k8-opt/bin/", and [folder]
// is at "/build/work/abc123/workspace/foo/bar", then we must look for a
- // file ending in ".packages" in the folder
+ // file ending in ".packages" in the folders
+ // "/build/work/abc123/workspace/blaze-out/host/bin/foo/bar" and
// "/build/work/abc123/workspace/blaze-out/k8-opt/bin/foo/bar".
// [folder]'s path, relative to [root]. For example, "foo/bar".
String relative = context.relative(folder.path, from: root);
- if (bin != null) {
+ for (String bin in binPaths) {
Folder binChild = provider.getFolder(context.join(bin, relative));
if (binChild.exists &&
binChild.getChildren().any((c) => c.path.endsWith('.packages'))) {
@@ -355,11 +361,11 @@
String readonlyRoot =
context.join(readonlyFolder.path, folder.shortName);
if (provider.getFolder(readonlyRoot).exists) {
- String binPath = _findBinFolderPath(folder);
+ List<String> binPaths = _findBinFolderPaths(folder);
String symlinkPrefix =
- _findSymlinkPrefix(provider, root, binPath: binPath);
- binPath ??= context.join(root, '$symlinkPrefix-bin');
- return new BazelWorkspace._(provider, root, readonlyRoot, binPath,
+ _findSymlinkPrefix(provider, root, binPaths: binPaths);
+ binPaths ??= [context.join(root, '$symlinkPrefix-bin')];
+ return new BazelWorkspace._(provider, root, readonlyRoot, binPaths,
context.join(root, '$symlinkPrefix-genfiles'));
}
}
@@ -367,23 +373,23 @@
if (_firstExistingFolder(parent, ['blaze-out', 'bazel-out']) != null) {
// Found the "out" folder; must be a bazel workspace.
String root = parent.path;
- String binPath = _findBinFolderPath(parent);
+ List<String> binPaths = _findBinFolderPaths(parent);
String symlinkPrefix =
- _findSymlinkPrefix(provider, root, binPath: binPath);
- binPath ??= context.join(root, '$symlinkPrefix-bin');
+ _findSymlinkPrefix(provider, root, binPaths: binPaths);
+ binPaths ??= [context.join(root, '$symlinkPrefix-bin')];
return new BazelWorkspace._(provider, root, null /* readonly */,
- binPath, context.join(root, '$symlinkPrefix-genfiles'));
+ binPaths, context.join(root, '$symlinkPrefix-genfiles'));
}
// Found the WORKSPACE file, must be a non-git workspace.
if (folder.getChildAssumingFile(_WORKSPACE).exists) {
String root = folder.path;
- String binPath = _findBinFolderPath(folder);
+ List<String> binPaths = _findBinFolderPaths(folder);
String symlinkPrefix =
- _findSymlinkPrefix(provider, root, binPath: binPath);
- binPath ??= context.join(root, '$symlinkPrefix-bin');
+ _findSymlinkPrefix(provider, root, binPaths: binPaths);
+ binPaths ??= [context.join(root, '$symlinkPrefix-bin')];
return new BazelWorkspace._(provider, root, null /* readonly */,
- binPath, context.join(root, '$symlinkPrefix-genfiles'));
+ binPaths, context.join(root, '$symlinkPrefix-genfiles'));
}
// Go up the folder.
@@ -391,11 +397,6 @@
}
}
- /// Return the first folder within [root], chosen from [names], which exists.
- static Folder _firstExistingFolder(Folder root, List<String> names) => names
- .map((name) => root.getChildAssumingFolder(name))
- .firstWhere((folder) => folder.exists, orElse: () => null);
-
/// Find the "bin" folder path, by searching for it.
///
/// Depending on the environment we're working in (source code tree, build
@@ -403,15 +404,15 @@
/// folder may be available at a symlink found at `$root/blaze-bin/` or
/// `$root/bazel-bin/`. If that symlink is not available, then we must search
/// the immediate folders found in `$root/blaze-out/` and `$root/bazel-out/`
- /// for a folder named "bin".
+ /// for folders named "bin".
///
/// If no "bin" folder is found in any of those locations, `null` is returned.
- static String _findBinFolderPath(Folder root) {
- // This is a symlink to the real bin folder, but it is the easiest and
- // cheapest to search for.
+ static List<String> _findBinFolderPaths(Folder root) {
+ // This is a symlink to the real, singular "bin" folder, but it is the
+ // easiest and cheapest to search for.
Folder symlink = _firstExistingFolder(root, ['blaze-bin', 'bazel-bin']);
if (symlink != null) {
- return symlink.path;
+ return [symlink.path];
}
Folder out = _firstExistingFolder(root, ['blaze-out', 'bazel-out']);
@@ -419,28 +420,32 @@
return null;
}
+ List<String> binPaths = [];
for (var child in out.getChildren().whereType<Folder>()) {
// Children are folders denoting architectures and build flags, like
// 'k8-opt', 'k8-fastbuild', perhaps 'host'.
Folder possibleBin = child.getChildAssumingFolder('bin');
if (possibleBin.exists) {
- return possibleBin.path;
+ binPaths.add(possibleBin.path);
}
}
- return null;
+ return binPaths.isEmpty ? null : binPaths;
}
/// Return the symlink prefix, _X_, for folders `X-bin` or `X-genfiles`.
///
- /// If the workspace's "bin" folder was already found, the symlink prefix is
- /// determined from [binPath]. Otherwise it is determined by probing the
- /// internal `blaze-genfiles` and `bazel-genfiles`. Make a default assumption
- /// according to [defaultSymlinkPrefix] if neither of the folders exists.
+ /// If the workspace's "bin" folders were already found, the symlink prefix is
+ /// determined from one of the [binPaths]. Otherwise it is determined by
+ /// probing the internal `blaze-genfiles` and `bazel-genfiles`. Make a default
+ /// assumption according to [defaultSymlinkPrefix] if neither of the folders
+ /// exists.
static String _findSymlinkPrefix(ResourceProvider provider, String root,
- {String binPath}) {
+ {List<String> binPaths}) {
path.Context context = provider.pathContext;
- if (binPath != null) {
- return context.basename(binPath).startsWith('bazel') ? 'bazel' : 'blaze';
+ if (binPaths != null && binPaths.isNotEmpty) {
+ return context.basename(binPaths.first).startsWith('bazel')
+ ? 'bazel'
+ : 'blaze';
}
if (provider.getFolder(context.join(root, 'blaze-genfiles')).exists) {
return 'blaze';
@@ -451,6 +456,11 @@
// Couldn't find it. Make a default assumption.
return defaultSymlinkPrefix;
}
+
+ /// Return the first folder within [root], chosen from [names], which exists.
+ static Folder _firstExistingFolder(Folder root, List<String> names) => names
+ .map((name) => root.getChildAssumingFolder(name))
+ .firstWhere((folder) => folder.exists, orElse: () => null);
}
/**
diff --git a/pkg/analyzer/lib/src/workspace/workspace.dart b/pkg/analyzer/lib/src/workspace/workspace.dart
index 7b74cb5..9b70903 100644
--- a/pkg/analyzer/lib/src/workspace/workspace.dart
+++ b/pkg/analyzer/lib/src/workspace/workspace.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/workspace/bazel.dart';
/**
* Abstract superclass of classes that provide information about the workspace
@@ -19,6 +20,11 @@
bool get hasFlutterDependency => packageMap?.containsKey('flutter') ?? false;
/**
+ * Return true iff this [Workspace] is a [BazelWorkspace].
+ */
+ bool get isBazel => false;
+
+ /**
* Return a (possibly null) map of package sources.
*/
Map<String, List<Folder>> get packageMap;
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index d5cf46c..0f460595 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -16,21 +16,6 @@
import 'test_support.dart';
class CompileTimeErrorCodeTestBase extends DriverResolutionTest {
- disabled_test_conflictingGenericInterfaces_hierarchyLoop_infinite() async {
- // There is an interface conflict here due to a loop in the class
- // hierarchy leading to an infinite set of implemented types; this loop
- // shouldn't cause non-termination.
-
- // TODO(paulberry): this test is currently disabled due to non-termination
- // bugs elsewhere in the analyzer.
- await assertErrorsInCode('''
-class A<T> implements B<List<T>> {}
-class B<T> implements A<List<T>> {}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 0, 0),
- ]);
- }
-
@failingTest
test_accessPrivateEnumField() async {
await assertErrorsInCode(r'''
@@ -4365,7 +4350,7 @@
test_typeAliasCannotReferenceItself_generic() async {
List<ExpectedError> expectedErrors = [
error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 37),
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 101, 1),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 101, 1),
];
await assertErrorsInCode(r'''
typedef F = void Function(List<G> l);
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index 8f4902a7..c28ee46 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -384,6 +384,7 @@
// abstract class A { int operator[](int index); }
//
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
MethodElement operator =
ElementFactory.methodElement("[]", intType, [intType]);
classA.methods = <MethodElement>[operator];
@@ -391,23 +392,26 @@
// class B implements A {}
//
ClassElementImpl classB = ElementFactory.classElement2("B");
- classB.interfaces = <InterfaceType>[interfaceType(classA)];
+ _encloseElement(classB);
+ classB.interfaces = <InterfaceType>[interfaceTypeStar(classA)];
//
// class C extends Object with B {}
//
ClassElementImpl classC = ElementFactory.classElement2("C");
- classC.mixins = <InterfaceType>[interfaceType(classB)];
+ _encloseElement(classC);
+ classC.mixins = <InterfaceType>[interfaceTypeStar(classB)];
//
// class D extends C {}
//
ClassElementImpl classD =
- ElementFactory.classElement("D", interfaceType(classC));
+ ElementFactory.classElement("D", interfaceTypeStar(classC));
+ _encloseElement(classA);
//
// D a;
// a[i];
//
SimpleIdentifier array = AstTestFactory.identifier3("a");
- array.staticType = interfaceType(classD);
+ array.staticType = interfaceTypeStar(classD);
IndexExpression expression =
AstTestFactory.indexExpression(array, AstTestFactory.identifier3("i"));
expect(_resolveIndexExpression(expression), same(operator));
@@ -492,8 +496,8 @@
// break loop;
// }
String label = "loop";
- LabelElementImpl labelElement = new LabelElementImpl.forNode(
- AstTestFactory.identifier3(label), false, false);
+ LabelElementImpl labelElement =
+ new LabelElementImpl(label, -1, false, false);
BreakStatement breakStatement = AstTestFactory.breakStatement2(label);
Expression condition = AstTestFactory.booleanLiteral(true);
WhileStatement whileStatement =
@@ -575,6 +579,7 @@
test_visitConstructorName_named() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
String constructorName = "a";
ConstructorElement constructor =
ElementFactory.constructorElement2(classA, constructorName);
@@ -588,6 +593,7 @@
test_visitConstructorName_unnamed() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
String constructorName;
ConstructorElement constructor =
ElementFactory.constructorElement2(classA, constructorName);
@@ -604,8 +610,8 @@
// continue loop;
// }
String label = "loop";
- LabelElementImpl labelElement = new LabelElementImpl.forNode(
- AstTestFactory.identifier3(label), false, false);
+ LabelElementImpl labelElement =
+ new LabelElementImpl(label, -1, false, false);
ContinueStatement continueStatement =
AstTestFactory.continueStatement(label);
Expression condition = AstTestFactory.booleanLiteral(true);
@@ -758,7 +764,8 @@
ConstructorElementImpl constructor =
ElementFactory.constructorElement2(classA, constructorName);
String parameterName = "a";
- ParameterElement parameter = ElementFactory.namedParameter(parameterName);
+ ParameterElement parameter =
+ ElementFactory.namedParameter2(parameterName, _typeProvider.intType);
constructor.parameters = <ParameterElement>[parameter];
classA.constructors = <ConstructorElement>[constructor];
ConstructorName name = AstTestFactory.constructorName(
@@ -848,15 +855,16 @@
test_visitPrefixedIdentifier_nonDynamic() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
String getterName = "b";
PropertyAccessorElement getter =
ElementFactory.getterElement(getterName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[getter];
SimpleIdentifier target = AstTestFactory.identifier3("a");
VariableElementImpl variable = ElementFactory.localVariableElement(target);
- variable.type = interfaceType(classA);
+ variable.type = interfaceTypeStar(classA);
target.staticElement = variable;
- target.staticType = interfaceType(classA);
+ target.staticType = interfaceTypeStar(classA);
PrefixedIdentifier identifier = AstTestFactory.identifier(
target, AstTestFactory.identifier3(getterName));
_resolveNode(identifier);
@@ -867,6 +875,7 @@
test_visitPrefixedIdentifier_staticClassMember_getter() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
// set accessors
String propName = "b";
PropertyAccessorElement getter =
@@ -877,7 +886,7 @@
// prepare "A.b"
SimpleIdentifier target = AstTestFactory.identifier3("A");
target.staticElement = classA;
- target.staticType = interfaceType(classA);
+ target.staticType = interfaceTypeStar(classA);
PrefixedIdentifier identifier =
AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
// resolve
@@ -889,6 +898,7 @@
test_visitPrefixedIdentifier_staticClassMember_method() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
// set methods
String propName = "m";
var method = ElementFactory.methodElement("m", _typeProvider.intType);
@@ -897,7 +907,7 @@
// prepare "A.m"
SimpleIdentifier target = AstTestFactory.identifier3("A");
target.staticElement = classA;
- target.staticType = interfaceType(classA);
+ target.staticType = interfaceTypeStar(classA);
PrefixedIdentifier identifier =
AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
AstTestFactory.expressionStatement(identifier);
@@ -910,6 +920,7 @@
test_visitPrefixedIdentifier_staticClassMember_setter() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
// set accessors
String propName = "b";
PropertyAccessorElement getter =
@@ -920,7 +931,7 @@
// prepare "A.b = null"
SimpleIdentifier target = AstTestFactory.identifier3("A");
target.staticElement = classA;
- target.staticType = interfaceType(classA);
+ target.staticType = interfaceTypeStar(classA);
PrefixedIdentifier identifier =
AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
AstTestFactory.assignmentExpression(
@@ -945,12 +956,13 @@
test_visitPropertyAccess_getter_identifier() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
String getterName = "b";
PropertyAccessorElement getter =
ElementFactory.getterElement(getterName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[getter];
SimpleIdentifier target = AstTestFactory.identifier3("a");
- target.staticType = interfaceType(classA);
+ target.staticType = interfaceTypeStar(classA);
PropertyAccess access = AstTestFactory.propertyAccess2(target, getterName);
_resolveNode(access);
expect(access.propertyName.staticElement, same(getter));
@@ -967,13 +979,14 @@
// }
//
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
String getterName = "b";
PropertyAccessorElement getter =
ElementFactory.getterElement(getterName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[getter];
SuperExpression target = AstTestFactory.superExpression();
- target.staticType =
- interfaceType(ElementFactory.classElement("B", interfaceType(classA)));
+ target.staticType = interfaceTypeStar(
+ ElementFactory.classElement("B", interfaceTypeStar(classA)));
PropertyAccess access = AstTestFactory.propertyAccess2(target, getterName);
AstTestFactory.methodDeclaration2(
null,
@@ -990,12 +1003,13 @@
test_visitPropertyAccess_setter_this() async {
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
String setterName = "b";
PropertyAccessorElement setter =
ElementFactory.setterElement(setterName, false, _typeProvider.intType);
classA.accessors = <PropertyAccessorElement>[setter];
ThisExpression target = AstTestFactory.thisExpression();
- target.staticType = interfaceType(classA);
+ target.staticType = interfaceTypeStar(classA);
PropertyAccess access = AstTestFactory.propertyAccess2(target, setterName);
AstTestFactory.assignmentExpression(
access, TokenType.EQ, AstTestFactory.integer(0));
@@ -1031,6 +1045,7 @@
test_visitSimpleIdentifier_lexicalScope_field_setter() async {
InterfaceType intType = _typeProvider.intType;
ClassElementImpl classA = ElementFactory.classElement2("A");
+ _encloseElement(classA);
String fieldName = "a";
FieldElement field =
ElementFactory.fieldElement(fieldName, false, false, false, intType);
@@ -1047,11 +1062,13 @@
test_visitSuperConstructorInvocation() async {
ClassElementImpl superclass = ElementFactory.classElement2("A");
+ _encloseElement(superclass);
ConstructorElementImpl superConstructor =
ElementFactory.constructorElement2(superclass, null);
superclass.constructors = <ConstructorElement>[superConstructor];
ClassElementImpl subclass =
- ElementFactory.classElement("B", interfaceType(superclass));
+ ElementFactory.classElement("B", interfaceTypeStar(superclass));
+ _encloseElement(subclass);
ConstructorElementImpl subConstructor =
ElementFactory.constructorElement2(subclass, null);
subclass.constructors = <ConstructorElement>[subConstructor];
@@ -1067,6 +1084,7 @@
test_visitSuperConstructorInvocation_namedParameter() async {
ClassElementImpl superclass = ElementFactory.classElement2("A");
+ _encloseElement(superclass);
ConstructorElementImpl superConstructor =
ElementFactory.constructorElement2(superclass, null);
String parameterName = "p";
@@ -1074,7 +1092,8 @@
superConstructor.parameters = <ParameterElement>[parameter];
superclass.constructors = <ConstructorElement>[superConstructor];
ClassElementImpl subclass =
- ElementFactory.classElement("B", interfaceType(superclass));
+ ElementFactory.classElement("B", interfaceTypeStar(superclass));
+ _encloseElement(subclass);
ConstructorElementImpl subConstructor =
ElementFactory.constructorElement2(subclass, null);
subclass.constructors = <ConstructorElement>[subConstructor];
@@ -1103,12 +1122,17 @@
AnalysisContext context = TestAnalysisContext();
_typeProvider = context.typeProvider;
- var inheritance = new InheritanceManager3(context.typeSystem);
Source source = new FileSource(getFile("/test.dart"));
CompilationUnitElementImpl unit = new CompilationUnitElementImpl();
unit.librarySource = unit.source = source;
- _definingLibrary = ElementFactory.library(context, "test");
+ _definingLibrary =
+ ElementFactory.library(context, "test", isNonNullableByDefault: false);
_definingLibrary.definingCompilationUnit = unit;
+
+ _definingLibrary.typeProvider = context.typeProvider;
+ _definingLibrary.typeSystem = context.typeSystem;
+ var inheritance = new InheritanceManager3();
+
_visitor = new ResolverVisitor(
inheritance, _definingLibrary, source, _typeProvider, _listener,
featureSet: FeatureSet.forTesting(),
@@ -1116,6 +1140,12 @@
_resolver = _visitor.elementResolver;
}
+ void _encloseElement(ElementImpl element) {
+ if (element is ClassElement) {
+ element.enclosingElement = _definingLibrary;
+ }
+ }
+
/**
* Return the element associated with the label of [statement] after the
* resolver has resolved it. [labelElement] is the label element to be
diff --git a/pkg/analyzer/test/generated/elements_types_mixin.dart b/pkg/analyzer/test/generated/elements_types_mixin.dart
index cff157f..08de4eb 100644
--- a/pkg/analyzer/test/generated/elements_types_mixin.dart
+++ b/pkg/analyzer/test/generated/elements_types_mixin.dart
@@ -6,6 +6,7 @@
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -13,7 +14,54 @@
import 'package:meta/meta.dart';
mixin ElementsTypesMixin {
- DynamicTypeImpl get dynamicType => typeProvider.dynamicType;
+ InterfaceType get doubleNone {
+ var element = typeProvider.doubleType.element;
+ return interfaceTypeNone(element);
+ }
+
+ InterfaceType get doubleQuestion {
+ var element = typeProvider.doubleType.element;
+ return interfaceTypeQuestion(element);
+ }
+
+ InterfaceType get doubleStar {
+ var element = typeProvider.doubleType.element;
+ return interfaceTypeStar(element);
+ }
+
+ DartType get dynamicNone => DynamicTypeImpl.instance;
+
+ DynamicTypeImpl get dynamicType => DynamicTypeImpl.instance;
+
+ InterfaceType get functionNone {
+ var element = typeProvider.functionType.element;
+ return interfaceTypeNone(element);
+ }
+
+ InterfaceType get functionQuestion {
+ var element = typeProvider.functionType.element;
+ return interfaceTypeQuestion(element);
+ }
+
+ InterfaceType get functionStar {
+ var element = typeProvider.functionType.element;
+ return interfaceTypeStar(element);
+ }
+
+ InterfaceType get intNone {
+ var element = typeProvider.intType.element;
+ return interfaceTypeNone(element);
+ }
+
+ InterfaceType get intQuestion {
+ var element = typeProvider.intType.element;
+ return interfaceTypeQuestion(element);
+ }
+
+ InterfaceType get intStar {
+ var element = typeProvider.intType.element;
+ return interfaceTypeStar(element);
+ }
NeverTypeImpl get neverNone => NeverTypeImpl.instance;
@@ -21,8 +69,70 @@
NeverTypeImpl get neverStar => NeverTypeImpl.instanceLegacy;
+ InterfaceType get nullNone {
+ var element = typeProvider.nullType.element;
+ return interfaceTypeNone(element);
+ }
+
+ InterfaceType get nullQuestion {
+ var element = typeProvider.nullType.element;
+ return interfaceTypeQuestion(element);
+ }
+
+ InterfaceType get nullStar {
+ var element = typeProvider.nullType.element;
+ return interfaceTypeStar(element);
+ }
+
+ InterfaceType get numNone {
+ var element = typeProvider.numType.element;
+ return interfaceTypeNone(element);
+ }
+
+ InterfaceType get numQuestion {
+ var element = typeProvider.numType.element;
+ return interfaceTypeQuestion(element);
+ }
+
+ InterfaceType get numStar {
+ var element = typeProvider.numType.element;
+ return interfaceTypeStar(element);
+ }
+
+ InterfaceType get objectNone {
+ var element = typeProvider.objectType.element;
+ return interfaceTypeNone(element);
+ }
+
+ InterfaceType get objectQuestion {
+ var element = typeProvider.objectType.element;
+ return interfaceTypeQuestion(element);
+ }
+
+ InterfaceType get objectStar {
+ var element = typeProvider.objectType.element;
+ return interfaceTypeStar(element);
+ }
+
+ InterfaceType get stringNone {
+ var element = typeProvider.stringType.element;
+ return interfaceTypeNone(element);
+ }
+
+ InterfaceType get stringQuestion {
+ var element = typeProvider.stringType.element;
+ return interfaceTypeQuestion(element);
+ }
+
+ InterfaceType get stringStar {
+ var element = typeProvider.stringType.element;
+ return interfaceTypeStar(element);
+ }
+
TypeProvider get typeProvider;
+ VoidType get voidNone => typeProvider.voidType;
+
ClassElementImpl class_({
@required String name,
bool isAbstract = false,
@@ -41,6 +151,33 @@
return element;
}
+ InterfaceType comparableNone(DartType type) {
+ var coreLibrary = typeProvider.intElement.library;
+ var element = coreLibrary.getType('Comparable');
+ return element.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ InterfaceType comparableQuestion(DartType type) {
+ var coreLibrary = typeProvider.intElement.library;
+ var element = coreLibrary.getType('Comparable');
+ return element.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.question,
+ );
+ }
+
+ InterfaceType comparableStar(DartType type) {
+ var coreLibrary = typeProvider.intElement.library;
+ var element = coreLibrary.getType('Comparable');
+ return element.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
+ }
+
FunctionTypeImpl functionType({
@required List<TypeParameterElement> typeFormals,
@required List<ParameterElement> parameters,
@@ -105,9 +242,51 @@
);
}
+ InterfaceTypeImpl futureNone(DartType type) {
+ return typeProvider.futureElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ InterfaceTypeImpl futureOrNone(DartType type) {
+ return typeProvider.futureOrElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ InterfaceTypeImpl futureOrQuestion(DartType type) {
+ return typeProvider.futureOrElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.question,
+ );
+ }
+
+ InterfaceTypeImpl futureOrStar(DartType type) {
+ return typeProvider.futureOrElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
+ }
+
+ InterfaceTypeImpl futureQuestion(DartType type) {
+ return typeProvider.futureElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.question,
+ );
+ }
+
+ InterfaceTypeImpl futureStar(DartType type) {
+ return typeProvider.futureElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
+ }
+
DartType futureType(DartType T) {
var futureElement = typeProvider.futureElement;
- return interfaceType(futureElement, typeArguments: [T]);
+ return interfaceTypeStar(futureElement, typeArguments: [T]);
}
GenericFunctionTypeElementImpl genericFunctionType({
@@ -135,15 +314,86 @@
InterfaceType interfaceType(
ClassElement element, {
List<DartType> typeArguments = const [],
- NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+ @required NullabilitySuffix nullabilitySuffix,
}) {
- return InterfaceTypeImpl.explicit(
- element,
- typeArguments,
+ return element.instantiate(
+ typeArguments: typeArguments,
nullabilitySuffix: nullabilitySuffix,
);
}
+ InterfaceType interfaceTypeNone(
+ ClassElement element, {
+ List<DartType> typeArguments = const [],
+ }) {
+ return element.instantiate(
+ typeArguments: typeArguments,
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ InterfaceType interfaceTypeQuestion(
+ ClassElement element, {
+ List<DartType> typeArguments = const [],
+ }) {
+ return element.instantiate(
+ typeArguments: typeArguments,
+ nullabilitySuffix: NullabilitySuffix.question,
+ );
+ }
+
+ InterfaceType interfaceTypeStar(
+ ClassElement element, {
+ List<DartType> typeArguments = const [],
+ }) {
+ return element.instantiate(
+ typeArguments: typeArguments,
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
+ }
+
+ InterfaceType iterableNone(DartType type) {
+ return typeProvider.iterableElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ InterfaceType iterableQuestion(DartType type) {
+ return typeProvider.iterableElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.question,
+ );
+ }
+
+ InterfaceType iterableStar(DartType type) {
+ return typeProvider.iterableElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
+ }
+
+ InterfaceType listNone(DartType type) {
+ return typeProvider.listElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+ }
+
+ InterfaceType listQuestion(DartType type) {
+ return typeProvider.listElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.question,
+ );
+ }
+
+ InterfaceType listStar(DartType type) {
+ return typeProvider.listElement.instantiate(
+ typeArguments: [type],
+ nullabilitySuffix: NullabilitySuffix.star,
+ );
+ }
+
MethodElement method(
String name,
DartType returnType, {
@@ -158,6 +408,20 @@
..typeParameters = typeFormals;
}
+ MixinElementImpl mixin_({
+ @required String name,
+ List<TypeParameterElement> typeParameters = const [],
+ List<InterfaceType> constraints,
+ List<InterfaceType> interfaces = const [],
+ }) {
+ var element = MixinElementImpl(name, 0);
+ element.typeParameters = typeParameters;
+ element.superclassConstraints = constraints ?? [typeProvider.objectType];
+ element.interfaces = interfaces;
+ element.constructors = const <ConstructorElement>[];
+ return element;
+ }
+
ParameterElement namedParameter({
@required String name,
@required DartType type,
@@ -185,6 +449,14 @@
return parameter;
}
+ TypeParameterMember promoteTypeParameter(
+ TypeParameterElement element,
+ DartType bound,
+ ) {
+ assert(element is! TypeParameterMember);
+ return TypeParameterMember(element, null, bound);
+ }
+
ParameterElement requiredParameter({String name, @required DartType type}) {
var parameter = ParameterElementImpl(name ?? '', 0);
parameter.parameterKind = ParameterKind.REQUIRED;
diff --git a/pkg/analyzer/test/generated/error_suppression_test.dart b/pkg/analyzer/test/generated/error_suppression_test.dart
index d3e8852..003c3b0 100644
--- a/pkg/analyzer/test/generated/error_suppression_test.dart
+++ b/pkg/analyzer/test/generated/error_suppression_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/test_utilities/package_mixin.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../src/dart/resolution/driver_resolution.dart';
@@ -14,7 +15,7 @@
}
@reflectiveTest
-class ErrorSuppressionTest extends DriverResolutionTest {
+class ErrorSuppressionTest extends DriverResolutionTest with PackageMixin {
String get ignoredCode => 'const_initialized_with_non_constant_value';
test_error_code_mismatch() async {
@@ -98,6 +99,18 @@
]);
}
+ test_ignore_uniqueName() async {
+ addMetaPackage();
+ await assertNoErrorsInCode('''
+import 'package:meta/meta.dart';
+
+int f({@Required('x') int a}) => 0;
+
+// ignore: missing_required_param_with_details
+int x = f();
+''');
+ }
+
test_ignore_upper_case() async {
await assertNoErrorsInCode('''
int x = ''; // ignore: INVALID_ASSIGNMENT
diff --git a/pkg/analyzer/test/generated/invalid_code_test.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
index c1531fd..c3f499c 100644
--- a/pkg/analyzer/test/generated/invalid_code_test.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -56,7 +56,7 @@
await _assertCanBeAnalyzed(r'''
typedef F = void Function(bool, int a(double b));
''');
- var alias = findElement.genericTypeAlias('F');
+ var alias = findElement.functionTypeAlias('F');
assertElementTypeString(
alias.instantiate(
typeArguments: const [],
@@ -126,7 +126,7 @@
await _assertCanBeAnalyzed(r'''
typedef void F(int a, this.b);
''');
- var alias = findElement.genericTypeAlias('F');
+ var alias = findElement.functionTypeAlias('F');
assertElementTypeString(
alias.instantiate(
typeArguments: const [],
@@ -202,6 +202,38 @@
await _assertCanBeAnalyzed(r'c(=k(<)>');
}
+ test_fuzz_38506() async {
+ // https://github.com/dart-lang/sdk/issues/38506
+ // We have only one LibraryElement to get resolved annotations.
+ // Leave annotations node of other LibraryDirective(s) unresolved.
+ await _assertCanBeAnalyzed(r'''
+library c;
+@foo
+library c;
+''');
+ }
+
+ test_fuzz_38953() async {
+ // When we enter a directive, we should stop using the element walker
+ // of the unit, just like when we enter a method body. Even though using
+ // interpolation is not allowed in any directives.
+ await _assertCanBeAnalyzed(r'''
+import '${[for(var v = 0;;) v]}';
+export '${[for(var v = 0;;) v]}';
+part '${[for(var v = 0;;) v]}';
+''');
+ }
+
+ test_fuzz_38878() async {
+ // We should not attempt to resolve `super` in annotations.
+ await _assertCanBeAnalyzed(r'''
+class C {
+ @A(super.f())
+ f(int x) {}
+}
+''');
+ }
+
test_genericFunction_asTypeArgument_ofUnresolvedClass() async {
await _assertCanBeAnalyzed(r'''
C<int Function()> c;
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 207f917..4d04bc4 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -2598,8 +2598,7 @@
parser.parseCompilationUnit2();
listener.assertErrors(usingFastaParser
? [
- expectedError(
- CompileTimeErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 2),
+ expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 2),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 13, 1),
@@ -2617,8 +2616,7 @@
parser.parseCompilationUnit2();
listener.assertErrors(usingFastaParser
? [
- expectedError(
- CompileTimeErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 6),
+ expectedError(ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 6),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 17, 1),
expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 17, 1)
@@ -2637,7 +2635,7 @@
listener.assertErrors(usingFastaParser
? [
expectedError(
- CompileTimeErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 13),
+ ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR, 11, 13),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 24, 1),
expectedError(ParserErrorCode.MISSING_METHOD_PARAMETERS, 10, 1),
expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 24, 1)
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 58fc71e..7400a44 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -137,8 +137,7 @@
void test_creation_nonEmpty() {
AnalysisContext context = TestAnalysisContext();
String importedTypeName = "A";
- ClassElement importedType = new ClassElementImpl.forNode(
- AstTestFactory.identifier3(importedTypeName));
+ ClassElement importedType = new ClassElementImpl(importedTypeName, -1);
LibraryElement importedLibrary = createTestLibrary(context, "imported");
(importedLibrary.definingCompilationUnit as CompilationUnitElementImpl)
.types = <ClassElement>[importedType];
@@ -224,8 +223,7 @@
void test_creation_nonEmpty() {
AnalysisContext context = TestAnalysisContext();
String importedTypeName = "A";
- ClassElement importedType = new ClassElementImpl.forNode(
- AstTestFactory.identifier3(importedTypeName));
+ ClassElement importedType = new ClassElementImpl(importedTypeName, -1);
LibraryElement importedLibrary = createTestLibrary(context, "imported");
(importedLibrary.definingCompilationUnit as CompilationUnitElementImpl)
.types = <ClassElement>[importedType];
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index 8978aa5..d3b2718 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -25,7 +25,6 @@
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
@@ -356,7 +355,7 @@
/**
* Return a type system that can be used to test the results of resolution.
*/
- TypeSystem get typeSystem {
+ TypeSystemImpl get typeSystem {
if (analysisResults.isEmpty) {
fail('typeSystem called before computing an analysis result.');
}
@@ -518,8 +517,7 @@
sourcedCompilationUnits = new List<CompilationUnitElement>(count);
for (int i = 0; i < count; i++) {
String typeName = typeNames[i];
- ClassElementImpl type =
- new ClassElementImpl.forNode(AstTestFactory.identifier3(typeName));
+ ClassElementImpl type = new ClassElementImpl(typeName, -1);
String fileName = "$typeName.dart";
CompilationUnitElementImpl compilationUnit =
new CompilationUnitElementImpl();
@@ -534,10 +532,12 @@
compilationUnit.librarySource =
compilationUnit.source = definingCompilationUnitSource;
var featureSet = context.analysisOptions.contextFeatures;
- LibraryElementImpl library = new LibraryElementImpl.forNode(
+ LibraryElementImpl library = new LibraryElementImpl(
context,
driver?.currentSession,
- AstTestFactory.libraryIdentifier2([libraryName]),
+ libraryName,
+ -1,
+ 0,
featureSet.isEnabled(Feature.non_nullable));
library.definingCompilationUnit = compilationUnit;
library.parts = sourcedCompilationUnits;
@@ -583,8 +583,10 @@
if (experiments != null) {
(options as AnalysisOptionsImpl).enabledExperiments = experiments;
}
- DartSdk sdk = new MockSdk(resourceProvider: resourceProvider)
- ..context.analysisOptions = options;
+ DartSdk sdk = new MockSdk(
+ resourceProvider: resourceProvider,
+ analysisOptions: options,
+ );
List<UriResolver> resolvers = <UriResolver>[
new DartUriResolver(sdk),
@@ -812,7 +814,7 @@
final Source source;
final CompilationUnit unit;
final List<AnalysisError> errors;
- final TypeSystem typeSystem;
+ final TypeSystemImpl typeSystem;
TestAnalysisResult(this.source, this.unit, this.errors, this.typeSystem);
}
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index 9a2e72b..501a1ef 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -1064,7 +1064,7 @@
verifyTestResolved();
expect(
- findElement.genericTypeAlias('F').metadata,
+ findElement.functionTypeAlias('F').metadata,
hasLength(1),
);
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 3e27401..2c4562d 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -220,7 +220,7 @@
/**
* The type system used to analyze the test cases.
*/
- TypeSystem get _typeSystem => _visitor.typeSystem;
+ TypeSystemImpl get _typeSystem => _visitor.typeSystem;
void fail_visitFunctionExpressionInvocation() {
_fail("Not yet tested");
@@ -251,21 +251,22 @@
InterfaceType intType = _typeProvider.intType;
DartType dynamicType = _typeProvider.dynamicType;
InterfaceType derivedIntType =
- interfaceType(derivedClass, typeArguments: [intType]);
+ interfaceTypeStar(derivedClass, typeArguments: [intType]);
// flatten(Derived) = dynamic
InterfaceType derivedDynamicType =
- interfaceType(derivedClass, typeArguments: [dynamicType]);
+ interfaceTypeStar(derivedClass, typeArguments: [dynamicType]);
expect(_flatten(derivedDynamicType), dynamicType);
// flatten(Derived<int>) = int
expect(_flatten(derivedIntType), intType);
// flatten(Derived<Derived>) = Derived
expect(
- _flatten(
- interfaceType(derivedClass, typeArguments: [derivedDynamicType])),
+ _flatten(interfaceTypeStar(derivedClass,
+ typeArguments: [derivedDynamicType])),
derivedDynamicType);
// flatten(Derived<Derived<int>>) = Derived<int>
expect(
- _flatten(interfaceType(derivedClass, typeArguments: [derivedIntType])),
+ _flatten(
+ interfaceTypeStar(derivedClass, typeArguments: [derivedIntType])),
derivedIntType);
}
@@ -274,13 +275,13 @@
// class B extends A
ClassElementImpl classA = ElementFactory.classElement2('A', []);
ClassElementImpl classB = ElementFactory.classElement2('B', []);
- classA.supertype = interfaceType(classB);
- classB.supertype = interfaceType(classA);
+ classA.supertype = interfaceTypeStar(classB);
+ classB.supertype = interfaceTypeStar(classA);
// flatten(A) = A and flatten(B) = B, since neither class contains Future
// in its class hierarchy. Even though there is a loop in the class
// hierarchy, flatten() should terminate.
- expect(_flatten(interfaceType(classA)), interfaceType(classA));
- expect(_flatten(interfaceType(classB)), interfaceType(classB));
+ expect(_flatten(interfaceTypeStar(classA)), interfaceTypeStar(classA));
+ expect(_flatten(interfaceTypeStar(classB)), interfaceTypeStar(classB));
}
void test_flatten_related_derived_types() {
@@ -293,21 +294,21 @@
futureType(typeParameterType(derivedClass.typeParameters[0]));
// class A extends Derived<int> implements Derived<num> { ... }
ClassElementImpl classA = ElementFactory.classElement(
- 'A', interfaceType(derivedClass, typeArguments: [intType]));
+ 'A', interfaceTypeStar(derivedClass, typeArguments: [intType]));
classA.interfaces = <InterfaceType>[
- interfaceType(derivedClass, typeArguments: [numType]),
+ interfaceTypeStar(derivedClass, typeArguments: [numType]),
];
// class B extends Future<num> implements Future<int> { ... }
ClassElementImpl classB = ElementFactory.classElement(
- 'B', interfaceType(derivedClass, typeArguments: [numType]));
+ 'B', interfaceTypeStar(derivedClass, typeArguments: [numType]));
classB.interfaces = <InterfaceType>[
- interfaceType(derivedClass, typeArguments: [intType])
+ interfaceTypeStar(derivedClass, typeArguments: [intType])
];
// flatten(A) = flatten(B) = int, since int is more specific than num.
// The code in flatten() that inhibits infinite recursion shouldn't be
// fooled by the fact that Derived appears twice in the type hierarchy.
- expect(_flatten(interfaceType(classA)), intType);
- expect(_flatten(interfaceType(classB)), intType);
+ expect(_flatten(interfaceTypeStar(classA)), intType);
+ expect(_flatten(interfaceTypeStar(classB)), intType);
}
void test_flatten_related_types() {
@@ -322,8 +323,8 @@
ElementFactory.classElement('B', _typeProvider.futureType2(numType));
classB.interfaces = <InterfaceType>[_typeProvider.futureType2(intType)];
// flatten(A) = flatten(B) = int, since int is more specific than num.
- expect(_flatten(interfaceType(classA)), intType);
- expect(_flatten(interfaceType(classB)), intType);
+ expect(_flatten(interfaceTypeStar(classA)), intType);
+ expect(_flatten(interfaceTypeStar(classB)), intType);
}
void test_flatten_simple() {
@@ -362,8 +363,8 @@
classB.interfaces = <InterfaceType>[_typeProvider.futureType2(intType)];
// flatten(A) = A and flatten(B) = B, since neither string nor int is more
// specific than the other.
- expect(_flatten(interfaceType(classA)), interfaceType(classA));
- expect(_flatten(interfaceType(classB)), interfaceType(classB));
+ expect(_flatten(interfaceTypeStar(classA)), interfaceTypeStar(classA));
+ expect(_flatten(interfaceTypeStar(classB)), interfaceTypeStar(classB));
}
void test_visitAdjacentStrings() {
@@ -378,11 +379,11 @@
// class A { ... this as B ... }
// class B extends A {}
ClassElement superclass = ElementFactory.classElement2("A");
- InterfaceType superclassType = interfaceType(superclass);
+ InterfaceType superclassType = interfaceTypeStar(superclass);
ClassElement subclass = ElementFactory.classElement("B", superclassType);
Expression node = AstTestFactory.asExpression(
AstTestFactory.thisExpression(), AstTestFactory.typeName(subclass));
- expect(_analyze(node, superclassType), interfaceType(subclass));
+ expect(_analyze(node, superclassType), interfaceTypeStar(subclass));
_listener.assertNoErrors();
}
@@ -509,7 +510,7 @@
// }
// (a as A) * 2.0
ClassElementImpl classA = ElementFactory.classElement2("A");
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
MethodElement operator =
ElementFactory.methodElement("*", typeA, [_typeProvider.doubleType]);
classA.methods = <MethodElement>[operator];
@@ -872,7 +873,7 @@
AstTestFactory.typeName(classElement),
[AstTestFactory.identifier3(constructorName)]);
node.staticElement = constructor;
- expect(_analyze(node), interfaceType(classElement));
+ expect(_analyze(node), interfaceTypeStar(classElement));
_listener.assertNoErrors();
}
@@ -885,15 +886,15 @@
elementC.constructors = <ConstructorElement>[constructor];
TypeName typeName =
AstTestFactory.typeName(elementC, [AstTestFactory.typeName(elementI)]);
- typeName.type =
- interfaceType(elementC, typeArguments: [interfaceType(elementI)]);
+ typeName.type = interfaceTypeStar(elementC,
+ typeArguments: [interfaceTypeStar(elementI)]);
InstanceCreationExpression node =
AstTestFactory.instanceCreationExpression2(null, typeName);
node.staticElement = constructor;
InterfaceType type = _analyze(node) as InterfaceType;
List<DartType> typeArgs = type.typeArguments;
expect(typeArgs.length, 1);
- expect(typeArgs[0], interfaceType(elementI));
+ expect(typeArgs[0], interfaceTypeStar(elementI));
_listener.assertNoErrors();
}
@@ -907,7 +908,7 @@
AstTestFactory.instanceCreationExpression2(
null, AstTestFactory.typeName(classElement));
node.staticElement = constructor;
- expect(_analyze(node), interfaceType(classElement));
+ expect(_analyze(node), interfaceTypeStar(classElement));
_listener.assertNoErrors();
}
@@ -1179,9 +1180,10 @@
void test_visitSuperExpression() {
// super
- InterfaceType superType = interfaceType(ElementFactory.classElement2("A"));
+ InterfaceType superType =
+ interfaceTypeStar(ElementFactory.classElement2("A"));
InterfaceType thisType =
- interfaceType(ElementFactory.classElement("B", superType));
+ interfaceTypeStar(ElementFactory.classElement("B", superType));
Expression node = AstTestFactory.superExpression();
expect(_analyze(node, thisType), same(thisType));
_listener.assertNoErrors();
@@ -1194,8 +1196,8 @@
void test_visitThisExpression() {
// this
- InterfaceType thisType = interfaceType(ElementFactory.classElement(
- "B", interfaceType(ElementFactory.classElement2("A"))));
+ InterfaceType thisType = interfaceTypeStar(ElementFactory.classElement(
+ "B", interfaceTypeStar(ElementFactory.classElement2("A"))));
Expression node = AstTestFactory.thisExpression();
expect(_analyze(node, thisType), same(thisType));
_listener.assertNoErrors();
@@ -1312,15 +1314,15 @@
*/
StaticTypeAnalyzer _createAnalyzer() {
var context = TestAnalysisContext();
- var inheritance = new InheritanceManager3(context.typeSystem);
+ var inheritance = new InheritanceManager3();
Source source = new FileSource(getFile("/lib.dart"));
CompilationUnitElementImpl definingCompilationUnit =
new CompilationUnitElementImpl();
definingCompilationUnit.librarySource =
definingCompilationUnit.source = source;
var featureSet = FeatureSet.forTesting();
- LibraryElementImpl definingLibrary = new LibraryElementImpl.forNode(
- context, null, null, featureSet.isEnabled(Feature.non_nullable));
+ LibraryElementImpl definingLibrary = new LibraryElementImpl(
+ context, null, null, -1, 0, featureSet.isEnabled(Feature.non_nullable));
definingLibrary.definingCompilationUnit = definingCompilationUnit;
_typeProvider = context.typeProvider;
_visitor = new ResolverVisitor(
@@ -1367,17 +1369,18 @@
FormalParameterList parameters, FunctionBody body) {
List<ParameterElement> parameterElements = new List<ParameterElement>();
for (FormalParameter parameter in parameters.parameters) {
+ var nameNode = parameter.identifier;
ParameterElementImpl element =
- new ParameterElementImpl.forNode(parameter.identifier);
+ new ParameterElementImpl(nameNode.name, nameNode.offset);
// ignore: deprecated_member_use_from_same_package
element.parameterKind = parameter.kind;
element.type = _typeProvider.dynamicType;
- parameter.identifier.staticElement = element;
+ nameNode.staticElement = element;
parameterElements.add(element);
}
FunctionExpression node =
AstTestFactory.functionExpression2(parameters, body);
- FunctionElementImpl element = new FunctionElementImpl.forNode(null);
+ FunctionElementImpl element = new FunctionElementImpl('', -1);
element.parameters = parameterElements;
(node as FunctionExpressionImpl).declaredElement = element;
return node;
@@ -1434,7 +1437,7 @@
SimpleIdentifier identifier = parameter.identifier;
Element element = identifier.staticElement;
if (element is! ParameterElement) {
- element = new ParameterElementImpl.forNode(identifier);
+ element = new ParameterElementImpl(identifier.name, identifier.offset);
identifier.staticElement = element;
}
(element as ParameterElementImpl).type = type;
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index 033dc53..4a2ffd8 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -927,7 +927,7 @@
}
Future<Future<int>> g() => null;
''', [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 54, 3),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 54, 3),
]);
}
@@ -938,7 +938,7 @@
return 5;
}
''', [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 57, 1),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 57, 1),
]);
}
@@ -949,7 +949,7 @@
}
''', [
error(StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, 0, 3),
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 25, 1),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 25, 1),
]);
}
@@ -957,7 +957,7 @@
await assertErrorsInCode('''
int f() => '0';
''', [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 11, 3),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 11, 3),
]);
}
@@ -965,7 +965,7 @@
await assertErrorsInCode('''
int get g => '0';
''', [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 13, 3),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 13, 3),
]);
}
@@ -979,7 +979,7 @@
}
''', [
error(HintCode.UNUSED_ELEMENT, 33, 1),
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 40, 3),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 40, 3),
]);
}
@@ -989,7 +989,7 @@
int f() => '0';
}
''', [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 23, 3),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_METHOD, 23, 3),
]);
}
@@ -997,7 +997,7 @@
await assertErrorsInCode('''
int f() { return '0'; }
''', [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 17, 3),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 17, 3),
]);
}
@@ -1005,7 +1005,7 @@
await assertErrorsInCode('''
int get g { return '0'; }
''', [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 19, 3),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 19, 3),
]);
}
@@ -1019,7 +1019,7 @@
}
''', [
error(HintCode.UNUSED_ELEMENT, 33, 1),
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 46, 3),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 46, 3),
]);
}
@@ -1029,7 +1029,7 @@
int f() { return '0'; }
}
''', [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 29, 3),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_METHOD, 29, 3),
]);
}
@@ -1059,7 +1059,7 @@
test_returnOfInvalidType_void() async {
await assertErrorsInCode("void f() { return 42; }", [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 18, 2),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 18, 2),
]);
}
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 3b2b23d..1aa5efc 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -5462,7 +5462,7 @@
test_returnOfInvalidType_object_void() async {
await assertErrorsInCode(
"Object f() { void voidFn() => null; return voidFn(); }", [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 43, 8),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 43, 8),
]);
}
@@ -5497,7 +5497,7 @@
}
set g(int x) => 42;
''', [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 41, 4),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 41, 4),
]);
}
diff --git a/pkg/analyzer/test/generated/test_analysis_context.dart b/pkg/analyzer/test/generated/test_analysis_context.dart
index 29f75ef..e42b7ee 100644
--- a/pkg/analyzer/test/generated/test_analysis_context.dart
+++ b/pkg/analyzer/test/generated/test_analysis_context.dart
@@ -4,6 +4,7 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/resolver.dart';
@@ -16,7 +17,7 @@
AnalysisOptions _analysisOptions;
TypeProviderImpl _typeProvider;
- TypeSystem _typeSystem;
+ TypeSystemImpl _typeSystem;
TestAnalysisContext({FeatureSet featureSet}) {
_analysisOptions = AnalysisOptionsImpl()
@@ -30,15 +31,24 @@
);
_typeProvider = TypeProviderImpl(
- sdkElements.coreLibrary,
- sdkElements.asyncLibrary,
+ coreLibrary: sdkElements.coreLibrary,
+ asyncLibrary: sdkElements.asyncLibrary,
+ isNonNullableByDefault: false,
);
if (_analysisOptions.contextFeatures.isEnabled(Feature.non_nullable)) {
- _typeProvider = _typeProvider.withNullability(NullabilitySuffix.none);
+ _typeProvider = _typeProvider.asNonNullableByDefault;
}
- _typeSystem = Dart2TypeSystem(typeProvider);
+ _typeSystem = TypeSystemImpl(
+ implicitCasts: true,
+ isNonNullableByDefault: false,
+ strictInference: false,
+ typeProvider: typeProvider,
+ );
+
+ _setLibraryTypeSystem(sdkElements.coreLibrary);
+ _setLibraryTypeSystem(sdkElements.asyncLibrary);
}
@override
@@ -48,9 +58,14 @@
TypeProvider get typeProvider => _typeProvider;
@override
- TypeSystem get typeSystem => _typeSystem;
+ TypeSystemImpl get typeSystem => _typeSystem;
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+
+ void _setLibraryTypeSystem(LibraryElementImpl libraryElement) {
+ libraryElement.typeProvider = _typeProvider;
+ libraryElement.typeSystem = _typeSystem;
+ }
}
class _MockSource implements Source {
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index ee8f7eb..5bc1e83 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -20,7 +20,6 @@
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart'
show NonExistingSource, UriKind;
-import 'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' show toUri;
import 'package:test/test.dart';
@@ -43,7 +42,7 @@
abstract class AbstractTypeSystemTest with ElementsTypesMixin {
TypeProvider typeProvider;
- Dart2TypeSystem typeSystem;
+ TypeSystemImpl typeSystem;
InterfaceType get doubleType => typeProvider.doubleType;
@@ -65,22 +64,22 @@
DartType futureOrType(DartType T) {
var futureOrElement = typeProvider.futureOrElement;
- return interfaceType(futureOrElement, typeArguments: [T]);
+ return interfaceTypeStar(futureOrElement, typeArguments: [T]);
}
DartType futureType(DartType T) {
var futureElement = typeProvider.futureElement;
- return interfaceType(futureElement, typeArguments: [T]);
+ return interfaceTypeStar(futureElement, typeArguments: [T]);
}
DartType iterableType(DartType T) {
var iterableElement = typeProvider.iterableElement;
- return interfaceType(iterableElement, typeArguments: [T]);
+ return interfaceTypeStar(iterableElement, typeArguments: [T]);
}
DartType listType(DartType T) {
var listElement = typeProvider.listElement;
- return interfaceType(listElement, typeArguments: [T]);
+ return interfaceTypeStar(listElement, typeArguments: [T]);
}
void setUp() {
@@ -93,6 +92,10 @@
typeProvider = typeProvider;
typeSystem = typeSystem;
}
+
+ String _typeString(TypeImpl type) {
+ return type.toString(withNullability: true);
+ }
}
@reflectiveTest
@@ -106,7 +109,7 @@
doubleType,
numType,
stringType,
- interfaceType(A),
+ interfaceTypeStar(A),
neverStar,
];
@@ -124,7 +127,7 @@
);
_checkIsStrictAssignableTo(
- interfaceType(B),
+ interfaceTypeStar(B),
functionTypeStar(
parameters: [
requiredParameter(type: intType),
@@ -136,17 +139,17 @@
void test_isAssignableTo_classes() {
var classTop = class_(name: 'A');
- var classLeft = class_(name: 'B', superType: interfaceType(classTop));
- var classRight = class_(name: 'C', superType: interfaceType(classTop));
+ var classLeft = class_(name: 'B', superType: interfaceTypeStar(classTop));
+ var classRight = class_(name: 'C', superType: interfaceTypeStar(classTop));
var classBottom = class_(
name: 'D',
- superType: interfaceType(classLeft),
- interfaces: [interfaceType(classRight)],
+ superType: interfaceTypeStar(classLeft),
+ interfaces: [interfaceTypeStar(classRight)],
);
- var top = interfaceType(classTop);
- var left = interfaceType(classLeft);
- var right = interfaceType(classRight);
- var bottom = interfaceType(classBottom);
+ var top = interfaceTypeStar(classTop);
+ var left = interfaceTypeStar(classLeft);
+ var right = interfaceTypeStar(classRight);
+ var bottom = interfaceTypeStar(classBottom);
_checkLattice(top, left, right, bottom);
}
@@ -163,7 +166,7 @@
List<DartType> unrelated = <DartType>[
intType,
stringType,
- interfaceType(A),
+ interfaceTypeStar(A),
];
_checkGroups(doubleType,
@@ -179,7 +182,7 @@
doubleType,
numType,
stringType,
- interfaceType(A),
+ interfaceTypeStar(A),
neverStar,
];
_checkGroups(dynamicType, interassignable: interassignable);
@@ -194,7 +197,7 @@
name: 'M',
typeParameters: [MT],
interfaces: [
- interfaceType(
+ interfaceTypeStar(
L,
typeArguments: [
typeParameterTypeStar(MT),
@@ -203,10 +206,10 @@
],
);
- var top = interfaceType(L, typeArguments: [dynamicType]);
- var left = interfaceType(M, typeArguments: [dynamicType]);
- var right = interfaceType(L, typeArguments: [intType]);
- var bottom = interfaceType(M, typeArguments: [intType]);
+ var top = interfaceTypeStar(L, typeArguments: [dynamicType]);
+ var left = interfaceTypeStar(M, typeArguments: [dynamicType]);
+ var right = interfaceTypeStar(L, typeArguments: [intType]);
+ var bottom = interfaceTypeStar(M, typeArguments: [intType]);
_checkCrossLattice(top, left, right, bottom);
}
@@ -223,7 +226,7 @@
List<DartType> unrelated = <DartType>[
doubleType,
stringType,
- interfaceType(A),
+ interfaceTypeStar(A),
];
_checkGroups(intType,
@@ -324,7 +327,7 @@
];
List<DartType> unrelated = <DartType>[
stringType,
- interfaceType(A),
+ interfaceTypeStar(A),
];
_checkGroups(numType,
@@ -459,18 +462,27 @@
expect(glb, expectedResult);
}
- void _checkLeastUpperBound(
- DartType type1, DartType type2, DartType expectedResult) {
- var lub = typeSystem.getLeastUpperBound(type1, type2);
- expect(lub, expectedResult);
+ void _checkLeastUpperBound(DartType T1, DartType T2, DartType expected) {
+ var expectedStr = _typeString(expected);
+
+ var result = typeSystem.getLeastUpperBound(T1, T2);
+ var resultStr = _typeString(result);
+ expect(result, expected, reason: '''
+expected: $expectedStr
+actual: $resultStr
+''');
// Check that the result is an upper bound.
- expect(typeSystem.isSubtypeOf(type1, lub), true);
- expect(typeSystem.isSubtypeOf(type2, lub), true);
+ expect(typeSystem.isSubtypeOf(T1, result), true);
+ expect(typeSystem.isSubtypeOf(T2, result), true);
- // Check for symmetry while we're at it.
- lub = typeSystem.getLeastUpperBound(type2, type1);
- expect(lub, expectedResult);
+ // Check for symmetry.
+ result = typeSystem.getLeastUpperBound(T2, T1);
+ resultStr = _typeString(result);
+ expect(result, expected, reason: '''
+expected: $expectedStr
+actual: $resultStr
+''');
}
}
@@ -757,6 +769,57 @@
covariant: true);
}
+ void test_variance_contravariant() {
+ // class A<in T>
+ var tContravariant = typeParameter('T', variance: Variance.contravariant);
+ var tType = typeParameterType(tContravariant);
+ var A = class_(name: 'A', typeParameters: [tContravariant]);
+
+ // A<num>
+ // A<T>
+ var aNum = interfaceType(A,
+ typeArguments: [numType], nullabilitySuffix: NullabilitySuffix.none);
+ var aT = interfaceType(A,
+ typeArguments: [tType], nullabilitySuffix: NullabilitySuffix.none);
+
+ _checkIsSubtypeMatchOf(aT, aNum, [tType], ['num <: in T'], covariant: true);
+ }
+
+ void test_variance_covariant() {
+ // class A<out T>
+ var tCovariant = typeParameter('T', variance: Variance.covariant);
+ var tType = typeParameterType(tCovariant);
+ var A = class_(name: 'A', typeParameters: [tCovariant]);
+
+ // A<num>
+ // A<T>
+ var aNum = interfaceType(A,
+ typeArguments: [numType], nullabilitySuffix: NullabilitySuffix.none);
+ var aT = interfaceType(A,
+ typeArguments: [tType], nullabilitySuffix: NullabilitySuffix.none);
+
+ _checkIsSubtypeMatchOf(aT, aNum, [tType], ['out T <: num'],
+ covariant: true);
+ }
+
+ void test_variance_invariant() {
+ // class A<inout T>
+ var tInvariant = typeParameter('T', variance: Variance.invariant);
+ var tType = typeParameterType(tInvariant);
+ var A = class_(name: 'A', typeParameters: [tInvariant]);
+
+ // A<num>
+ // A<T>
+ var aNum = interfaceType(A,
+ typeArguments: [numType], nullabilitySuffix: NullabilitySuffix.none);
+ var aT = interfaceType(A,
+ typeArguments: [tType], nullabilitySuffix: NullabilitySuffix.none);
+
+ _checkIsSubtypeMatchOf(
+ aT, aNum, [tType], ['inout T <: num', 'num <: inout T'],
+ covariant: true);
+ }
+
void test_x_futureOr_fail_both_branches() {
// List<T> <: FutureOr<String> can't be satisfied because neither
// List<T> <: Future<String> nor List<T> <: int can be satisfied
@@ -892,11 +955,11 @@
// class A {}
var A = class_(name: 'A', superType: objectType);
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
// class B extends A {}
var B = class_(name: 'B', superType: typeA);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
// class C<T extends A> {
var CT = typeParameter('T', bound: typeA);
@@ -922,11 +985,11 @@
// }
// C<Object> cOfObject;
- var cOfObject = interfaceType(C, typeArguments: [objectType]);
+ var cOfObject = interfaceTypeStar(C, typeArguments: [objectType]);
// C<A> cOfA;
- var cOfA = interfaceType(C, typeArguments: [typeA]);
+ var cOfA = interfaceTypeStar(C, typeArguments: [typeA]);
// C<B> cOfB;
- var cOfB = interfaceType(C, typeArguments: [typeB]);
+ var cOfB = interfaceTypeStar(C, typeArguments: [typeB]);
// B b;
// cOfB.m(b); // infer <B>
expect(_inferCall2(cOfB.getMethod('m').type, [typeB]).toString(),
@@ -944,11 +1007,11 @@
// class A {}
var A = class_(name: 'A', superType: objectType);
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
// class B extends A {}
var B = class_(name: 'B', superType: typeA);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
// class C<T extends A> {
var CT = typeParameter('T', bound: typeA);
@@ -975,11 +1038,11 @@
// }
// C<Object> cOfObject;
- var cOfObject = interfaceType(C, typeArguments: [objectType]);
+ var cOfObject = interfaceTypeStar(C, typeArguments: [objectType]);
// C<A> cOfA;
- var cOfA = interfaceType(C, typeArguments: [typeA]);
+ var cOfA = interfaceTypeStar(C, typeArguments: [typeA]);
// C<B> cOfB;
- var cOfB = interfaceType(C, typeArguments: [typeB]);
+ var cOfB = interfaceTypeStar(C, typeArguments: [typeB]);
// List<B> b;
var listOfB = listType(typeB);
// cOfB.m(b); // infer <B>
@@ -1001,20 +1064,20 @@
superType: objectType,
typeParameters: [T],
);
- T.bound = interfaceType(
+ T.bound = interfaceTypeStar(
A,
typeArguments: [typeParameterTypeStar(T)],
);
// class B extends A<B> {}
var B = class_(name: 'B', superType: null);
- B.supertype = interfaceType(A, typeArguments: [interfaceType(B)]);
- var typeB = interfaceType(B);
+ B.supertype = interfaceTypeStar(A, typeArguments: [interfaceTypeStar(B)]);
+ var typeB = interfaceTypeStar(B);
// <S extends A<S>>
var S = typeParameter('S');
var typeS = typeParameterTypeStar(S);
- S.bound = interfaceType(A, typeArguments: [typeS]);
+ S.bound = interfaceTypeStar(A, typeArguments: [typeS]);
// (S, S) -> S
var clone = functionTypeStar(
@@ -1128,6 +1191,50 @@
expect(_inferCall(f, [intType]), [intType]);
}
+ void test_parameter_contravariantUseUpperBound() {
+ // <T>(T x, void Function(T) y) -> T
+ // Generates constraints int <: T <: num.
+ // Since T is contravariant, choose num.
+ var T = typeParameter('T', variance: Variance.contravariant);
+ var tFunction = functionTypeStar(
+ parameters: [requiredParameter(type: typeParameterTypeStar(T))],
+ returnType: voidType);
+ var numFunction = functionTypeStar(
+ parameters: [requiredParameter(type: numType)], returnType: voidType);
+ var function = functionTypeStar(
+ typeFormals: [T],
+ parameters: [
+ requiredParameter(type: typeParameterTypeStar(T)),
+ requiredParameter(type: tFunction)
+ ],
+ returnType: typeParameterTypeStar(T),
+ );
+
+ expect(_inferCall(function, [intType, numFunction]), [numType]);
+ }
+
+ void test_parameter_covariantUseLowerBound() {
+ // <T>(T x, void Function(T) y) -> T
+ // Generates constraints int <: T <: num.
+ // Since T is covariant, choose int.
+ var T = typeParameter('T', variance: Variance.covariant);
+ var tFunction = functionTypeStar(
+ parameters: [requiredParameter(type: typeParameterTypeStar(T))],
+ returnType: voidType);
+ var numFunction = functionTypeStar(
+ parameters: [requiredParameter(type: numType)], returnType: voidType);
+ var function = functionTypeStar(
+ typeFormals: [T],
+ parameters: [
+ requiredParameter(type: typeParameterTypeStar(T)),
+ requiredParameter(type: tFunction)
+ ],
+ returnType: typeParameterTypeStar(T),
+ );
+
+ expect(_inferCall(function, [intType, numFunction]), [intType]);
+ }
+
void test_returnFunctionWithGenericParameter() {
// <T>(T -> T) -> (T -> void)
var T = typeParameter('T');
@@ -1382,6 +1489,7 @@
contextReturnType: returnType,
errorReporter: reporter,
errorNode: astFactory.nullLiteral(new KeywordToken(Keyword.NULL, 0)),
+ isNonNullableByDefault: false,
);
if (expectError) {
@@ -1415,7 +1523,7 @@
void test_bottom_interface() {
var A = class_(name: 'A');
- _checkGreatestLowerBound(neverStar, interfaceType(A), neverStar);
+ _checkGreatestLowerBound(neverStar, interfaceTypeStar(A), neverStar);
}
void test_bottom_typeParam() {
@@ -1486,12 +1594,12 @@
// class B extends A
// class C extends B
var A = class_(name: 'A');
- var B = class_(name: 'B', superType: interfaceType(A));
- var C = class_(name: 'C', superType: interfaceType(B));
+ var B = class_(name: 'B', superType: interfaceTypeStar(A));
+ var C = class_(name: 'C', superType: interfaceTypeStar(B));
_checkGreatestLowerBound(
- interfaceType(A),
- interfaceType(C),
- interfaceType(C),
+ interfaceTypeStar(A),
+ interfaceTypeStar(C),
+ interfaceTypeStar(C),
);
}
@@ -1500,12 +1608,12 @@
// class B implements A
// class C implements B
var A = class_(name: 'A');
- var B = class_(name: 'B', interfaces: [interfaceType(A)]);
- var C = class_(name: 'C', interfaces: [interfaceType(B)]);
+ var B = class_(name: 'B', interfaces: [interfaceTypeStar(A)]);
+ var C = class_(name: 'C', interfaces: [interfaceTypeStar(B)]);
_checkGreatestLowerBound(
- interfaceType(A),
- interfaceType(C),
- interfaceType(C),
+ interfaceTypeStar(A),
+ interfaceTypeStar(C),
+ interfaceTypeStar(C),
);
}
@@ -1522,7 +1630,7 @@
void test_dynamic_interface() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
_checkGreatestLowerBound(dynamicType, typeA, typeA);
}
@@ -1849,7 +1957,7 @@
void test_interface_function() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
_checkGreatestLowerBound(
typeA,
functionTypeStar(returnType: voidType),
@@ -1863,20 +1971,20 @@
// class C
// class D extends A with B, C
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B');
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C');
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
var D = class_(
name: 'D',
- superType: interfaceType(A),
+ superType: interfaceTypeStar(A),
mixins: [typeB, typeC],
);
- var typeD = interfaceType(D);
+ var typeD = interfaceTypeStar(D);
_checkGreatestLowerBound(typeA, typeD, typeD);
_checkGreatestLowerBound(typeB, typeD, typeD);
@@ -1892,7 +2000,7 @@
voidType,
neverStar,
typeParameterTypeStar(T),
- interfaceType(A),
+ interfaceTypeStar(A),
functionTypeStar(returnType: voidType),
];
@@ -1912,13 +2020,13 @@
void test_typeParam_interface_bounded() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', superType: typeA);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', superType: typeB);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
var T = typeParameter('T', bound: typeB);
_checkGreatestLowerBound(typeParameterTypeStar(T), typeC, neverStar);
@@ -1930,7 +2038,7 @@
var A = class_(name: 'A');
_checkGreatestLowerBound(
typeParameterTypeStar(T),
- interfaceType(A),
+ interfaceTypeStar(A),
neverStar,
);
}
@@ -1949,144 +2057,14 @@
_checkGreatestLowerBound(listOfIntType, listOfIntType, listOfIntType);
}
- void test_typeParameters_covariant_same() {
- // class A<out T>
- var T = typeParameter('T', variance: Variance.covariant);
- var A = class_(name: 'A', typeParameters: [T]);
-
- // A<num>
- var aNum = interfaceType(A, typeArguments: [numType]);
-
- _checkLeastUpperBound(aNum, aNum, aNum);
- }
-
- void test_typeParameters_covariant_different() {
- // class A<out T>
- var T = typeParameter('T', variance: Variance.covariant);
- var A = class_(name: 'A', typeParameters: [T]);
-
- // A<num>
- // A<int>
- var aNum = interfaceType(A, typeArguments: [numType]);
- var aInt = interfaceType(A, typeArguments: [intType]);
-
- _checkLeastUpperBound(aInt, aNum, aNum);
- }
-
- void test_typeParameters_contravariant_same() {
- // class A<in T>
- var T = typeParameter('T', variance: Variance.contravariant);
- var A = class_(name: 'A', typeParameters: [T]);
-
- // A<num>
- var aNum = interfaceType(A, typeArguments: [numType]);
-
- _checkLeastUpperBound(aNum, aNum, aNum);
- }
-
- void test_typeParameters_contravariant_different() {
- // class A<in T>
- var T = typeParameter('T', variance: Variance.contravariant);
- var A = class_(name: 'A', typeParameters: [T]);
-
- // A<num>
- // A<int>
- var aNum = interfaceType(A, typeArguments: [numType]);
- var aInt = interfaceType(A, typeArguments: [intType]);
-
- _checkLeastUpperBound(aInt, aNum, aInt);
- }
-
- void test_typeParameters_invariant_same() {
- // class A<inout T>
- var T = typeParameter('T', variance: Variance.invariant);
- var A = class_(name: 'A', typeParameters: [T]);
-
- // A<num>
- var aNum = interfaceType(A, typeArguments: [numType]);
-
- _checkLeastUpperBound(aNum, aNum, aNum);
- }
-
- void test_typeParameters_invariant_object() {
- // class A<inout T>
- var T = typeParameter('T', variance: Variance.invariant);
- var A = class_(name: 'A', typeParameters: [T]);
-
- // A<num>
- // A<int>
- var aNum = interfaceType(A, typeArguments: [numType]);
- var aInt = interfaceType(A, typeArguments: [intType]);
-
- _checkLeastUpperBound(aNum, aInt, objectType);
- }
-
- void test_typeParameters_multi_basic() {
- // class Multi<out T, inout U, in V>
- var T = typeParameter('T', variance: Variance.covariant);
- var U = typeParameter('T', variance: Variance.invariant);
- var V = typeParameter('T', variance: Variance.contravariant);
- var Multi = class_(name: 'A', typeParameters: [T, U, V]);
-
- // Multi<num, num, num>
- // Multi<int, num, int>
- var multiNumNumNum =
- interfaceType(Multi, typeArguments: [numType, numType, numType]);
- var multiIntNumInt =
- interfaceType(Multi, typeArguments: [intType, numType, intType]);
-
- // We expect Multi<num, num, int>
- var multiNumNumInt =
- interfaceType(Multi, typeArguments: [numType, numType, intType]);
-
- _checkLeastUpperBound(multiNumNumNum, multiIntNumInt, multiNumNumInt);
- }
-
- void test_typeParameters_multi_objectInterface() {
- // class Multi<out T, inout U, in V>
- var T = typeParameter('T', variance: Variance.covariant);
- var U = typeParameter('T', variance: Variance.invariant);
- var V = typeParameter('T', variance: Variance.contravariant);
- var Multi = class_(name: 'A', typeParameters: [T, U, V]);
-
- // Multi<num, String, num>
- // Multi<int, num, int>
- var multiNumStringNum =
- interfaceType(Multi, typeArguments: [numType, stringType, numType]);
- var multiIntNumInt =
- interfaceType(Multi, typeArguments: [intType, numType, intType]);
-
- _checkLeastUpperBound(multiNumStringNum, multiIntNumInt, objectType);
- }
-
- void test_typeParameters_multi_objectType() {
- // class Multi<out T, inout U, in V>
- var T = typeParameter('T', variance: Variance.covariant);
- var U = typeParameter('T', variance: Variance.invariant);
- var V = typeParameter('T', variance: Variance.contravariant);
- var Multi = class_(name: 'A', typeParameters: [T, U, V]);
-
- // Multi<String, num, num>
- // Multi<int, num, int>
- var multiStringNumNum =
- interfaceType(Multi, typeArguments: [stringType, numType, numType]);
- var multiIntNumInt =
- interfaceType(Multi, typeArguments: [intType, numType, intType]);
-
- // We expect Multi<Object, num, int>
- var multiObjectNumInt =
- interfaceType(Multi, typeArguments: [objectType, numType, intType]);
-
- _checkLeastUpperBound(multiStringNumNum, multiIntNumInt, multiObjectNumInt);
- }
-
void test_unrelatedClasses() {
// class A
// class B
// class C
var A = class_(name: 'A');
var B = class_(name: 'B');
- _checkGreatestLowerBound(interfaceType(A), interfaceType(B), neverStar);
+ _checkGreatestLowerBound(
+ interfaceTypeStar(A), interfaceTypeStar(B), neverStar);
}
void test_void() {
@@ -2095,7 +2073,7 @@
List<DartType> types = [
neverStar,
functionTypeStar(returnType: voidType),
- interfaceType(A),
+ interfaceTypeStar(A),
typeParameterTypeStar(T),
];
for (DartType type in types) {
@@ -2405,17 +2383,20 @@
@reflectiveTest
class LeastUpperBoundTest extends BoundTestBase {
+ @FailingTest(reason: 'With new rules UP(Never*, T)=T?')
void test_bottom_function() {
_checkLeastUpperBound(neverStar, functionTypeStar(returnType: voidType),
functionTypeStar(returnType: voidType));
}
+ @FailingTest(reason: 'With new rules UP(Never*, T)=T?')
void test_bottom_interface() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
_checkLeastUpperBound(neverStar, typeA, typeA);
}
+ @FailingTest(reason: 'With new rules UP(Never*, T)=T?')
void test_bottom_typeParam() {
var T = typeParameter('T');
var typeT = typeParameterTypeStar(T);
@@ -2428,13 +2409,13 @@
// class C implements B
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', interfaces: [typeA]);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', interfaces: [typeB]);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
_checkLeastUpperBound(typeB, typeC, typeB);
}
@@ -2445,31 +2426,22 @@
// class C extends B
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', superType: typeA);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', superType: typeB);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
_checkLeastUpperBound(typeB, typeC, typeB);
}
void test_directSuperclass_nullability() {
var aElement = class_(name: 'A');
- var aQuestion = interfaceType(
- aElement,
- nullabilitySuffix: NullabilitySuffix.question,
- );
- var aStar = interfaceType(
- aElement,
- nullabilitySuffix: NullabilitySuffix.star,
- );
- var aNone = interfaceType(
- aElement,
- nullabilitySuffix: NullabilitySuffix.none,
- );
+ var aQuestion = interfaceTypeQuestion(aElement);
+ var aStar = interfaceTypeStar(aElement);
+ var aNone = interfaceTypeNone(aElement);
var bElementStar = class_(name: 'B', superType: aStar);
var bElementNone = class_(name: 'B', superType: aNone);
@@ -2537,7 +2509,7 @@
void test_dynamic_interface() {
var A = class_(name: 'A');
- _checkLeastUpperBound(dynamicType, interfaceType(A), dynamicType);
+ _checkLeastUpperBound(dynamicType, interfaceTypeStar(A), dynamicType);
}
void test_dynamic_typeParam() {
@@ -2552,25 +2524,16 @@
void test_interface_function() {
var A = class_(name: 'A');
- _checkLeastUpperBound(
- interfaceType(A), functionTypeStar(returnType: voidType), objectType);
+ _checkLeastUpperBound(interfaceTypeStar(A),
+ functionTypeStar(returnType: voidType), objectType);
}
void test_interface_sameElement_nullability() {
var aElement = class_(name: 'A');
- var aQuestion = interfaceType(
- aElement,
- nullabilitySuffix: NullabilitySuffix.question,
- );
- var aStar = interfaceType(
- aElement,
- nullabilitySuffix: NullabilitySuffix.star,
- );
- var aNone = interfaceType(
- aElement,
- nullabilitySuffix: NullabilitySuffix.none,
- );
+ var aQuestion = interfaceTypeQuestion(aElement);
+ var aStar = interfaceTypeStar(aElement);
+ var aNone = interfaceTypeNone(aElement);
void assertLUB(DartType type1, DartType type2, DartType expected) {
expect(typeSystem.getLeastUpperBound(type1, type2), expected);
@@ -2599,31 +2562,25 @@
interfaces: [instA.withNullabilitySuffixNone],
);
- var mixinM = ElementFactory.mixinElement(
+ var mixinM = mixin_(
name: 'M',
constraints: [instA.withNullabilitySuffixNone],
);
_checkLeastUpperBound(
- interfaceType(
- classB,
- nullabilitySuffix: NullabilitySuffix.star,
- ),
- interfaceType(
- mixinM,
- nullabilitySuffix: NullabilitySuffix.star,
- ),
+ interfaceTypeStar(classB),
+ interfaceTypeStar(mixinM),
instA.withNullability(NullabilitySuffix.star),
);
}
void test_mixinAndClass_object() {
var classA = class_(name: 'A');
- var mixinM = ElementFactory.mixinElement(name: 'M');
+ var mixinM = mixin_(name: 'M');
_checkLeastUpperBound(
- interfaceType(classA),
- interfaceType(mixinM),
+ interfaceTypeStar(classA),
+ interfaceTypeStar(mixinM),
objectType,
);
}
@@ -2637,20 +2594,14 @@
interfaces: [instA.withNullabilitySuffixNone],
);
- var mixinM = ElementFactory.mixinElement(
+ var mixinM = mixin_(
name: 'M',
interfaces: [instA.withNullabilitySuffixNone],
);
_checkLeastUpperBound(
- interfaceType(
- classB,
- nullabilitySuffix: NullabilitySuffix.star,
- ),
- interfaceType(
- mixinM,
- nullabilitySuffix: NullabilitySuffix.star,
- ),
+ interfaceTypeStar(classB),
+ interfaceTypeStar(mixinM),
instA.withNullability(NullabilitySuffix.star),
);
}
@@ -2662,25 +2613,25 @@
// class D extends B with M, N, O, P
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', superType: typeA);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', superType: typeA);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
var D = class_(
name: 'D',
superType: typeB,
mixins: [
- interfaceType(class_(name: 'M')),
- interfaceType(class_(name: 'N')),
- interfaceType(class_(name: 'O')),
- interfaceType(class_(name: 'P')),
+ interfaceTypeStar(class_(name: 'M')),
+ interfaceTypeStar(class_(name: 'N')),
+ interfaceTypeStar(class_(name: 'O')),
+ interfaceTypeStar(class_(name: 'P')),
],
);
- var typeD = interfaceType(D);
+ var typeD = interfaceTypeStar(D);
_checkLeastUpperBound(typeD, typeC, typeA);
}
@@ -2821,8 +2772,8 @@
void test_object() {
var A = class_(name: 'A');
var B = class_(name: 'B');
- var typeA = interfaceType(A);
- var typeB = interfaceType(B);
+ var typeA = interfaceTypeStar(A);
+ var typeB = interfaceTypeStar(B);
var typeObject = typeA.element.supertype;
// assert that object does not have a super type
expect(typeObject.element.supertype, isNull);
@@ -2841,7 +2792,7 @@
voidType,
neverStar,
typeParameterTypeStar(T),
- interfaceType(A),
+ interfaceTypeStar(A),
functionTypeStar(returnType: voidType)
];
@@ -2852,31 +2803,22 @@
void test_sharedSuperclass1() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', superType: typeA);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', superType: typeA);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
_checkLeastUpperBound(typeB, typeC, typeA);
}
void test_sharedSuperclass1_nullability() {
var aElement = class_(name: 'A');
- var aQuestion = interfaceType(
- aElement,
- nullabilitySuffix: NullabilitySuffix.question,
- );
- var aStar = interfaceType(
- aElement,
- nullabilitySuffix: NullabilitySuffix.star,
- );
- var aNone = interfaceType(
- aElement,
- nullabilitySuffix: NullabilitySuffix.none,
- );
+ var aQuestion = interfaceTypeQuestion(aElement);
+ var aStar = interfaceTypeStar(aElement);
+ var aNone = interfaceTypeNone(aElement);
var bElementNone = class_(name: 'B', superType: aNone);
var bElementStar = class_(name: 'B', superType: aStar);
@@ -2978,115 +2920,115 @@
void test_sharedSuperclass2() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', superType: typeA);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', superType: typeA);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
var D = class_(name: 'D', superType: typeC);
- var typeD = interfaceType(D);
+ var typeD = interfaceTypeStar(D);
_checkLeastUpperBound(typeB, typeD, typeA);
}
void test_sharedSuperclass3() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', superType: typeA);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', superType: typeB);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
var D = class_(name: 'D', superType: typeB);
- var typeD = interfaceType(D);
+ var typeD = interfaceTypeStar(D);
_checkLeastUpperBound(typeC, typeD, typeB);
}
void test_sharedSuperclass4() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var A2 = class_(name: 'A2');
- var typeA2 = interfaceType(A2);
+ var typeA2 = interfaceTypeStar(A2);
var A3 = class_(name: 'A3');
- var typeA3 = interfaceType(A3);
+ var typeA3 = interfaceTypeStar(A3);
var B = class_(name: 'B', superType: typeA, interfaces: [typeA2]);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', superType: typeA, interfaces: [typeA3]);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
_checkLeastUpperBound(typeB, typeC, typeA);
}
void test_sharedSuperinterface1() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', interfaces: [typeA]);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', interfaces: [typeA]);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
_checkLeastUpperBound(typeB, typeC, typeA);
}
void test_sharedSuperinterface2() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', interfaces: [typeA]);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', interfaces: [typeA]);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
var D = class_(name: 'D', interfaces: [typeC]);
- var typeD = interfaceType(D);
+ var typeD = interfaceTypeStar(D);
_checkLeastUpperBound(typeB, typeD, typeA);
}
void test_sharedSuperinterface3() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', interfaces: [typeA]);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', interfaces: [typeB]);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
var D = class_(name: 'D', interfaces: [typeB]);
- var typeD = interfaceType(D);
+ var typeD = interfaceTypeStar(D);
_checkLeastUpperBound(typeC, typeD, typeB);
}
void test_sharedSuperinterface4() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var A2 = class_(name: 'A2');
- var typeA2 = interfaceType(A2);
+ var typeA2 = interfaceTypeStar(A2);
var A3 = class_(name: 'A3');
- var typeA3 = interfaceType(A3);
+ var typeA3 = interfaceTypeStar(A3);
var B = class_(name: 'B', interfaces: [typeA, typeA2]);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', interfaces: [typeA, typeA3]);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
_checkLeastUpperBound(typeB, typeC, typeA);
}
@@ -3107,7 +3049,7 @@
void test_typeParam_class_implements_Function_ignored() {
var A = class_(name: 'A', superType: typeProvider.functionType);
- var T = typeParameter('T', bound: interfaceType(A));
+ var T = typeParameter('T', bound: interfaceTypeStar(A));
_checkLeastUpperBound(typeParameterTypeStar(T),
functionTypeStar(returnType: voidType), objectType);
}
@@ -3118,16 +3060,16 @@
var S = typeParameter('S');
var typeS = typeParameterTypeStar(S);
- S.bound = interfaceType(A, typeArguments: [typeS]);
+ S.bound = interfaceTypeStar(A, typeArguments: [typeS]);
var U = typeParameter('U');
var typeU = typeParameterTypeStar(U);
- U.bound = interfaceType(A, typeArguments: [typeU]);
+ U.bound = interfaceTypeStar(A, typeArguments: [typeU]);
_checkLeastUpperBound(
typeS,
typeParameterTypeStar(U),
- interfaceType(A, typeArguments: [objectType]),
+ interfaceTypeStar(A, typeArguments: [objectType]),
);
}
@@ -3151,13 +3093,13 @@
void test_typeParam_interface_bounded() {
var A = class_(name: 'A');
- var typeA = interfaceType(A);
+ var typeA = interfaceTypeStar(A);
var B = class_(name: 'B', superType: typeA);
- var typeB = interfaceType(B);
+ var typeB = interfaceTypeStar(B);
var C = class_(name: 'C', superType: typeA);
- var typeC = interfaceType(C);
+ var typeC = interfaceTypeStar(C);
var T = typeParameter('T', bound: typeB);
var typeT = typeParameterTypeStar(T);
@@ -3170,11 +3112,59 @@
var A = class_(name: 'A');
_checkLeastUpperBound(
typeParameterTypeStar(T),
- interfaceType(A),
+ interfaceTypeStar(A),
objectType,
);
}
+ void test_typeParameters_contravariant_different() {
+ // class A<in T>
+ var T = typeParameter('T', variance: Variance.contravariant);
+ var A = class_(name: 'A', typeParameters: [T]);
+
+ // A<num>
+ // A<int>
+ var aNum = interfaceTypeStar(A, typeArguments: [numType]);
+ var aInt = interfaceTypeStar(A, typeArguments: [intType]);
+
+ _checkLeastUpperBound(aInt, aNum, aInt);
+ }
+
+ void test_typeParameters_contravariant_same() {
+ // class A<in T>
+ var T = typeParameter('T', variance: Variance.contravariant);
+ var A = class_(name: 'A', typeParameters: [T]);
+
+ // A<num>
+ var aNum = interfaceTypeStar(A, typeArguments: [numType]);
+
+ _checkLeastUpperBound(aNum, aNum, aNum);
+ }
+
+ void test_typeParameters_covariant_different() {
+ // class A<out T>
+ var T = typeParameter('T', variance: Variance.covariant);
+ var A = class_(name: 'A', typeParameters: [T]);
+
+ // A<num>
+ // A<int>
+ var aNum = interfaceTypeStar(A, typeArguments: [numType]);
+ var aInt = interfaceTypeStar(A, typeArguments: [intType]);
+
+ _checkLeastUpperBound(aInt, aNum, aNum);
+ }
+
+ void test_typeParameters_covariant_same() {
+ // class A<out T>
+ var T = typeParameter('T', variance: Variance.covariant);
+ var A = class_(name: 'A', typeParameters: [T]);
+
+ // A<num>
+ var aNum = interfaceTypeStar(A, typeArguments: [numType]);
+
+ _checkLeastUpperBound(aNum, aNum, aNum);
+ }
+
/// Check least upper bound of the same class with different type parameters.
void test_typeParameters_different() {
// class List<int>
@@ -3185,6 +3175,89 @@
_checkLeastUpperBound(listOfIntType, listOfDoubleType, listOfNum);
}
+ void test_typeParameters_invariant_object() {
+ // class A<inout T>
+ var T = typeParameter('T', variance: Variance.invariant);
+ var A = class_(name: 'A', typeParameters: [T]);
+
+ // A<num>
+ // A<int>
+ var aNum = interfaceTypeStar(A, typeArguments: [numType]);
+ var aInt = interfaceTypeStar(A, typeArguments: [intType]);
+
+ _checkLeastUpperBound(aNum, aInt, objectType);
+ }
+
+ void test_typeParameters_invariant_same() {
+ // class A<inout T>
+ var T = typeParameter('T', variance: Variance.invariant);
+ var A = class_(name: 'A', typeParameters: [T]);
+
+ // A<num>
+ var aNum = interfaceTypeStar(A, typeArguments: [numType]);
+
+ _checkLeastUpperBound(aNum, aNum, aNum);
+ }
+
+ void test_typeParameters_multi_basic() {
+ // class Multi<out T, inout U, in V>
+ var T = typeParameter('T', variance: Variance.covariant);
+ var U = typeParameter('T', variance: Variance.invariant);
+ var V = typeParameter('T', variance: Variance.contravariant);
+ var Multi = class_(name: 'A', typeParameters: [T, U, V]);
+
+ // Multi<num, num, num>
+ // Multi<int, num, int>
+ var multiNumNumNum =
+ interfaceTypeStar(Multi, typeArguments: [numType, numType, numType]);
+ var multiIntNumInt =
+ interfaceTypeStar(Multi, typeArguments: [intType, numType, intType]);
+
+ // We expect Multi<num, num, int>
+ var multiNumNumInt =
+ interfaceTypeStar(Multi, typeArguments: [numType, numType, intType]);
+
+ _checkLeastUpperBound(multiNumNumNum, multiIntNumInt, multiNumNumInt);
+ }
+
+ void test_typeParameters_multi_objectInterface() {
+ // class Multi<out T, inout U, in V>
+ var T = typeParameter('T', variance: Variance.covariant);
+ var U = typeParameter('T', variance: Variance.invariant);
+ var V = typeParameter('T', variance: Variance.contravariant);
+ var Multi = class_(name: 'A', typeParameters: [T, U, V]);
+
+ // Multi<num, String, num>
+ // Multi<int, num, int>
+ var multiNumStringNum =
+ interfaceTypeStar(Multi, typeArguments: [numType, stringType, numType]);
+ var multiIntNumInt =
+ interfaceTypeStar(Multi, typeArguments: [intType, numType, intType]);
+
+ _checkLeastUpperBound(multiNumStringNum, multiIntNumInt, objectType);
+ }
+
+ void test_typeParameters_multi_objectType() {
+ // class Multi<out T, inout U, in V>
+ var T = typeParameter('T', variance: Variance.covariant);
+ var U = typeParameter('T', variance: Variance.invariant);
+ var V = typeParameter('T', variance: Variance.contravariant);
+ var Multi = class_(name: 'A', typeParameters: [T, U, V]);
+
+ // Multi<String, num, num>
+ // Multi<int, num, int>
+ var multiStringNumNum =
+ interfaceTypeStar(Multi, typeArguments: [stringType, numType, numType]);
+ var multiIntNumInt =
+ interfaceTypeStar(Multi, typeArguments: [intType, numType, intType]);
+
+ // We expect Multi<Object, num, int>
+ var multiObjectNumInt =
+ interfaceTypeStar(Multi, typeArguments: [objectType, numType, intType]);
+
+ _checkLeastUpperBound(multiStringNumNum, multiIntNumInt, multiObjectNumInt);
+ }
+
void test_typeParameters_same() {
// List<int>
// List<int>
@@ -3209,7 +3282,7 @@
List<DartType> types = [
neverStar,
functionTypeStar(returnType: voidType),
- interfaceType(A),
+ interfaceTypeStar(A),
typeParameterTypeStar(T),
];
for (DartType type in types) {
@@ -3222,123 +3295,23 @@
}
}
-//class Mix with ElementsTypesMixin {
-// TypeProvider typeProvider;
-// Dart2TypeSystem typeSystem;
-//
-// FeatureSet get testFeatureSet {
-// return FeatureSet.forTesting();
-// }
-//
-// void setUp() {
-// var analysisContext = TestAnalysisContext(
-// featureSet: testFeatureSet,
-// );
-// typeProvider = analysisContext.typeProvider;
-// typeSystem = analysisContext.typeSystem;
-// }
-//}
-
-class SubtypingTestBase extends AbstractTypeSystemTest {
- void _checkEquivalent(DartType type1, DartType type2) {
- _checkIsSubtypeOf(type1, type2);
- _checkIsSubtypeOf(type2, type1);
- }
-
- void _checkGroups(DartType t1,
- {List<DartType> equivalents,
- List<DartType> unrelated,
- List<DartType> subtypes,
- List<DartType> supertypes}) {
- if (equivalents != null) {
- for (DartType t2 in equivalents) {
- _checkEquivalent(t1, t2);
- }
- }
- if (unrelated != null) {
- for (DartType t2 in unrelated) {
- _checkUnrelated(t1, t2);
- }
- }
- if (subtypes != null) {
- for (DartType t2 in subtypes) {
- _checkIsStrictSubtypeOf(t2, t1);
- }
- }
- if (supertypes != null) {
- for (DartType t2 in supertypes) {
- _checkIsStrictSubtypeOf(t1, t2);
- }
- }
- }
-
- void _checkIsNotSubtypeOf(DartType type1, DartType type2) {
- var strType1 = _toStringWithNullability(type1);
- var strType2 = _toStringWithNullability(type2);
- expect(typeSystem.isSubtypeOf(type1, type2), false,
- reason: '$strType1 was not supposed to be a subtype of $strType2');
- }
-
- void _checkIsStrictSubtypeOf(DartType type1, DartType type2) {
- _checkIsSubtypeOf(type1, type2);
- _checkIsNotSubtypeOf(type2, type1);
- }
-
- void _checkIsSubtypeOf(DartType type1, DartType type2) {
- expect(typeSystem.isSubtypeOf(type1, type2), true,
- reason: '$type1 is not a subtype of $type2');
- }
-
- void _checkLattice(
- DartType top, DartType left, DartType right, DartType bottom) {
- _checkGroups(top,
- equivalents: <DartType>[top],
- subtypes: <DartType>[left, right, bottom]);
- _checkGroups(left,
- equivalents: <DartType>[left],
- subtypes: <DartType>[bottom],
- unrelated: <DartType>[right],
- supertypes: <DartType>[top]);
- _checkGroups(right,
- equivalents: <DartType>[right],
- subtypes: <DartType>[bottom],
- unrelated: <DartType>[left],
- supertypes: <DartType>[top]);
- _checkGroups(bottom,
- equivalents: <DartType>[bottom],
- supertypes: <DartType>[top, left, right]);
- }
-
- void _checkUnrelated(DartType type1, DartType type2) {
- _checkIsNotSubtypeOf(type1, type2);
- _checkIsNotSubtypeOf(type2, type1);
- }
-
- static String _toStringWithNullability(DartType type) {
- return (type as TypeImpl).toString(withNullability: true);
- }
-}
-
@reflectiveTest
class TypeSystemTest extends AbstractTypeSystemTest {
InterfaceTypeImpl get functionClassTypeNone {
- return interfaceType(
+ return interfaceTypeNone(
typeProvider.functionType.element,
- nullabilitySuffix: NullabilitySuffix.none,
);
}
InterfaceTypeImpl get functionClassTypeQuestion {
- return interfaceType(
+ return interfaceTypeQuestion(
typeProvider.functionType.element,
- nullabilitySuffix: NullabilitySuffix.question,
);
}
InterfaceTypeImpl get functionClassTypeStar {
- return interfaceType(
+ return interfaceTypeStar(
typeProvider.functionType.element,
- nullabilitySuffix: NullabilitySuffix.star,
);
}
@@ -3379,75 +3352,60 @@
.withNullability(NullabilitySuffix.star);
InterfaceTypeImpl get stringClassTypeNone {
- return interfaceType(
+ return interfaceTypeNone(
typeProvider.stringType.element,
- nullabilitySuffix: NullabilitySuffix.none,
);
}
InterfaceTypeImpl get stringClassTypeQuestion {
- return interfaceType(
+ return interfaceTypeQuestion(
typeProvider.stringType.element,
- nullabilitySuffix: NullabilitySuffix.question,
);
}
InterfaceTypeImpl get stringClassTypeStar {
- return interfaceType(
+ return interfaceTypeStar(
typeProvider.stringType.element,
- nullabilitySuffix: NullabilitySuffix.star,
);
}
InterfaceTypeImpl futureOrTypeNone({@required DartType argument}) {
- var element = typeProvider.futureOrElement;
- return interfaceType(
- element,
+ return typeProvider.futureOrElement.instantiate(
typeArguments: <DartType>[argument],
nullabilitySuffix: NullabilitySuffix.none,
);
}
InterfaceTypeImpl futureOrTypeQuestion({@required DartType argument}) {
- var element = typeProvider.futureOrElement;
- return interfaceType(
- element,
+ return typeProvider.futureOrElement.instantiate(
typeArguments: <DartType>[argument],
nullabilitySuffix: NullabilitySuffix.question,
);
}
InterfaceTypeImpl futureOrTypeStar({@required DartType argument}) {
- var element = typeProvider.futureOrElement;
- return interfaceType(
- element,
+ return typeProvider.futureOrElement.instantiate(
typeArguments: <DartType>[argument],
nullabilitySuffix: NullabilitySuffix.star,
);
}
InterfaceTypeImpl listClassTypeNone(DartType argument) {
- var element = typeProvider.listElement;
- return interfaceType(
- element,
+ return typeProvider.listElement.instantiate(
typeArguments: <DartType>[argument],
nullabilitySuffix: NullabilitySuffix.none,
);
}
InterfaceTypeImpl listClassTypeQuestion(DartType argument) {
- var element = typeProvider.listElement;
- return interfaceType(
- element,
+ return typeProvider.listElement.instantiate(
typeArguments: <DartType>[argument],
nullabilitySuffix: NullabilitySuffix.question,
);
}
InterfaceTypeImpl listClassTypeStar(DartType argument) {
- var element = typeProvider.listElement;
- return interfaceType(
- element,
+ return typeProvider.listElement.instantiate(
typeArguments: <DartType>[argument],
nullabilitySuffix: NullabilitySuffix.star,
);
diff --git a/pkg/analyzer/test/source/error_processor_test.dart b/pkg/analyzer/test/source/error_processor_test.dart
index 71d8d5e..ec49f93 100644
--- a/pkg/analyzer/test/source/error_processor_test.dart
+++ b/pkg/analyzer/test/source/error_processor_test.dart
@@ -2,11 +2,14 @@
// 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:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/error_processor.dart';
import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/task/options.dart';
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';
@@ -157,4 +160,13 @@
ErrorProcessor getProcessor(AnalysisError error) =>
ErrorProcessor.getProcessor(context.analysisOptions, error);
-class TestContext extends AnalysisContextImpl {}
+class TestContext extends AnalysisContextImpl {
+ TestContext()
+ : super(
+ SynchronousSession(
+ AnalysisOptionsImpl(),
+ DeclaredVariables(),
+ ),
+ null,
+ );
+}
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index cfe7454..fccee0d 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -593,35 +593,6 @@
expect(workspace, TypeMatcher<BasicWorkspace>());
}
- void test_declareVariables_emptyMap() {
- AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
- Iterable<String> expected = context.declaredVariables.variableNames;
- builderOptions.declaredVariables = <String, String>{};
-
- builder.declareVariables(context);
- expect(context.declaredVariables.variableNames, unorderedEquals(expected));
- }
-
- void test_declareVariables_nonEmptyMap() {
- AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
- List<String> expected = context.declaredVariables.variableNames.toList();
- expect(expected, isNot(contains('a')));
- expect(expected, isNot(contains('b')));
- expected.addAll(['a', 'b']);
- builderOptions.declaredVariables = <String, String>{'a': 'a', 'b': 'b'};
-
- builder.declareVariables(context);
- expect(context.declaredVariables.variableNames, unorderedEquals(expected));
- }
-
- void test_declareVariables_null() {
- AnalysisContext context = AnalysisEngine.instance.createAnalysisContext();
- Iterable<String> expected = context.declaredVariables.variableNames;
-
- builder.declareVariables(context);
- expect(context.declaredVariables.variableNames, unorderedEquals(expected));
- }
-
@failingTest
void test_findSdk_embedder_extensions() {
// See test_createSourceFactory_noProvider_packages_embedder_extensions
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 2bba18a..573749d 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -833,10 +833,10 @@
expect(atD.element, constructorD);
expect(constC.staticElement, constructorC);
- expect(constC.staticType, interfaceType(elementC));
+ expect(constC.staticType, interfaceTypeStar(elementC));
expect(constC.constructorName.staticElement, constructorC);
- expect(constC.constructorName.type.type, interfaceType(elementC));
+ expect(constC.constructorName.type.type, interfaceTypeStar(elementC));
}
test_annotation_unprefixed_topLevelVariable() async {
@@ -1468,7 +1468,7 @@
expect(constructorName.staticElement, same(aUnnamed));
TypeName typeName = constructorName.type;
- expect(typeName.type, interfaceType(aElement));
+ expect(typeName.type, interfaceTypeStar(aElement));
SimpleIdentifier identifier = typeName.name;
expect(identifier.staticElement, same(aElement));
@@ -1488,7 +1488,7 @@
expect(constructorName.staticElement, same(aNamed));
TypeName typeName = constructorName.type;
- expect(typeName.type, interfaceType(aElement));
+ expect(typeName.type, interfaceTypeStar(aElement));
SimpleIdentifier identifier = typeName.name;
expect(identifier.staticElement, same(aElement));
@@ -2217,7 +2217,7 @@
VariableDeclaration aNode = aDeclaration.variables.variables[0];
InstanceCreationExpression value = aNode.initializer;
expect(value.staticElement, defaultConstructor);
- expect(value.staticType, interfaceType(cElement));
+ expect(value.staticType, interfaceTypeStar(cElement));
TypeName typeName = value.constructorName.type;
expect(typeName.typeArguments, isNull);
@@ -2234,7 +2234,7 @@
VariableDeclaration bNode = bDeclaration.variables.variables[0];
InstanceCreationExpression value = bNode.initializer;
expect(value.staticElement, namedConstructor);
- expect(value.staticType, interfaceType(cElement));
+ expect(value.staticType, interfaceTypeStar(cElement));
TypeName typeName = value.constructorName.type;
expect(typeName.typeArguments, isNull);
@@ -2270,7 +2270,7 @@
InstanceCreationExpression creation = vNode.initializer;
List<Expression> arguments = creation.argumentList.arguments;
expect(creation.staticElement, constructorElement);
- expect(creation.staticType, interfaceType(xElement));
+ expect(creation.staticType, interfaceTypeStar(xElement));
TypeName typeName = creation.constructorName.type;
expect(typeName.typeArguments, isNull);
@@ -2310,7 +2310,7 @@
VariableDeclaration aNode = aDeclaration.variables.variables[0];
InstanceCreationExpression value = aNode.initializer;
expect(value.staticElement, defaultConstructor);
- expect(value.staticType, interfaceType(cElement));
+ expect(value.staticType, interfaceTypeStar(cElement));
TypeName typeName = value.constructorName.type;
expect(typeName.typeArguments, isNull);
@@ -2330,7 +2330,7 @@
VariableDeclaration bNode = bDeclaration.variables.variables[0];
InstanceCreationExpression value = bNode.initializer;
expect(value.staticElement, namedConstructor);
- expect(value.staticType, interfaceType(cElement));
+ expect(value.staticType, interfaceTypeStar(cElement));
TypeName typeName = value.constructorName.type;
expect(typeName.typeArguments, isNull);
@@ -2616,7 +2616,7 @@
expect(creation.constructorName.name, isNull);
Expression argument = creation.argumentList.arguments[0];
- _assertArgumentToParameter(argument, defaultConstructor.parameters[0]);
+ _assertArgumentToParameter2(argument, 'int');
}
{
@@ -2638,7 +2638,7 @@
assertType(constructorName, null);
var argument = creation.argumentList.arguments[0];
- _assertArgumentToParameter(argument, namedConstructor.parameters[0]);
+ _assertArgumentToParameter2(argument, 'num');
}
}
@@ -6295,7 +6295,7 @@
SimpleIdentifier prefix = prefixed.prefix;
expect(prefix.staticElement, same(vElement));
- expect(prefix.staticType, interfaceType(cElement));
+ expect(prefix.staticType, interfaceTypeStar(cElement));
SimpleIdentifier identifier = prefixed.identifier;
expect(identifier.staticElement, same(fElement.getter));
@@ -6623,7 +6623,7 @@
InstanceCreationExpression newC = access.target;
expect(newC.staticElement, cClassElement.unnamedConstructor);
- expect(newC.staticType, interfaceType(cClassElement));
+ expect(newC.staticType, interfaceTypeStar(cClassElement));
expect(access.propertyName.staticElement, same(fElement.getter));
expect(access.propertyName.staticType, typeProvider.intType);
@@ -6658,7 +6658,7 @@
InstanceCreationExpression newC = access.target;
expect(newC.staticElement, cClassElement.unnamedConstructor);
- expect(newC.staticType, interfaceType(cClassElement));
+ expect(newC.staticType, interfaceTypeStar(cClassElement));
expect(access.propertyName.staticElement, same(fElement.getter));
expect(access.propertyName.staticType, typeProvider.intType);
@@ -6823,7 +6823,8 @@
MethodInvocation invocation = statement.expression;
SuperExpression target = invocation.target;
- expect(target.staticType, interfaceType(bNode.declaredElement)); // raw
+ expect(
+ target.staticType, interfaceTypeStar(bNode.declaredElement)); // raw
expect(invocation.methodName.staticElement, same(methodElement));
}
@@ -6844,7 +6845,8 @@
expect(propertyAccess.staticType, typeProvider.intType);
SuperExpression target = propertyAccess.target;
- expect(target.staticType, interfaceType(bNode.declaredElement)); // raw
+ expect(
+ target.staticType, interfaceTypeStar(bNode.declaredElement)); // raw
expect(propertyAccess.propertyName.staticElement, same(getterElement));
expect(propertyAccess.propertyName.staticType, typeProvider.intType);
@@ -6868,7 +6870,8 @@
PropertyAccess propertyAccess = assignment.leftHandSide;
SuperExpression target = propertyAccess.target;
- expect(target.staticType, interfaceType(bNode.declaredElement)); // raw
+ expect(
+ target.staticType, interfaceTypeStar(bNode.declaredElement)); // raw
expect(propertyAccess.propertyName.staticElement, same(setterElement));
expect(propertyAccess.propertyName.staticType, typeProvider.intType);
@@ -6880,7 +6883,8 @@
BinaryExpression binary = statement.expression;
ThisExpression target = binary.leftOperand;
- expect(target.staticType, interfaceType(bNode.declaredElement)); // raw
+ expect(
+ target.staticType, interfaceTypeStar(bNode.declaredElement)); // raw
expect(binary.staticElement, same(operatorElement));
expect(binary.staticType, typeProvider.intType);
@@ -6920,7 +6924,7 @@
List<Statement> testStatements = testBody.block.statements;
var elementA = findElement.class_('A');
- var thisTypeA = interfaceType(elementA);
+ var thisTypeA = interfaceTypeStar(elementA);
// method(1);
{
@@ -7763,7 +7767,7 @@
expect(tNode.declaredElement, same(cElement.typeParameters[0]));
TypeName bound = tNode.bound;
- expect(bound.type, interfaceType(aElement));
+ expect(bound.type, interfaceTypeStar(aElement));
SimpleIdentifier boundIdentifier = bound.name;
expect(boundIdentifier.staticElement, same(aElement));
@@ -7773,7 +7777,7 @@
{
var listElement = typeProvider.listElement;
var listOfA = listElement.instantiate(
- typeArguments: [interfaceType(aElement)],
+ typeArguments: [interfaceTypeStar(aElement)],
nullabilitySuffix: NullabilitySuffix.star,
);
@@ -7788,7 +7792,7 @@
expect(listIdentifier.staticType, isNull);
TypeName aTypeName = bound.typeArguments.arguments[0];
- expect(aTypeName.type, interfaceType(aElement));
+ expect(aTypeName.type, interfaceTypeStar(aElement));
SimpleIdentifier aIdentifier = aTypeName.name;
expect(aIdentifier.staticElement, same(aElement));
@@ -8291,7 +8295,7 @@
ExpressionStatement statement = statements[0];
InstanceCreationExpression creation = statement.expression;
- expect(creation.staticType, interfaceType(randomElement));
+ expect(creation.staticType, interfaceTypeStar(randomElement));
ConstructorName constructorName = creation.constructorName;
diff --git a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
index a56c686..791e065 100644
--- a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
@@ -2706,6 +2706,18 @@
_assertSource("E", AstTestFactory.typeParameter("E"));
}
+ void test_visitTypeParameter_variance_covariant() {
+ _assertSource("out E", AstTestFactory.typeParameter3("E", "out"));
+ }
+
+ void test_visitTypeParameter_variance_contravariant() {
+ _assertSource("in E", AstTestFactory.typeParameter3("E", "in"));
+ }
+
+ void test_visitTypeParameter_variance_invariant() {
+ _assertSource("inout E", AstTestFactory.typeParameter3("E", "inout"));
+ }
+
void test_visitTypeParameterList_multiple() {
_assertSource("<E, F>", AstTestFactory.typeParameterList(["E", "F"]));
}
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index bc1afd0..8f414bc 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -138,7 +138,7 @@
]);
AdjacentStrings fromNode = createNode();
- DartType staticType = interfaceType(ElementFactory.classElement2('B'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('B'));
fromNode.staticType = staticType;
AdjacentStrings toNode = createNode();
@@ -161,7 +161,7 @@
void test_visitAsExpression() {
AsExpression fromNode = AstTestFactory.asExpression(
AstTestFactory.identifier3("x"), AstTestFactory.typeName4("A"));
- DartType staticType = interfaceType(ElementFactory.classElement2('B'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('B'));
fromNode.staticType = staticType;
AsExpression toNode = AstTestFactory.asExpression(
AstTestFactory.identifier3("x"), AstTestFactory.typeName4("A"));
@@ -174,7 +174,7 @@
AstTestFactory.identifier3("a"),
TokenType.PLUS_EQ,
AstTestFactory.identifier3("b"));
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
MethodElement staticElement = ElementFactory.methodElement("+", staticType);
fromNode.staticElement = staticElement;
fromNode.staticType = staticType;
@@ -192,7 +192,7 @@
AstTestFactory.identifier3("a"),
TokenType.PLUS,
AstTestFactory.identifier3("b"));
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
MethodElement staticElement = ElementFactory.methodElement("+", staticType);
fromNode.staticElement = staticElement;
fromNode.staticType = staticType;
@@ -207,7 +207,7 @@
void test_visitBooleanLiteral() {
BooleanLiteral fromNode = AstTestFactory.booleanLiteral(true);
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
BooleanLiteral toNode = AstTestFactory.booleanLiteral(true);
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -217,7 +217,7 @@
void test_visitCascadeExpression() {
CascadeExpression fromNode = AstTestFactory.cascadeExpression(
AstTestFactory.identifier3("a"), [AstTestFactory.identifier3("b")]);
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
CascadeExpression toNode = AstTestFactory.cascadeExpression(
AstTestFactory.identifier3("a"), [AstTestFactory.identifier3("b")]);
@@ -239,7 +239,7 @@
AstTestFactory.identifier3("c"),
AstTestFactory.identifier3("a"),
AstTestFactory.identifier3("b"));
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
ConditionalExpression toNode = AstTestFactory.conditionalExpression(
AstTestFactory.identifier3("c"),
@@ -283,7 +283,7 @@
void test_visitDoubleLiteral() {
DoubleLiteral fromNode = AstTestFactory.doubleLiteral(1.0);
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
DoubleLiteral toNode = AstTestFactory.doubleLiteral(1.0);
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -305,7 +305,7 @@
loopVariable: AstTestFactory.declaredIdentifier3('a'),
iterable: AstTestFactory.identifier3('b'));
- DartType typeB = interfaceType(ElementFactory.classElement2('B'));
+ DartType typeB = interfaceTypeStar(ElementFactory.classElement2('B'));
ForEachPartsWithDeclaration fromNode = createNode();
(fromNode.iterable as SimpleIdentifier).staticType = typeB;
@@ -321,8 +321,8 @@
identifier: AstTestFactory.identifier3('a'),
iterable: AstTestFactory.identifier3('b'));
- DartType typeA = interfaceType(ElementFactory.classElement2('A'));
- DartType typeB = interfaceType(ElementFactory.classElement2('B'));
+ DartType typeA = interfaceTypeStar(ElementFactory.classElement2('A'));
+ DartType typeB = interfaceTypeStar(ElementFactory.classElement2('B'));
ForEachPartsWithIdentifier fromNode = createNode();
fromNode.identifier.staticType = typeA;
@@ -341,7 +341,7 @@
iterable: AstTestFactory.identifier3('b')),
body: AstTestFactory.identifier3('c'));
- DartType typeC = interfaceType(ElementFactory.classElement2('C'));
+ DartType typeC = interfaceTypeStar(ElementFactory.classElement2('C'));
ForElement fromNode = createNode();
(fromNode.body as SimpleIdentifier).staticType = typeC;
@@ -359,8 +359,8 @@
condition: AstTestFactory.identifier3('b'),
updaters: [AstTestFactory.identifier3('c')]);
- DartType typeB = interfaceType(ElementFactory.classElement2('B'));
- DartType typeC = interfaceType(ElementFactory.classElement2('C'));
+ DartType typeB = interfaceTypeStar(ElementFactory.classElement2('B'));
+ DartType typeC = interfaceTypeStar(ElementFactory.classElement2('C'));
ForPartsWithDeclarations fromNode = createNode();
(fromNode.condition as SimpleIdentifier).staticType = typeB;
@@ -378,9 +378,9 @@
condition: AstTestFactory.identifier3('b'),
updaters: [AstTestFactory.identifier3('c')]);
- DartType typeA = interfaceType(ElementFactory.classElement2('A'));
- DartType typeB = interfaceType(ElementFactory.classElement2('B'));
- DartType typeC = interfaceType(ElementFactory.classElement2('C'));
+ DartType typeA = interfaceTypeStar(ElementFactory.classElement2('A'));
+ DartType typeB = interfaceTypeStar(ElementFactory.classElement2('B'));
+ DartType typeC = interfaceTypeStar(ElementFactory.classElement2('C'));
ForPartsWithExpression fromNode = createNode();
(fromNode.initialization as SimpleIdentifier).staticType = typeA;
@@ -402,9 +402,9 @@
body: AstTestFactory.expressionStatement(
AstTestFactory.identifier3('c')));
- DartType typeA = interfaceType(ElementFactory.classElement2('A'));
- DartType typeB = interfaceType(ElementFactory.classElement2('B'));
- DartType typeC = interfaceType(ElementFactory.classElement2('C'));
+ DartType typeA = interfaceTypeStar(ElementFactory.classElement2('A'));
+ DartType typeB = interfaceTypeStar(ElementFactory.classElement2('B'));
+ DartType typeC = interfaceTypeStar(ElementFactory.classElement2('C'));
ForStatement fromNode = createNode();
ForEachPartsWithIdentifier fromForLoopParts = fromNode.forLoopParts;
@@ -430,9 +430,9 @@
AstTestFactory.formalParameterList(),
AstTestFactory.emptyFunctionBody());
MethodElement element = ElementFactory.methodElement(
- "m", interfaceType(ElementFactory.classElement2('C')));
+ "m", interfaceTypeStar(ElementFactory.classElement2('C')));
fromNode.declaredElement = element;
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
FunctionExpression toNode = AstTestFactory.functionExpression2(
AstTestFactory.formalParameterList(),
@@ -447,7 +447,7 @@
AstTestFactory.functionExpressionInvocation(
AstTestFactory.identifier3("f"));
MethodElement staticElement = ElementFactory.methodElement(
- "m", interfaceType(ElementFactory.classElement2('C')));
+ "m", interfaceTypeStar(ElementFactory.classElement2('C')));
fromNode.staticElement = staticElement;
FunctionExpressionInvocation toNode =
AstTestFactory.functionExpressionInvocation(
@@ -469,9 +469,9 @@
thenElement: AstTestFactory.identifier3('b'),
elseElement: AstTestFactory.identifier3('c'));
- DartType typeA = interfaceType(ElementFactory.classElement2('A'));
- DartType typeB = interfaceType(ElementFactory.classElement2('B'));
- DartType typeC = interfaceType(ElementFactory.classElement2('C'));
+ DartType typeA = interfaceTypeStar(ElementFactory.classElement2('A'));
+ DartType typeB = interfaceTypeStar(ElementFactory.classElement2('B'));
+ DartType typeC = interfaceTypeStar(ElementFactory.classElement2('C'));
IfElement fromNode = createNode();
(fromNode.condition as SimpleIdentifier).staticType = typeA;
@@ -499,11 +499,11 @@
IndexExpression fromNode = AstTestFactory.indexExpression(
AstTestFactory.identifier3("a"), AstTestFactory.integer(0));
MethodElement staticElement = ElementFactory.methodElement(
- "m", interfaceType(ElementFactory.classElement2('C')));
+ "m", interfaceTypeStar(ElementFactory.classElement2('C')));
AuxiliaryElements auxiliaryElements = new AuxiliaryElements(staticElement);
fromNode.auxiliaryElements = auxiliaryElements;
fromNode.staticElement = staticElement;
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
IndexExpression toNode = AstTestFactory.indexExpression(
AstTestFactory.identifier3("a"), AstTestFactory.integer(0));
@@ -520,7 +520,7 @@
ConstructorElement staticElement = ElementFactory.constructorElement2(
ElementFactory.classElement2("C"), null);
fromNode.staticElement = staticElement;
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
InstanceCreationExpression toNode =
AstTestFactory.instanceCreationExpression2(
@@ -532,7 +532,7 @@
void test_visitIntegerLiteral() {
IntegerLiteral fromNode = AstTestFactory.integer(2);
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
IntegerLiteral toNode = AstTestFactory.integer(2);
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -542,7 +542,7 @@
void test_visitIsExpression() {
IsExpression fromNode = AstTestFactory.isExpression(
AstTestFactory.identifier3("x"), false, AstTestFactory.typeName4("A"));
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
IsExpression toNode = AstTestFactory.isExpression(
AstTestFactory.identifier3("x"), false, AstTestFactory.typeName4("A"));
@@ -553,7 +553,7 @@
void test_visitLibraryIdentifier() {
LibraryIdentifier fromNode =
AstTestFactory.libraryIdentifier([AstTestFactory.identifier3("lib")]);
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
LibraryIdentifier toNode =
AstTestFactory.libraryIdentifier([AstTestFactory.identifier3("lib")]);
@@ -569,9 +569,9 @@
[AstTestFactory.identifier3('b')],
null);
- DartType typeA = interfaceType(ElementFactory.classElement2('A'));
- DartType typeB = interfaceType(ElementFactory.classElement2('B'));
- DartType typeC = interfaceType(ElementFactory.classElement2('C'));
+ DartType typeA = interfaceTypeStar(ElementFactory.classElement2('A'));
+ DartType typeB = interfaceTypeStar(ElementFactory.classElement2('B'));
+ DartType typeC = interfaceTypeStar(ElementFactory.classElement2('C'));
ListLiteral fromNode = createNode();
(fromNode.typeArguments.arguments[0] as TypeName).type = typeA;
@@ -587,7 +587,7 @@
void test_visitMapLiteral() {
SetOrMapLiteral fromNode = AstTestFactory.setOrMapLiteral(null, null);
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
SetOrMapLiteral toNode = AstTestFactory.setOrMapLiteral(null, null);
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -608,7 +608,7 @@
void test_visitNamedExpression() {
NamedExpression fromNode =
AstTestFactory.namedExpression2("n", AstTestFactory.integer(0));
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
NamedExpression toNode =
AstTestFactory.namedExpression2("n", AstTestFactory.integer(0));
@@ -618,7 +618,7 @@
void test_visitNullLiteral() {
NullLiteral fromNode = AstTestFactory.nullLiteral();
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
NullLiteral toNode = AstTestFactory.nullLiteral();
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -628,7 +628,7 @@
void test_visitParenthesizedExpression() {
ParenthesizedExpression fromNode =
AstTestFactory.parenthesizedExpression(AstTestFactory.integer(0));
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
ParenthesizedExpression toNode =
AstTestFactory.parenthesizedExpression(AstTestFactory.integer(0));
@@ -638,8 +638,8 @@
void test_visitPartDirective() {
PartDirective fromNode = AstTestFactory.partDirective2("part.dart");
- LibraryElement element = new LibraryElementImpl.forNode(
- null, null, AstTestFactory.libraryIdentifier2(["lib"]), true);
+ LibraryElement element =
+ new LibraryElementImpl(null, null, 'lib', -1, 0, true);
fromNode.element = element;
PartDirective toNode = AstTestFactory.partDirective2("part.dart");
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -649,8 +649,8 @@
void test_visitPartOfDirective() {
PartOfDirective fromNode = AstTestFactory.partOfDirective(
AstTestFactory.libraryIdentifier2(["lib"]));
- LibraryElement element = new LibraryElementImpl.forNode(
- null, null, AstTestFactory.libraryIdentifier2(["lib"]), true);
+ LibraryElement element =
+ new LibraryElementImpl(null, null, 'lib', -1, 0, true);
fromNode.element = element;
PartOfDirective toNode = AstTestFactory.partOfDirective(
AstTestFactory.libraryIdentifier2(["lib"]));
@@ -663,9 +663,9 @@
PostfixExpression fromNode = AstTestFactory.postfixExpression(
AstTestFactory.identifier3(variableName), TokenType.PLUS_PLUS);
MethodElement staticElement = ElementFactory.methodElement(
- "+", interfaceType(ElementFactory.classElement2('C')));
+ "+", interfaceTypeStar(ElementFactory.classElement2('C')));
fromNode.staticElement = staticElement;
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
PostfixExpression toNode = AstTestFactory.postfixExpression(
AstTestFactory.identifier3(variableName), TokenType.PLUS_PLUS);
@@ -676,7 +676,7 @@
void test_visitPrefixedIdentifier() {
PrefixedIdentifier fromNode = AstTestFactory.identifier5("p", "f");
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
PrefixedIdentifier toNode = AstTestFactory.identifier5("p", "f");
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -686,9 +686,9 @@
void test_visitPrefixExpression() {
PrefixExpression fromNode = AstTestFactory.prefixExpression(
TokenType.PLUS_PLUS, AstTestFactory.identifier3("x"));
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
MethodElement staticElement = ElementFactory.methodElement(
- "+", interfaceType(ElementFactory.classElement2('C')));
+ "+", interfaceTypeStar(ElementFactory.classElement2('C')));
fromNode.staticElement = staticElement;
fromNode.staticType = staticType;
PrefixExpression toNode = AstTestFactory.prefixExpression(
@@ -701,7 +701,7 @@
void test_visitPropertyAccess() {
PropertyAccess fromNode =
AstTestFactory.propertyAccess2(AstTestFactory.identifier3("x"), "y");
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
PropertyAccess toNode =
AstTestFactory.propertyAccess2(AstTestFactory.identifier3("x"), "y");
@@ -723,7 +723,7 @@
void test_visitRethrowExpression() {
RethrowExpression fromNode = AstTestFactory.rethrowExpression();
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
RethrowExpression toNode = AstTestFactory.rethrowExpression();
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -736,10 +736,10 @@
[AstTestFactory.typeName4('A'), AstTestFactory.typeName4('B')]),
elements: [AstTestFactory.mapLiteralEntry3('c', 'd')]);
- DartType typeA = interfaceType(ElementFactory.classElement2('A'));
- DartType typeB = interfaceType(ElementFactory.classElement2('B'));
- DartType typeC = interfaceType(ElementFactory.classElement2('C'));
- DartType typeD = interfaceType(ElementFactory.classElement2('D'));
+ DartType typeA = interfaceTypeStar(ElementFactory.classElement2('A'));
+ DartType typeB = interfaceTypeStar(ElementFactory.classElement2('B'));
+ DartType typeC = interfaceTypeStar(ElementFactory.classElement2('C'));
+ DartType typeD = interfaceTypeStar(ElementFactory.classElement2('D'));
SetOrMapLiteral fromNode = createNode();
(fromNode.typeArguments.arguments[0] as TypeName).type = typeA;
@@ -763,8 +763,8 @@
AstTestFactory.typeArgumentList([AstTestFactory.typeName4('A')]),
elements: [AstTestFactory.identifier3('b')]);
- DartType typeA = interfaceType(ElementFactory.classElement2('A'));
- DartType typeB = interfaceType(ElementFactory.classElement2('B'));
+ DartType typeA = interfaceTypeStar(ElementFactory.classElement2('A'));
+ DartType typeB = interfaceTypeStar(ElementFactory.classElement2('B'));
SetOrMapLiteral fromNode = createNode();
(fromNode.typeArguments.arguments[0] as TypeName).type = typeA;
@@ -779,11 +779,11 @@
void test_visitSimpleIdentifier() {
SimpleIdentifier fromNode = AstTestFactory.identifier3("x");
MethodElement staticElement = ElementFactory.methodElement(
- "m", interfaceType(ElementFactory.classElement2('C')));
+ "m", interfaceTypeStar(ElementFactory.classElement2('C')));
AuxiliaryElements auxiliaryElements = new AuxiliaryElements(staticElement);
fromNode.auxiliaryElements = auxiliaryElements;
fromNode.staticElement = staticElement;
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
SimpleIdentifier toNode = AstTestFactory.identifier3("x");
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -794,7 +794,7 @@
void test_visitSimpleStringLiteral() {
SimpleStringLiteral fromNode = AstTestFactory.string2("abc");
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
SimpleStringLiteral toNode = AstTestFactory.string2("abc");
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -808,7 +808,7 @@
expression: astFactory.listLiteral(
null, null, null, [AstTestFactory.identifier3('a')], null));
- DartType typeA = interfaceType(ElementFactory.classElement2('A'));
+ DartType typeA = interfaceTypeStar(ElementFactory.classElement2('A'));
SpreadElement fromNode = createNode();
((fromNode.expression as ListLiteral).elements[0] as SimpleIdentifier)
@@ -825,7 +825,7 @@
void test_visitStringInterpolation() {
StringInterpolation fromNode =
AstTestFactory.string([AstTestFactory.interpolationString("a", "'a'")]);
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
StringInterpolation toNode =
AstTestFactory.string([AstTestFactory.interpolationString("a", "'a'")]);
@@ -847,7 +847,7 @@
void test_visitSuperExpression() {
SuperExpression fromNode = AstTestFactory.superExpression();
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
SuperExpression toNode = AstTestFactory.superExpression();
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -856,7 +856,7 @@
void test_visitSymbolLiteral() {
SymbolLiteral fromNode = AstTestFactory.symbolLiteral(["s"]);
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
SymbolLiteral toNode = AstTestFactory.symbolLiteral(["s"]);
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -865,7 +865,7 @@
void test_visitThisExpression() {
ThisExpression fromNode = AstTestFactory.thisExpression();
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
ThisExpression toNode = AstTestFactory.thisExpression();
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -874,7 +874,7 @@
void test_visitThrowExpression() {
ThrowExpression fromNode = AstTestFactory.throwExpression();
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
ThrowExpression toNode = AstTestFactory.throwExpression();
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -883,7 +883,7 @@
void test_visitTypeName() {
TypeName fromNode = AstTestFactory.typeName4("C");
- DartType type = interfaceType(ElementFactory.classElement2('C'));
+ DartType type = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.type = type;
TypeName toNode = AstTestFactory.typeName4("C");
ResolutionCopier.copyResolutionData(fromNode, toNode);
@@ -892,11 +892,11 @@
void _copyAndVerifyInvocation(
InvocationExpression fromNode, InvocationExpression toNode) {
- DartType staticType = interfaceType(ElementFactory.classElement2('C'));
+ DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticType = staticType;
DartType staticInvokeType =
- interfaceType(ElementFactory.classElement2('C'));
+ interfaceTypeStar(ElementFactory.classElement2('C'));
fromNode.staticInvokeType = staticInvokeType;
ResolutionCopier.copyResolutionData(fromNode, toNode);
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 9ef159d..49b073d 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -11,7 +11,6 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/testing/element_factory.dart';
import 'package:analyzer/src/generated/testing/test_type_provider.dart';
import 'package:test/test.dart';
@@ -55,12 +54,12 @@
void test_getAllSupertypes_interface() {
ClassElement classA = class_(name: 'A');
ClassElement classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
ClassElementImpl elementC = ElementFactory.classElement2("C");
InterfaceType typeObject = classA.supertype;
- InterfaceType typeA = interfaceType(classA);
- InterfaceType typeB = interfaceType(classB);
- InterfaceType typeC = interfaceType(elementC);
+ InterfaceType typeA = interfaceTypeStar(classA);
+ InterfaceType typeB = interfaceTypeStar(classB);
+ InterfaceType typeC = interfaceTypeStar(elementC);
elementC.interfaces = <InterfaceType>[typeB];
List<InterfaceType> supers = elementC.allSupertypes;
List<InterfaceType> types = new List<InterfaceType>();
@@ -74,12 +73,12 @@
void test_getAllSupertypes_mixins() {
ClassElement classA = class_(name: 'A');
ClassElement classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
var classC = ElementFactory.classElement2("C");
InterfaceType typeObject = classA.supertype;
- InterfaceType typeA = interfaceType(classA);
- InterfaceType typeB = interfaceType(classB);
- InterfaceType typeC = interfaceType(classC);
+ InterfaceType typeA = interfaceTypeStar(classA);
+ InterfaceType typeB = interfaceTypeStar(classB);
+ InterfaceType typeC = interfaceTypeStar(classC);
classC.mixins = <InterfaceType>[typeB];
List<InterfaceType> supers = classC.allSupertypes;
List<InterfaceType> types = new List<InterfaceType>();
@@ -93,8 +92,8 @@
void test_getAllSupertypes_recursive() {
var classA = class_(name: 'A');
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- classA.supertype = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ classA.supertype = interfaceTypeStar(classB);
List<InterfaceType> supers = classB.allSupertypes;
expect(supers, hasLength(1));
}
@@ -131,7 +130,7 @@
var classA = class_(name: 'A');
classA.fields = <FieldElement>[
ElementFactory.fieldElement(
- "f", false, false, true, interfaceType(classA))
+ "f", false, false, true, interfaceTypeStar(classA))
];
expect(classA.hasNonFinalField, isFalse);
}
@@ -140,7 +139,7 @@
var classA = class_(name: 'A');
classA.fields = <FieldElement>[
ElementFactory.fieldElement(
- "f", false, true, false, interfaceType(classA))
+ "f", false, true, false, interfaceTypeStar(classA))
];
expect(classA.hasNonFinalField, isFalse);
}
@@ -148,8 +147,8 @@
void test_hasNonFinalField_false_recursive() {
var classA = class_(name: 'A');
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- classA.supertype = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ classA.supertype = interfaceTypeStar(classB);
expect(classA.hasNonFinalField, isFalse);
}
@@ -157,7 +156,7 @@
var classA = class_(name: 'A');
classA.fields = <FieldElement>[
ElementFactory.fieldElement(
- "f", false, false, false, interfaceType(classA))
+ "f", false, false, false, interfaceTypeStar(classA))
];
expect(classA.hasNonFinalField, isTrue);
}
@@ -165,10 +164,10 @@
void test_hasNonFinalField_true_inherited() {
var classA = class_(name: 'A');
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
classA.fields = <FieldElement>[
ElementFactory.fieldElement(
- "f", false, false, false, interfaceType(classA))
+ "f", false, false, false, interfaceTypeStar(classA))
];
expect(classB.hasNonFinalField, isTrue);
}
@@ -280,7 +279,7 @@
ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
MethodElementImpl method = ElementFactory.methodElement(methodName, null);
method.isAbstract = true;
classB.methods = <MethodElement>[method];
@@ -304,7 +303,7 @@
ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
MethodElement method = ElementFactory.methodElement(methodName, null);
classB.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -328,7 +327,7 @@
inheritedMethod.isAbstract = true;
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
MethodElement method = ElementFactory.methodElement(methodName, null);
classB.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -349,7 +348,7 @@
ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classB.lookUpConcreteMethod(methodName, library),
@@ -394,7 +393,7 @@
ElementFactory.getterElement(getterName, false, null);
classA.accessors = <PropertyAccessorElement>[getter];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classB.lookUpGetter(getterName, library), same(getter));
@@ -418,8 +417,8 @@
LibraryElementImpl library = _newLibrary();
var classA = class_(name: 'A');
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- classA.supertype = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ classA.supertype = interfaceTypeStar(classB);
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classA.lookUpGetter("g", library), isNull);
@@ -453,7 +452,7 @@
ElementFactory.getterElement(getterName, false, null);
classA.accessors = <PropertyAccessorElement>[inheritedGetter];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classB.lookUpInheritedConcreteGetter(getterName, library),
@@ -478,8 +477,8 @@
LibraryElementImpl library = _newLibrary();
var classA = class_(name: 'A');
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- classA.supertype = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ classA.supertype = interfaceTypeStar(classB);
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classA.lookUpInheritedConcreteGetter("g", library), isNull);
@@ -513,7 +512,7 @@
ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
MethodElementImpl method = ElementFactory.methodElement(methodName, null);
method.isAbstract = true;
classB.methods = <MethodElement>[method];
@@ -537,7 +536,7 @@
ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
MethodElement method = ElementFactory.methodElement(methodName, null);
classB.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -562,7 +561,7 @@
inheritedMethod.isAbstract = true;
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
MethodElement method = ElementFactory.methodElement(methodName, null);
classB.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -588,13 +587,13 @@
ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
MethodElementImpl abstractMethod =
ElementFactory.methodElement(methodName, null);
abstractMethod.isAbstract = true;
classB.methods = <MethodElement>[abstractMethod];
ClassElementImpl classC =
- ElementFactory.classElement("C", interfaceType(classB));
+ ElementFactory.classElement("C", interfaceTypeStar(classB));
MethodElementImpl method = ElementFactory.methodElement(methodName, null);
classC.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -616,7 +615,7 @@
ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classB.lookUpInheritedConcreteMethod(methodName, library),
@@ -661,7 +660,7 @@
ElementFactory.setterElement(setterName, false, null);
classA.accessors = <PropertyAccessorElement>[setter];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classB.lookUpInheritedConcreteSetter(setterName, library),
@@ -686,8 +685,8 @@
LibraryElementImpl library = _newLibrary();
var classA = class_(name: 'A');
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- classA.supertype = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ classA.supertype = interfaceTypeStar(classB);
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classA.lookUpInheritedConcreteSetter("s", library), isNull);
@@ -721,7 +720,7 @@
ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
MethodElement method = ElementFactory.methodElement(methodName, null);
classB.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
@@ -743,7 +742,7 @@
ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classB.lookUpInheritedMethod(methodName, library),
@@ -778,7 +777,7 @@
MethodElement method = ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[method];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classB.lookUpMethod(methodName, library), same(method));
@@ -796,8 +795,8 @@
LibraryElementImpl library = _newLibrary();
var classA = class_(name: 'A');
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- classA.supertype = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ classA.supertype = interfaceTypeStar(classB);
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classA.lookUpMethod("m", library), isNull);
@@ -831,7 +830,7 @@
ElementFactory.setterElement(setterName, false, null);
classA.accessors = <PropertyAccessorElement>[setter];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classB.lookUpSetter(setterName, library), same(setter));
@@ -855,8 +854,8 @@
LibraryElementImpl library = _newLibrary();
var classA = class_(name: 'A');
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- classA.supertype = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ classA.supertype = interfaceTypeStar(classB);
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
expect(classA.lookUpSetter("s", library), isNull);
@@ -1263,8 +1262,7 @@
ClassElementImpl definingClass = ElementFactory.classElement2("C", ["E"]);
TypeParameterType parameterType =
typeParameterType(definingClass.typeParameters[0]);
- MethodElementImpl functionElement =
- new MethodElementImpl.forNode(AstTestFactory.identifier3("m"));
+ MethodElementImpl functionElement = new MethodElementImpl('m', -1);
String namedParameterName = "c";
functionElement.parameters = <ParameterElement>[
ElementFactory.requiredParameter2("a", parameterType),
@@ -1274,8 +1272,8 @@
functionElement.returnType = parameterType;
definingClass.methods = <MethodElement>[functionElement];
FunctionTypeImpl functionType = functionElement.type;
- InterfaceTypeImpl argumentType = new InterfaceTypeImpl(
- new ClassElementImpl.forNode(AstTestFactory.identifier3("D")));
+ InterfaceTypeImpl argumentType =
+ new InterfaceTypeImpl(new ClassElementImpl('D', -1));
FunctionType result = functionType
.substitute2(<DartType>[argumentType], <DartType>[parameterType]);
expect(result.returnType, argumentType);
@@ -1292,16 +1290,14 @@
@deprecated
void test_substitute2_notEqual() {
- DartType returnType = new InterfaceTypeImpl(
- new ClassElementImpl.forNode(AstTestFactory.identifier3("R")));
- DartType normalParameterType = new InterfaceTypeImpl(
- new ClassElementImpl.forNode(AstTestFactory.identifier3("A")));
- DartType optionalParameterType = new InterfaceTypeImpl(
- new ClassElementImpl.forNode(AstTestFactory.identifier3("B")));
- DartType namedParameterType = new InterfaceTypeImpl(
- new ClassElementImpl.forNode(AstTestFactory.identifier3("C")));
- FunctionElementImpl functionElement =
- new FunctionElementImpl.forNode(AstTestFactory.identifier3("f"));
+ DartType returnType = new InterfaceTypeImpl(new ClassElementImpl('R', -1));
+ DartType normalParameterType =
+ new InterfaceTypeImpl(new ClassElementImpl('A', -1));
+ DartType optionalParameterType =
+ new InterfaceTypeImpl(new ClassElementImpl('B', -1));
+ DartType namedParameterType =
+ new InterfaceTypeImpl(new ClassElementImpl('C', -1));
+ FunctionElementImpl functionElement = new FunctionElementImpl('f', -1);
String namedParameterName = "c";
functionElement.parameters = <ParameterElement>[
ElementFactory.requiredParameter2("a", normalParameterType),
@@ -1310,10 +1306,10 @@
];
functionElement.returnType = returnType;
FunctionTypeImpl functionType = functionElement.type;
- InterfaceTypeImpl argumentType = new InterfaceTypeImpl(
- new ClassElementImpl.forNode(AstTestFactory.identifier3("D")));
- TypeParameterTypeImpl parameterType = new TypeParameterTypeImpl(
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E")));
+ InterfaceTypeImpl argumentType =
+ new InterfaceTypeImpl(new ClassElementImpl('D', -1));
+ TypeParameterTypeImpl parameterType =
+ new TypeParameterTypeImpl(new TypeParameterElementImpl('E', -1));
FunctionType result = functionType
.substitute2(<DartType>[argumentType], <DartType>[parameterType]);
expect(result.returnType, returnType);
@@ -1367,14 +1363,14 @@
var AofC = A.instantiate(
typeArguments: [
- interfaceType(C),
+ interfaceTypeStar(C),
],
nullabilitySuffix: NullabilitySuffix.star,
);
B.interfaces = <InterfaceType>[AofC];
- InterfaceTypeImpl targetType = interfaceType(B);
+ InterfaceTypeImpl targetType = interfaceTypeStar(B);
InterfaceType result = targetType.asInstanceOf(A);
expect(result, AofC);
}
@@ -1401,14 +1397,14 @@
var C = class_(name: 'C');
InterfaceTypeImpl targetType = B.instantiate(
- typeArguments: [interfaceType(C)],
+ typeArguments: [interfaceTypeStar(C)],
nullabilitySuffix: NullabilitySuffix.star,
);
InterfaceType result = targetType.asInstanceOf(A);
expect(
result,
A.instantiate(
- typeArguments: [interfaceType(C)],
+ typeArguments: [interfaceTypeStar(C)],
nullabilitySuffix: NullabilitySuffix.star,
),
);
@@ -1471,7 +1467,7 @@
PropertyAccessorElement getterG =
ElementFactory.getterElement(getterName, false, null);
classA.accessors = <PropertyAccessorElement>[getterG];
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
expect(typeA.getGetter(getterName), same(getterG));
}
@@ -1490,7 +1486,7 @@
//
// A<I>
//
- InterfaceType I = interfaceType(class_(name: 'I'));
+ InterfaceType I = interfaceTypeStar(class_(name: 'I'));
InterfaceTypeImpl AofI = A.instantiate(
typeArguments: [I],
nullabilitySuffix: NullabilitySuffix.star,
@@ -1507,7 +1503,7 @@
// class A {}
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
expect(typeA.getGetter("g"), isNull);
}
@@ -1516,12 +1512,12 @@
// class C implements A, B
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
var classB = ElementFactory.classElement2("B");
- InterfaceType typeB = interfaceType(classB);
+ InterfaceType typeB = interfaceTypeStar(classB);
var classC = ElementFactory.classElement2("C");
classC.interfaces = <InterfaceType>[typeA, typeB];
- List<InterfaceType> interfaces = interfaceType(classC).interfaces;
+ List<InterfaceType> interfaces = interfaceTypeStar(classC).interfaces;
expect(interfaces, hasLength(2));
if (identical(interfaces[0], typeA)) {
expect(interfaces[1], same(typeB));
@@ -1552,8 +1548,8 @@
//
// B<I>
//
- InterfaceType typeI = interfaceType(class_(name: 'I'));
- InterfaceTypeImpl typeBI = interfaceType(B, typeArguments: [typeI]);
+ InterfaceType typeI = interfaceTypeStar(class_(name: 'I'));
+ InterfaceTypeImpl typeBI = interfaceTypeStar(B, typeArguments: [typeI]);
List<InterfaceType> interfaces = typeBI.interfaces;
expect(interfaces, hasLength(1));
@@ -1570,7 +1566,7 @@
String methodName = "m";
MethodElementImpl methodM = ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[methodM];
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
expect(typeA.getMethod(methodName), same(methodM));
}
@@ -1580,7 +1576,7 @@
// class B {}
//
var classA = ElementFactory.classElement2("A", ["E"]);
- InterfaceType typeB = interfaceType(class_(name: 'B'));
+ InterfaceType typeB = interfaceTypeStar(class_(name: 'B'));
String methodName = "m";
MethodElementImpl methodM =
ElementFactory.methodElement(methodName, typeB, []);
@@ -1588,7 +1584,7 @@
//
// A<I>
//
- InterfaceType typeI = interfaceType(class_(name: 'I'));
+ InterfaceType typeI = interfaceTypeStar(class_(name: 'I'));
InterfaceTypeImpl typeAI =
new InterfaceTypeImpl.explicit(classA, <DartType>[typeI]);
MethodElement method = typeAI.getMethod(methodName);
@@ -1611,7 +1607,7 @@
//
// A<I>
//
- InterfaceType typeI = interfaceType(class_(name: 'I'));
+ InterfaceType typeI = interfaceTypeStar(class_(name: 'I'));
InterfaceTypeImpl typeAI =
new InterfaceTypeImpl.explicit(A, <DartType>[typeI]);
MethodElement method = typeAI.getMethod(methodName);
@@ -1629,7 +1625,7 @@
// class A {}
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
expect(typeA.getMethod("m"), isNull);
}
@@ -1653,12 +1649,12 @@
// class C extends Object with A, B
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
var classB = ElementFactory.classElement2("B");
- InterfaceType typeB = interfaceType(classB);
+ InterfaceType typeB = interfaceTypeStar(classB);
var classC = ElementFactory.classElement2("C");
classC.mixins = <InterfaceType>[typeA, typeB];
- List<InterfaceType> interfaces = interfaceType(classC).mixins;
+ List<InterfaceType> interfaces = interfaceTypeStar(classC).mixins;
expect(interfaces, hasLength(2));
if (identical(interfaces[0], typeA)) {
expect(interfaces[1], same(typeB));
@@ -1681,7 +1677,7 @@
name: 'B',
typeParameters: [F],
mixins: [
- interfaceType(A, typeArguments: [
+ interfaceTypeStar(A, typeArguments: [
typeParameterType(F),
]),
],
@@ -1689,7 +1685,7 @@
//
// B<I>
//
- InterfaceType typeI = interfaceType(class_(name: 'I'));
+ InterfaceType typeI = interfaceTypeStar(class_(name: 'I'));
InterfaceTypeImpl typeBI =
new InterfaceTypeImpl.explicit(B, <DartType>[typeI]);
List<InterfaceType> interfaces = typeBI.mixins;
@@ -1708,7 +1704,7 @@
PropertyAccessorElement setterS =
ElementFactory.setterElement(setterName, false, null);
classA.accessors = <PropertyAccessorElement>[setterS];
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
expect(typeA.getSetter(setterName), same(setterS));
}
@@ -1726,7 +1722,7 @@
//
// A<I>
//
- InterfaceType typeI = interfaceType(class_(name: 'I'));
+ InterfaceType typeI = interfaceTypeStar(class_(name: 'I'));
InterfaceTypeImpl typeAI =
new InterfaceTypeImpl.explicit(A, <DartType>[typeI]);
PropertyAccessorElement setter = typeAI.getSetter(setterName);
@@ -1742,7 +1738,7 @@
// class A {}
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
expect(typeA.getSetter("s"), isNull);
}
@@ -1751,9 +1747,9 @@
// class B extends A
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
var classB = ElementFactory.classElement("B", typeA);
- InterfaceType typeB = interfaceType(classB);
+ InterfaceType typeB = interfaceTypeStar(classB);
expect(typeB.superclass, same(typeA));
}
@@ -1771,14 +1767,14 @@
var B = class_(
name: 'B',
typeParameters: [F],
- superType: interfaceType(A, typeArguments: [typeF]),
+ superType: interfaceTypeStar(A, typeArguments: [typeF]),
);
var classB = B;
//
// B<I>
//
- InterfaceType typeI = interfaceType(class_(name: 'I'));
+ InterfaceType typeI = interfaceTypeStar(class_(name: 'I'));
InterfaceTypeImpl typeBI =
new InterfaceTypeImpl.explicit(classB, <DartType>[typeI]);
InterfaceType superclass = typeBI.superclass;
@@ -1787,13 +1783,13 @@
}
void test_getTypeArguments_empty() {
- InterfaceType type = interfaceType(ElementFactory.classElement2('A'));
+ InterfaceType type = interfaceTypeStar(ElementFactory.classElement2('A'));
expect(type.typeArguments, hasLength(0));
}
void test_hashCode() {
ClassElement classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
expect(0 == typeA.hashCode, isFalse);
}
@@ -1806,7 +1802,7 @@
PropertyAccessorElement getterG =
ElementFactory.getterElement(getterName, false, null);
classA.accessors = <PropertyAccessorElement>[getterG];
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -1825,8 +1821,8 @@
ElementFactory.getterElement(getterName, false, null);
classA.accessors = <PropertyAccessorElement>[getterG];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- InterfaceType typeB = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ InterfaceType typeB = interfaceTypeStar(classB);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -1853,16 +1849,17 @@
getterName, false, typeProvider.dynamicType);
classM2.accessors = <PropertyAccessorElement>[getterM2g];
ClassElementImpl classC =
- ElementFactory.classElement('C', interfaceType(classB));
+ ElementFactory.classElement('C', interfaceTypeStar(classB));
classC.mixins = <InterfaceType>[
- interfaceType(classM1),
- interfaceType(classM2)
+ interfaceTypeStar(classM1),
+ interfaceTypeStar(classM2)
];
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElementImpl unit = library.definingCompilationUnit;
unit.types = <ClassElement>[classB, classM1, classM2, classC];
- expect(interfaceType(classC).lookUpGetter(getterName, library), getterM2g);
+ expect(
+ interfaceTypeStar(classC).lookUpGetter(getterName, library), getterM2g);
}
void test_lookUpGetter_recursive() {
@@ -1871,9 +1868,9 @@
// class B extends A {}
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
var classB = ElementFactory.classElement("B", typeA);
- classA.supertype = interfaceType(classB);
+ classA.supertype = interfaceTypeStar(classB);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -1886,7 +1883,7 @@
// class A {}
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -1902,7 +1899,7 @@
String methodName = "m";
MethodElementImpl methodM = ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[methodM];
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -1920,8 +1917,8 @@
MethodElementImpl methodM = ElementFactory.methodElement(methodName, null);
classA.methods = <MethodElement>[methodM];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- InterfaceType typeB = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ InterfaceType typeB = interfaceTypeStar(classB);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -1947,16 +1944,17 @@
ElementFactory.methodElement(methodName, null);
classM2.methods = <MethodElement>[methodM2m];
ClassElementImpl classC =
- ElementFactory.classElement('C', interfaceType(classB));
+ ElementFactory.classElement('C', interfaceTypeStar(classB));
classC.mixins = <InterfaceType>[
- interfaceType(classM1),
- interfaceType(classM2)
+ interfaceTypeStar(classM1),
+ interfaceTypeStar(classM2)
];
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElementImpl unit = library.definingCompilationUnit;
unit.types = <ClassElement>[classB, classM1, classM2, classC];
- expect(interfaceType(classC).lookUpMethod(methodName, library), methodM2m);
+ expect(
+ interfaceTypeStar(classC).lookUpMethod(methodName, library), methodM2m);
}
void test_lookUpMethod_parameterized() {
@@ -1976,7 +1974,7 @@
var B = class_(
name: 'B',
typeParameters: [F],
- superType: interfaceType(A, typeArguments: [
+ superType: interfaceTypeStar(A, typeArguments: [
typeParameterType(F),
]),
);
@@ -1987,7 +1985,7 @@
//
// B<I>
//
- InterfaceType typeI = interfaceType(class_(name: 'I'));
+ InterfaceType typeI = interfaceTypeStar(class_(name: 'I'));
InterfaceTypeImpl typeBI =
new InterfaceTypeImpl.explicit(B, <DartType>[typeI]);
MethodElement method = typeBI.lookUpMethod(methodName, library);
@@ -2005,9 +2003,9 @@
// class B extends A {}
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
var classB = ElementFactory.classElement("B", typeA);
- classA.supertype = interfaceType(classB);
+ classA.supertype = interfaceTypeStar(classB);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -2020,7 +2018,7 @@
// class A {}
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -2037,7 +2035,7 @@
PropertyAccessorElement setterS =
ElementFactory.setterElement(setterName, false, null);
classA.accessors = <PropertyAccessorElement>[setterS];
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -2056,8 +2054,8 @@
ElementFactory.setterElement(setterName, false, null);
classA.accessors = <PropertyAccessorElement>[setterS];
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- InterfaceType typeB = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ InterfaceType typeB = interfaceTypeStar(classB);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -2084,16 +2082,17 @@
setterName, false, typeProvider.dynamicType);
classM2.accessors = <PropertyAccessorElement>[setterM2g];
ClassElementImpl classC =
- ElementFactory.classElement('C', interfaceType(classB));
+ ElementFactory.classElement('C', interfaceTypeStar(classB));
classC.mixins = <InterfaceType>[
- interfaceType(classM1),
- interfaceType(classM2)
+ interfaceTypeStar(classM1),
+ interfaceTypeStar(classM2)
];
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElementImpl unit = library.definingCompilationUnit;
unit.types = <ClassElement>[classB, classM1, classM2, classC];
- expect(interfaceType(classC).lookUpGetter(setterName, library), setterM2g);
+ expect(
+ interfaceTypeStar(classC).lookUpGetter(setterName, library), setterM2g);
}
void test_lookUpSetter_recursive() {
@@ -2102,9 +2101,9 @@
// class B extends A {}
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
var classB = ElementFactory.classElement("B", typeA);
- classA.supertype = interfaceType(classB);
+ classA.supertype = interfaceTypeStar(classB);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -2117,7 +2116,7 @@
// class A {}
//
var classA = class_(name: 'A');
- InterfaceType typeA = interfaceType(classA);
+ InterfaceType typeA = interfaceTypeStar(classA);
LibraryElementImpl library =
ElementFactory.library(_analysisContext, "lib");
CompilationUnitElement unit = library.definingCompilationUnit;
@@ -2126,7 +2125,8 @@
}
void test_resolveToBound() {
- InterfaceTypeImpl type = interfaceType(ElementFactory.classElement2('A'));
+ InterfaceTypeImpl type =
+ interfaceTypeStar(ElementFactory.classElement2('A'));
// Returns this.
expect(type.resolveToBound(null), same(type));
@@ -2137,7 +2137,7 @@
try {
var classA = class_(name: 'A');
InterfaceTypeImpl type = new InterfaceTypeImpl(classA);
- InterfaceType argumentType = interfaceType(class_(name: 'B'));
+ InterfaceType argumentType = interfaceTypeStar(class_(name: 'B'));
type.substitute2(<DartType>[argumentType], <DartType>[]);
fail(
"Expected to encounter exception, argument and parameter type array lengths not equal.");
@@ -2152,14 +2152,14 @@
// implementation.
var classA = class_(name: 'A');
TypeParameterElementImpl parameterElement =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ new TypeParameterElementImpl('E', -1);
TypeParameterTypeImpl parameter =
new TypeParameterTypeImpl(parameterElement);
InterfaceTypeImpl type =
new InterfaceTypeImpl.explicit(classA, <DartType>[parameter]);
- InterfaceType argumentType = interfaceType(class_(name: 'B'));
- TypeParameterTypeImpl parameterType = new TypeParameterTypeImpl(
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("F")));
+ InterfaceType argumentType = interfaceTypeStar(class_(name: 'B'));
+ TypeParameterTypeImpl parameterType =
+ new TypeParameterTypeImpl(new TypeParameterElementImpl('F', -1));
InterfaceType result =
type.substitute2(<DartType>[argumentType], <DartType>[parameterType]);
expect(result.element, classA);
@@ -2171,23 +2171,14 @@
@reflectiveTest
class LibraryElementImplTest {
- void test_creation() {
- expect(
- new LibraryElementImpl.forNode(TestAnalysisContext(), null,
- AstTestFactory.libraryIdentifier2(["l"]), true),
- isNotNull);
- }
-
void test_getImportedLibraries() {
AnalysisContext context = TestAnalysisContext();
LibraryElementImpl library1 = ElementFactory.library(context, "l1");
LibraryElementImpl library2 = ElementFactory.library(context, "l2");
LibraryElementImpl library3 = ElementFactory.library(context, "l3");
LibraryElementImpl library4 = ElementFactory.library(context, "l4");
- PrefixElement prefixA =
- new PrefixElementImpl.forNode(AstTestFactory.identifier3("a"));
- PrefixElement prefixB =
- new PrefixElementImpl.forNode(AstTestFactory.identifier3("b"));
+ PrefixElement prefixA = new PrefixElementImpl('a', -1);
+ PrefixElement prefixB = new PrefixElementImpl('b', -1);
List<ImportElementImpl> imports = [
ElementFactory.importFor(library2, null),
ElementFactory.importFor(library2, prefixB),
@@ -2205,10 +2196,8 @@
void test_getPrefixes() {
AnalysisContext context = TestAnalysisContext();
LibraryElementImpl library = ElementFactory.library(context, "l1");
- PrefixElement prefixA =
- new PrefixElementImpl.forNode(AstTestFactory.identifier3("a"));
- PrefixElement prefixB =
- new PrefixElementImpl.forNode(AstTestFactory.identifier3("b"));
+ PrefixElement prefixA = new PrefixElementImpl('a', -1);
+ PrefixElement prefixB = new PrefixElementImpl('b', -1);
List<ImportElementImpl> imports = [
ElementFactory.importFor(ElementFactory.library(context, "l2"), null),
ElementFactory.importFor(ElementFactory.library(context, "l3"), null),
@@ -2242,8 +2231,8 @@
void test_setImports() {
AnalysisContext context = TestAnalysisContext();
- LibraryElementImpl library = new LibraryElementImpl.forNode(
- context, null, AstTestFactory.libraryIdentifier2(["l1"]), true);
+ LibraryElementImpl library =
+ new LibraryElementImpl(context, null, 'l1', -1, 0, true);
List<ImportElementImpl> expectedImports = [
ElementFactory.importFor(ElementFactory.library(context, "l2"), null),
ElementFactory.importFor(ElementFactory.library(context, "l3"), null)
@@ -2284,33 +2273,28 @@
@reflectiveTest
class TypeParameterTypeImplTest extends AbstractTypeTest {
void test_creation() {
- expect(
- new TypeParameterTypeImpl(new TypeParameterElementImpl.forNode(
- AstTestFactory.identifier3("E"))),
+ expect(new TypeParameterTypeImpl(new TypeParameterElementImpl('E', -1)),
isNotNull);
}
void test_getElement() {
- TypeParameterElementImpl element =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ TypeParameterElementImpl element = new TypeParameterElementImpl('E', -1);
TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
expect(type.element, element);
}
void test_resolveToBound_bound() {
ClassElementImpl classS = class_(name: 'A');
- TypeParameterElementImpl element =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
- element.bound = interfaceType(classS);
+ TypeParameterElementImpl element = new TypeParameterElementImpl('E', -1);
+ element.bound = interfaceTypeStar(classS);
TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
- expect(type.resolveToBound(null), interfaceType(classS));
+ expect(type.resolveToBound(null), interfaceTypeStar(classS));
}
void test_resolveToBound_bound_nullableInner() {
ClassElementImpl classS = class_(name: 'A');
- TypeParameterElementImpl element =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
- element.bound = (interfaceType(classS) as TypeImpl)
+ TypeParameterElementImpl element = new TypeParameterElementImpl('E', -1);
+ element.bound = (interfaceTypeStar(classS) as TypeImpl)
.withNullability(NullabilitySuffix.question);
TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
expect(type.resolveToBound(null), same(element.bound));
@@ -2318,9 +2302,8 @@
void test_resolveToBound_bound_nullableInnerOuter() {
ClassElementImpl classS = class_(name: 'A');
- TypeParameterElementImpl element =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
- element.bound = (interfaceType(classS) as TypeImpl)
+ TypeParameterElementImpl element = new TypeParameterElementImpl('E', -1);
+ element.bound = (interfaceTypeStar(classS) as TypeImpl)
.withNullability(NullabilitySuffix.question);
TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
.withNullability(NullabilitySuffix.question);
@@ -2329,36 +2312,33 @@
void test_resolveToBound_bound_nullableInnerStarOuter() {
ClassElementImpl classS = class_(name: 'A');
- TypeParameterElementImpl element =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
- element.bound = (interfaceType(classS) as TypeImpl)
+ TypeParameterElementImpl element = new TypeParameterElementImpl('E', -1);
+ element.bound = (interfaceTypeStar(classS) as TypeImpl)
.withNullability(NullabilitySuffix.star);
TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
.withNullability(NullabilitySuffix.question);
expect(
type.resolveToBound(null),
- equals((interfaceType(classS) as TypeImpl)
+ equals((interfaceTypeStar(classS) as TypeImpl)
.withNullability(NullabilitySuffix.question)));
}
void test_resolveToBound_bound_nullableOuter() {
ClassElementImpl classS = class_(name: 'A');
- TypeParameterElementImpl element =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
- element.bound = interfaceType(classS);
+ TypeParameterElementImpl element = new TypeParameterElementImpl('E', -1);
+ element.bound = interfaceTypeStar(classS);
TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
.withNullability(NullabilitySuffix.question);
expect(
type.resolveToBound(null),
- equals((interfaceType(classS) as TypeImpl)
+ equals((interfaceTypeStar(classS) as TypeImpl)
.withNullability(NullabilitySuffix.question)));
}
void test_resolveToBound_bound_starInner() {
ClassElementImpl classS = class_(name: 'A');
- TypeParameterElementImpl element =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
- element.bound = (interfaceType(classS) as TypeImpl)
+ TypeParameterElementImpl element = new TypeParameterElementImpl('E', -1);
+ element.bound = (interfaceTypeStar(classS) as TypeImpl)
.withNullability(NullabilitySuffix.star);
TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
expect(type.resolveToBound(null), same(element.bound));
@@ -2366,9 +2346,8 @@
void test_resolveToBound_bound_starInnerNullableOuter() {
ClassElementImpl classS = class_(name: 'A');
- TypeParameterElementImpl element =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
- element.bound = (interfaceType(classS) as TypeImpl)
+ TypeParameterElementImpl element = new TypeParameterElementImpl('E', -1);
+ element.bound = (interfaceTypeStar(classS) as TypeImpl)
.withNullability(NullabilitySuffix.question);
TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
.withNullability(NullabilitySuffix.star);
@@ -2377,33 +2356,30 @@
void test_resolveToBound_bound_starOuter() {
ClassElementImpl classS = class_(name: 'A');
- TypeParameterElementImpl element =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
- element.bound = interfaceType(classS);
+ TypeParameterElementImpl element = new TypeParameterElementImpl('E', -1);
+ element.bound = interfaceTypeStar(classS);
TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
.withNullability(NullabilitySuffix.star);
expect(
type.resolveToBound(null),
- (interfaceType(classS) as TypeImpl)
+ (interfaceTypeStar(classS) as TypeImpl)
.withNullability(NullabilitySuffix.star));
}
void test_resolveToBound_nestedBound() {
ClassElementImpl classS = class_(name: 'A');
- TypeParameterElementImpl elementE =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
- elementE.bound = interfaceType(classS);
+ TypeParameterElementImpl elementE = new TypeParameterElementImpl('E', -1);
+ elementE.bound = interfaceTypeStar(classS);
TypeParameterTypeImpl typeE = new TypeParameterTypeImpl(elementE);
- TypeParameterElementImpl elementF =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("F"));
+ TypeParameterElementImpl elementF = new TypeParameterElementImpl('F', -1);
elementF.bound = typeE;
TypeParameterTypeImpl typeF = new TypeParameterTypeImpl(elementE);
- expect(typeF.resolveToBound(null), interfaceType(classS));
+ expect(typeF.resolveToBound(null), interfaceTypeStar(classS));
}
void test_resolveToBound_unbound() {
- TypeParameterTypeImpl type = new TypeParameterTypeImpl(
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E")));
+ TypeParameterTypeImpl type =
+ new TypeParameterTypeImpl(new TypeParameterElementImpl('E', -1));
// Returns whatever type is passed to resolveToBound().
expect(type.resolveToBound(VoidTypeImpl.instance),
same(VoidTypeImpl.instance));
@@ -2411,11 +2387,10 @@
@deprecated
void test_substitute_equal() {
- TypeParameterElementImpl element =
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ TypeParameterElementImpl element = new TypeParameterElementImpl('E', -1);
TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
- InterfaceTypeImpl argument = new InterfaceTypeImpl(
- new ClassElementImpl.forNode(AstTestFactory.identifier3("A")));
+ InterfaceTypeImpl argument =
+ new InterfaceTypeImpl(new ClassElementImpl('A', -1));
TypeParameterTypeImpl parameter = new TypeParameterTypeImpl(element);
expect(type.substitute2(<DartType>[argument], <DartType>[parameter]),
same(argument));
@@ -2423,12 +2398,12 @@
@deprecated
void test_substitute_notEqual() {
- TypeParameterTypeImpl type = new TypeParameterTypeImpl(
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E")));
- InterfaceTypeImpl argument = new InterfaceTypeImpl(
- new ClassElementImpl.forNode(AstTestFactory.identifier3("A")));
- TypeParameterTypeImpl parameter = new TypeParameterTypeImpl(
- new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("F")));
+ TypeParameterTypeImpl type =
+ new TypeParameterTypeImpl(new TypeParameterElementImpl('E', -1));
+ InterfaceTypeImpl argument =
+ new InterfaceTypeImpl(new ClassElementImpl('A', -1));
+ TypeParameterTypeImpl parameter =
+ new TypeParameterTypeImpl(new TypeParameterElementImpl('F', -1));
expect(type.substitute2(<DartType>[argument], <DartType>[parameter]),
same(type));
}
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
index 9d113c6..aa2e228 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager3_test.dart
@@ -2,10 +2,12 @@
// 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:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:meta/meta.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -15,21 +17,12 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(InheritanceManager3Test);
+ defineReflectiveTests(InheritanceManager3WithNnbdTest);
});
}
@reflectiveTest
-class InheritanceManager3Test extends DriverResolutionTest {
- InheritanceManager3 manager;
-
- @override
- Future<void> resolveTestFile() async {
- await super.resolveTestFile();
- manager = new InheritanceManager3(
- result.unit.declaredElement.context.typeSystem,
- );
- }
-
+class InheritanceManager3Test extends _InheritanceManager3Base {
test_getInherited_closestSuper() async {
await resolveTestCode('''
class A {
@@ -1048,12 +1041,90 @@
expected: 'A.foo: void Function()',
);
}
+}
+
+@reflectiveTest
+class InheritanceManager3WithNnbdTest extends _InheritanceManager3Base {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = FeatureSet.forTesting(
+ sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ test_getMember_optOut_inheritsOptIn() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo(int a, int? b) => 0;
+}
+''');
+ await resolveTestCode('''
+// @dart = 2.6
+import 'a.dart';
+class B extends A {
+ int bar(int a) => 0;
+}
+''');
+ _assertGetMember(
+ className: 'B',
+ name: 'foo',
+ expected: 'A.foo: int Function(int, int?)',
+ );
+ _assertGetMember(
+ className: 'B',
+ name: 'bar',
+ expected: 'B.bar: int* Function(int*)*',
+ );
+ }
+
+ test_getMember_optOut_passOptIn() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo(int a, int? b) => 0;
+}
+''');
+ newFile('/test/lib/b.dart', content: r'''
+// @dart = 2.6
+import 'a.dart';
+class B extends A {
+ int bar(int a) => 0;
+}
+''');
+ await resolveTestCode('''
+import 'b.dart';
+class C extends B {}
+''');
+ _assertGetMember(
+ className: 'C',
+ name: 'foo',
+ expected: 'A.foo: int Function(int, int?)',
+ );
+ _assertGetMember(
+ className: 'C',
+ name: 'bar',
+ expected: 'B.bar: int* Function(int*)*',
+ );
+ }
+}
+
+class _InheritanceManager3Base extends DriverResolutionTest {
+ InheritanceManager3 manager;
+
+ @override
+ Future<void> resolveTestFile() async {
+ await super.resolveTestFile();
+ manager = new InheritanceManager3();
+ }
void _assertExecutable(ExecutableElement element, String expected) {
if (expected != null) {
- var type = element.type;
var enclosingElement = element.enclosingElement;
- var actual = '${enclosingElement.name}.${element.name}: $type';
+
+ var type = element.type;
+ var typeStr = typeString(type);
+
+ var actual = '${enclosingElement.name}.${element.name}: $typeStr';
expect(actual, expected);
} else {
expect(element, isNull);
diff --git a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
index d9f6283..5132ab1 100644
--- a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
+++ b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
@@ -40,12 +40,12 @@
ClassElementImpl classC = ElementFactory.classElement2("C");
ClassElementImpl classD = ElementFactory.classElement2("D");
ClassElementImpl classE = ElementFactory.classElement2("E");
- classB.interfaces = <InterfaceType>[interfaceType(classA)];
- classC.interfaces = <InterfaceType>[interfaceType(classA)];
- classD.interfaces = <InterfaceType>[interfaceType(classC)];
+ classB.interfaces = <InterfaceType>[interfaceTypeStar(classA)];
+ classC.interfaces = <InterfaceType>[interfaceTypeStar(classA)];
+ classD.interfaces = <InterfaceType>[interfaceTypeStar(classC)];
classE.interfaces = <InterfaceType>[
- interfaceType(classB),
- interfaceType(classD)
+ interfaceTypeStar(classB),
+ interfaceTypeStar(classD)
];
// assertion: even though the longest path to Object for typeB is 2, and
// typeE implements typeB, the longest path for typeE is 4 since it also
@@ -68,14 +68,14 @@
//
ClassElement classA = ElementFactory.classElement2("A");
ClassElement classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
ClassElement classC =
- ElementFactory.classElement("C", interfaceType(classA));
+ ElementFactory.classElement("C", interfaceTypeStar(classA));
ClassElement classD =
- ElementFactory.classElement("D", interfaceType(classC));
+ ElementFactory.classElement("D", interfaceTypeStar(classC));
ClassElementImpl classE =
- ElementFactory.classElement("E", interfaceType(classB));
- classE.interfaces = <InterfaceType>[interfaceType(classD)];
+ ElementFactory.classElement("E", interfaceTypeStar(classB));
+ classE.interfaces = <InterfaceType>[interfaceTypeStar(classD)];
// assertion: even though the longest path to Object for typeB is 2, and
// typeE extends typeB, the longest path for typeE is 4 since it also
// implements typeD
@@ -90,8 +90,8 @@
void test_computeLongestInheritancePathToObject_recursion() {
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB =
- ElementFactory.classElement("B", interfaceType(classA));
- classA.supertype = interfaceType(classB);
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
+ classA.supertype = interfaceTypeStar(classB);
expect(_longestPathToObject(classA), 2);
}
@@ -108,8 +108,8 @@
ClassElementImpl classA = ElementFactory.classElement2("A");
ClassElementImpl classB = ElementFactory.classElement2("B");
ClassElementImpl classC = ElementFactory.classElement2("C");
- classB.interfaces = <InterfaceType>[interfaceType(classA)];
- classC.interfaces = <InterfaceType>[interfaceType(classB)];
+ classB.interfaces = <InterfaceType>[interfaceTypeStar(classA)];
+ classC.interfaces = <InterfaceType>[interfaceTypeStar(classB)];
expect(_longestPathToObject(classA), 1);
expect(_longestPathToObject(classB), 2);
expect(_longestPathToObject(classC), 3);
@@ -127,9 +127,9 @@
//
ClassElement classA = ElementFactory.classElement2("A");
ClassElement classB =
- ElementFactory.classElement("B", interfaceType(classA));
+ ElementFactory.classElement("B", interfaceTypeStar(classA));
ClassElement classC =
- ElementFactory.classElement("C", interfaceType(classB));
+ ElementFactory.classElement("C", interfaceTypeStar(classB));
expect(_longestPathToObject(classA), 1);
expect(_longestPathToObject(classB), 2);
expect(_longestPathToObject(classC), 3);
@@ -181,7 +181,7 @@
// B<D>
expect(
_superInterfaces(
- InstantiatedClass(classB, [interfaceType(classD)]),
+ InstantiatedClass(classB, [interfaceTypeStar(classD)]),
),
unorderedEquals([instObject, instA]),
);
@@ -189,12 +189,12 @@
// C<D>
expect(
_superInterfaces(
- InstantiatedClass(classC, [interfaceType(classD)]),
+ InstantiatedClass(classC, [interfaceTypeStar(classD)]),
),
unorderedEquals([
instObject,
instA,
- InstantiatedClass(classB, [interfaceType(classD)]),
+ InstantiatedClass(classB, [interfaceTypeStar(classD)]),
]),
);
}
@@ -242,7 +242,7 @@
// B<D>
expect(
_superInterfaces(
- InstantiatedClass(classB, [interfaceType(classD)]),
+ InstantiatedClass(classB, [interfaceTypeStar(classD)]),
),
unorderedEquals([instObject, instA]),
);
@@ -250,12 +250,12 @@
// C<D>
expect(
_superInterfaces(
- InstantiatedClass(classC, [interfaceType(classD)]),
+ InstantiatedClass(classC, [interfaceTypeStar(classD)]),
),
unorderedEquals([
instObject,
instA,
- InstantiatedClass(classB, [interfaceType(classD)]),
+ InstantiatedClass(classB, [interfaceTypeStar(classD)]),
]),
);
}
@@ -275,7 +275,7 @@
var classC = ElementFactory.classElement3(name: 'C');
var instC = InstantiatedClass(classC, const []);
- var mixinM = ElementFactory.mixinElement(
+ var mixinM = mixin_(
name: 'M',
constraints: [
instB.withNullabilitySuffixNone,
@@ -293,7 +293,7 @@
void test_computeSuperinterfaceSet_mixin_constraints_object() {
var instObject = InstantiatedClass.of(typeProvider.objectType);
- var mixinM = ElementFactory.mixinElement(name: 'M');
+ var mixinM = mixin_(name: 'M');
var instM = InstantiatedClass(mixinM, const []);
expect(
@@ -317,7 +317,7 @@
var classC = ElementFactory.classElement3(name: 'C');
var instC = InstantiatedClass(classC, const []);
- var mixinM = ElementFactory.mixinElement(
+ var mixinM = mixin_(
name: 'M',
interfaces: [
instB.withNullabilitySuffixNone,
diff --git a/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
index b0b9091..15b1c8c 100644
--- a/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
+++ b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
import 'package:analyzer/src/dart/element/type.dart';
@@ -21,7 +20,7 @@
}
@reflectiveTest
-class NullabilityEliminatorTest with ElementsTypesMixin, TypeProviderTypes {
+class NullabilityEliminatorTest with ElementsTypesMixin {
@override
TypeProvider typeProvider;
@@ -41,17 +40,17 @@
test_functionType() {
_verify(
- functionTypeNone(returnType: voidType),
- functionTypeStar(returnType: voidType),
+ functionTypeNone(returnType: voidNone),
+ functionTypeStar(returnType: voidNone),
);
_verify(
- functionTypeQuestion(returnType: voidType),
- functionTypeStar(returnType: voidType),
+ functionTypeQuestion(returnType: voidNone),
+ functionTypeStar(returnType: voidNone),
);
_verifySame(
- functionTypeStar(returnType: voidType),
+ functionTypeStar(returnType: voidNone),
);
}
@@ -61,13 +60,13 @@
parameters: [
requiredParameter(type: intNone),
],
- returnType: voidType,
+ returnType: voidNone,
),
functionTypeStar(
parameters: [
requiredParameter(type: intStar),
],
- returnType: voidType,
+ returnType: voidNone,
),
);
@@ -76,13 +75,13 @@
parameters: [
requiredParameter(type: intQuestion),
],
- returnType: voidType,
+ returnType: voidNone,
),
functionTypeStar(
parameters: [
requiredParameter(type: intStar),
],
- returnType: voidType,
+ returnType: voidNone,
),
);
@@ -91,7 +90,7 @@
parameters: [
requiredParameter(type: intStar),
],
- returnType: voidType,
+ returnType: voidNone,
),
);
}
@@ -264,53 +263,3 @@
expect(_typeToString(result), expectedStr);
}
}
-
-mixin TypeProviderTypes {
- DynamicTypeImpl get dynamicType => typeProvider.dynamicType;
-
- InterfaceType get intNone {
- return typeProvider.intElement.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceType get intQuestion {
- return typeProvider.intElement.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType get intStar {
- return typeProvider.intElement.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
- TypeProvider get typeProvider;
-
- VoidTypeImpl get voidType => typeProvider.voidType;
-
- InterfaceType listNone(DartType type) {
- return typeProvider.listElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceType listQuestion(DartType type) {
- return typeProvider.listElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType listStar(DartType type) {
- return typeProvider.listElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-}
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index 354f34e..d3999f4 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -277,47 +277,12 @@
if (expectedString != null) {
var typeStr = _typeStr(type);
- var typeParameterCollector = _TypeParameterCollector();
- DartTypeVisitor.visit(type, typeParameterCollector);
- for (var typeParameter in typeParameterCollector.typeParameters) {
- if (typeParameter is TypeParameterMember) {
- var base = typeParameter.declaration;
- var baseBound = base.bound as TypeImpl;
- if (baseBound != null) {
- var baseBoundStr = baseBound.toString(withNullability: true);
- typeStr += ', ${typeParameter.name} extends ' + baseBoundStr;
- }
-
- var bound = typeParameter.bound as TypeImpl;
- var boundStr = bound.toString(withNullability: true);
- typeStr += ', ${typeParameter.name} & ' + boundStr;
- } else {
- var bound = typeParameter.bound as TypeImpl;
- if (bound != null) {
- var boundStr = bound.toString(withNullability: true);
- typeStr += ', ${typeParameter.name} extends ' + boundStr;
- }
- }
- }
+ typeStr += _typeParametersStr(type);
expect(typeStr, expectedString);
}
}
- InterfaceType comparableQuestion(DartType type) {
- return comparableElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType comparableStar(DartType type) {
- return comparableElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
void isNotSubtype(
DartType T0,
DartType T1, {
@@ -365,42 +330,6 @@
expect(typeSystem.isSubtypeOf(T0, T1), isTrue);
}
- InterfaceType iterableStar(DartType type) {
- return typeProvider.iterableElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
- InterfaceType listNone(DartType type) {
- return typeProvider.listElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceType listQuestion(DartType type) {
- return typeProvider.listElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType listStar(DartType type) {
- return typeProvider.listElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
- TypeParameterMember promoteTypeParameter(
- TypeParameterElement element,
- DartType bound,
- ) {
- assert(element is! TypeParameterMember);
- return TypeParameterMember(element, null, bound);
- }
-
@override
void setUp() {
super.setUp();
@@ -2846,37 +2775,7 @@
);
}
- test_interfaceType_covariant_01() {
- var T = typeParameter('T', variance: Variance.covariant);
- var A = class_(name: 'A', typeParameters: [T]);
-
- var A_num = A.instantiate(
- typeArguments: [numNone],
- nullabilitySuffix: NullabilitySuffix.none,
- );
-
- var A_int = A.instantiate(
- typeArguments: [intNone],
- nullabilitySuffix: NullabilitySuffix.none,
- );
-
- isSubtype(A_int, A_num, strT0: "A<int>", strT1: "A<num>");
- isNotSubtype(A_num, A_int, strT0: "A<num>", strT1: "A<int>");
- }
-
- test_interfaceType_covariant_02() {
- var T = typeParameter('T', variance: Variance.covariant);
- var A = class_(name: 'A', typeParameters: [T]);
-
- var A_num = A.instantiate(
- typeArguments: [numNone],
- nullabilitySuffix: NullabilitySuffix.none,
- );
-
- isSubtype(A_num, A_num, strT0: "A<num>", strT1: "A<num>");
- }
-
- test_interfaceType_contravariant_01() {
+ test_interfaceType_contravariant() {
var T = typeParameter('T', variance: Variance.contravariant);
var A = class_(name: 'A', typeParameters: [T]);
@@ -2891,11 +2790,12 @@
);
isSubtype(A_num, A_int, strT0: "A<num>", strT1: "A<int>");
+ isSubtype(A_num, A_num, strT0: "A<num>", strT1: "A<num>");
isNotSubtype(A_int, A_num, strT0: "A<int>", strT1: "A<num>");
}
- test_interfaceType_contravariant_02() {
- var T = typeParameter('T', variance: Variance.contravariant);
+ test_interfaceType_covariant() {
+ var T = typeParameter('T', variance: Variance.covariant);
var A = class_(name: 'A', typeParameters: [T]);
var A_num = A.instantiate(
@@ -2903,7 +2803,14 @@
nullabilitySuffix: NullabilitySuffix.none,
);
+ var A_int = A.instantiate(
+ typeArguments: [intNone],
+ nullabilitySuffix: NullabilitySuffix.none,
+ );
+
+ isSubtype(A_int, A_num, strT0: "A<int>", strT1: "A<num>");
isSubtype(A_num, A_num, strT0: "A<num>", strT1: "A<num>");
+ isNotSubtype(A_num, A_int, strT0: "A<num>", strT1: "A<int>");
}
test_interfaceType_invariant() {
@@ -5968,6 +5875,34 @@
return type;
}
+ String _typeParametersStr(TypeImpl type) {
+ var typeStr = '';
+
+ var typeParameterCollector = _TypeParameterCollector();
+ DartTypeVisitor.visit(type, typeParameterCollector);
+ for (var typeParameter in typeParameterCollector.typeParameters) {
+ if (typeParameter is TypeParameterMember) {
+ var base = typeParameter.declaration;
+ var baseBound = base.bound as TypeImpl;
+ if (baseBound != null) {
+ var baseBoundStr = baseBound.toString(withNullability: true);
+ typeStr += ', ${typeParameter.name} extends ' + baseBoundStr;
+ }
+
+ var bound = typeParameter.bound as TypeImpl;
+ var boundStr = bound.toString(withNullability: true);
+ typeStr += ', ${typeParameter.name} & ' + boundStr;
+ } else {
+ var bound = typeParameter.bound as TypeImpl;
+ if (bound != null) {
+ var boundStr = bound.toString(withNullability: true);
+ typeStr += ', ${typeParameter.name} extends ' + boundStr;
+ }
+ }
+ }
+ return typeStr;
+ }
+
static String _typeStr(DartType type) {
return (type as TypeImpl).toString(withNullability: true);
}
@@ -6146,233 +6081,12 @@
class _SubtypingTestBase with ElementsTypesMixin {
TypeProvider typeProvider;
- Dart2TypeSystem typeSystem;
-
- ClassElement _comparableElement;
-
- ClassElement get comparableElement {
- return _comparableElement ??=
- typeProvider.intType.element.library.getType('Comparable');
- }
-
- InterfaceType get doubleNone {
- var element = typeProvider.doubleType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceType get doubleQuestion {
- var element = typeProvider.doubleType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType get doubleStar {
- var element = typeProvider.doubleType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
- DartType get dynamicNone => typeProvider.dynamicType;
-
- InterfaceType get functionNone {
- var element = typeProvider.functionType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceType get functionQuestion {
- var element = typeProvider.functionType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType get functionStar {
- var element = typeProvider.functionType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
- InterfaceType get intNone {
- var element = typeProvider.intType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceType get intQuestion {
- var element = typeProvider.intType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType get intStar {
- var element = typeProvider.intType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
- InterfaceType get nullNone {
- var element = typeProvider.nullType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceType get nullQuestion {
- var element = typeProvider.nullType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType get nullStar {
- var element = typeProvider.nullType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
- InterfaceType get numNone {
- var element = typeProvider.numType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceType get numQuestion {
- var element = typeProvider.numType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType get numStar {
- var element = typeProvider.numType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
- InterfaceType get objectNone {
- var element = typeProvider.objectType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceType get objectQuestion {
- var element = typeProvider.objectType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType get objectStar {
- var element = typeProvider.objectType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
- InterfaceType get stringNone {
- var element = typeProvider.stringType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceType get stringQuestion {
- var element = typeProvider.stringType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceType get stringStar {
- var element = typeProvider.stringType.element;
- return element.instantiate(
- typeArguments: const [],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
+ TypeSystemImpl typeSystem;
FeatureSet get testFeatureSet {
return FeatureSet.forTesting();
}
- VoidType get voidNone => typeProvider.voidType;
-
- InterfaceTypeImpl futureNone(DartType type) {
- return typeProvider.futureElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceTypeImpl futureOrNone(DartType type) {
- return typeProvider.futureOrElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.none,
- );
- }
-
- InterfaceTypeImpl futureOrQuestion(DartType type) {
- return typeProvider.futureOrElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceTypeImpl futureOrStar(DartType type) {
- return typeProvider.futureOrElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
- InterfaceTypeImpl futureQuestion(DartType type) {
- return typeProvider.futureElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.question,
- );
- }
-
- InterfaceTypeImpl futureStar(DartType type) {
- return typeProvider.futureElement.instantiate(
- typeArguments: [type],
- nullabilitySuffix: NullabilitySuffix.star,
- );
- }
-
void setUp() {
var analysisContext = TestAnalysisContext(
featureSet: testFeatureSet,
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index 9cccdad..1527bf0 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -12,6 +12,7 @@
import 'subtype_test.dart' as subtype;
import 'type_algebra_test.dart' as type_algebra;
import 'type_parameter_element_test.dart' as type_parameter_element;
+import 'upper_bound_test.dart' as upper_bound;
/// Utility for manually running all tests.
main() {
@@ -24,5 +25,6 @@
subtype.main();
type_algebra.main();
type_parameter_element.main();
+ upper_bound.main();
}, name: 'element');
}
diff --git a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
index 977b926..9f6b25e 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -33,7 +33,7 @@
var T = typeParameter('T');
var A = class_(name: 'A', typeParameters: [T]);
- var type = interfaceType(A, typeArguments: [intType]);
+ var type = interfaceTypeStar(A, typeArguments: [intType]);
var result = Substitution.empty.substituteType(type);
expect(result, same(type));
@@ -51,11 +51,11 @@
var U = typeParameter('U');
var B = class_(name: 'B', typeParameters: [U]);
- var BofInt = interfaceType(B, typeArguments: [intType]);
+ var BofInt = interfaceTypeStar(B, typeArguments: [intType]);
var substitution = Substitution.fromInterfaceType(BofInt);
// A<U>
- var type = interfaceType(A, typeArguments: [typeParameterType(U)]);
+ var type = interfaceTypeStar(A, typeArguments: [typeParameterType(U)]);
assertElementTypeString(type, 'A<U>');
var result = substitution.substituteType(type);
@@ -71,7 +71,7 @@
var U = typeParameter('U');
var A = class_(name: 'A', typeParameters: [T, U]);
- var type = interfaceType(
+ var type = interfaceTypeStar(
A,
typeArguments: [
typeParameterType(T),
@@ -188,7 +188,7 @@
var T = typeParameter('T');
var U = typeParameter('U');
var V = typeParameter('V');
- T.bound = interfaceType(classTriplet, typeArguments: [
+ T.bound = interfaceTypeStar(classTriplet, typeArguments: [
typeParameterType(T),
typeParameterType(U),
typeParameterType(V),
@@ -221,7 +221,7 @@
var A = class_(name: 'A', typeParameters: [T]);
var U = typeParameter('U');
- var type = interfaceType(A, typeArguments: [
+ var type = interfaceTypeStar(A, typeArguments: [
typeParameterType(U),
]);
@@ -234,8 +234,8 @@
var A = class_(name: 'A', typeParameters: [T]);
var U = typeParameter('U');
- var type = interfaceType(A, typeArguments: [
- interfaceType(
+ var type = interfaceTypeStar(A, typeArguments: [
+ interfaceTypeStar(
typeProvider.listElement,
typeArguments: [
typeParameterType(U),
@@ -251,7 +251,7 @@
// class A {}
var A = class_(name: 'A');
- var type = interfaceType(A);
+ var type = interfaceTypeStar(A);
var T = typeParameter('T');
_assertIdenticalType(type, {T: intType});
}
@@ -261,7 +261,7 @@
var T = typeParameter('T');
var A = class_(name: 'A', typeParameters: [T]);
- var type = interfaceType(A, typeArguments: [intType]);
+ var type = interfaceTypeStar(A, typeArguments: [intType]);
var U = typeParameter('U');
_assertIdenticalType(type, {U: doubleType});
@@ -387,9 +387,7 @@
final bool useNnbd;
_Base({this.useNnbd = false})
- : typeProvider = TestTypeProvider(
- nullabilitySuffix:
- useNnbd ? NullabilitySuffix.none : NullabilitySuffix.question);
+ : typeProvider = TestTypeProvider(isNonNullableByDefault: useNnbd);
InterfaceType get boolType => typeProvider.boolType;
diff --git a/pkg/analyzer/test/src/dart/element/upper_bound_test.dart b/pkg/analyzer/test/src/dart/element/upper_bound_test.dart
new file mode 100644
index 0000000..9a7c535
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/upper_bound_test.dart
@@ -0,0 +1,1366 @@
+// Copyright (c) 2019, 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.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_visitor.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/elements_types_mixin.dart';
+import '../../../generated/test_analysis_context.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(BoundsHelperPredicatesTest);
+ defineReflectiveTests(UpperBoundTest);
+ });
+}
+
+@reflectiveTest
+class BoundsHelperPredicatesTest extends _SubtypingTestBase {
+ static final Map<String, StackTrace> _isMoreBottomChecked = {};
+ static final Map<String, StackTrace> _isMoreTopChecked = {};
+
+ @override
+ FeatureSet get testFeatureSet {
+ return FeatureSet.forTesting(
+ additionalFeatures: [Feature.non_nullable],
+ );
+ }
+
+ void isBottom(DartType type) {
+ expect(typeSystem.isBottom(type), isTrue, reason: _typeString(type));
+ }
+
+ void isMoreBottom(DartType T, DartType S) {
+ _assertIsBottomOrNull(T);
+ _assertIsBottomOrNull(S);
+
+ var str = _typeString(T) + ' vs ' + _typeString(S);
+ _checkUniqueTypeStr(_isMoreBottomChecked, str);
+
+ expect(typeSystem.isMoreBottom(T, S), isTrue, reason: str);
+ }
+
+ void isMoreTop(DartType T, DartType S) {
+ _assertIsTopOrObject(T);
+ _assertIsTopOrObject(S);
+
+ var str = _typeString(T) + ' vs ' + _typeString(S);
+ _checkUniqueTypeStr(_isMoreTopChecked, str);
+
+ expect(typeSystem.isMoreTop(T, S), isTrue, reason: str);
+ }
+
+ void isNotBottom(DartType type) {
+ expect(typeSystem.isBottom(type), isFalse, reason: _typeString(type));
+ }
+
+ void isNotMoreBottom(DartType T, DartType S) {
+ _assertIsBottomOrNull(T);
+ _assertIsBottomOrNull(S);
+
+ var str = _typeString(T) + ' vs ' + _typeString(S);
+ _checkUniqueTypeStr(_isMoreBottomChecked, str);
+
+ expect(typeSystem.isMoreBottom(T, S), isFalse, reason: str);
+ }
+
+ void isNotMoreTop(DartType T, DartType S) {
+ _assertIsTopOrObject(T);
+ _assertIsTopOrObject(S);
+
+ var str = _typeString(T) + ' vs ' + _typeString(S);
+ _checkUniqueTypeStr(_isMoreTopChecked, str);
+
+ expect(typeSystem.isMoreTop(T, S), isFalse, reason: str);
+ }
+
+ void isNotNull(DartType type) {
+ expect(typeSystem.isNull(type), isFalse, reason: _typeString(type));
+ }
+
+ void isNotObject(DartType type) {
+ expect(typeSystem.isObject(type), isFalse, reason: _typeString(type));
+ }
+
+ void isNotTop(DartType type) {
+ expect(typeSystem.isTop(type), isFalse, reason: _typeString(type));
+ }
+
+ void isNull(DartType type) {
+ expect(typeSystem.isNull(type), isTrue, reason: _typeString(type));
+ }
+
+ void isObject(DartType type) {
+ expect(typeSystem.isObject(type), isTrue, reason: _typeString(type));
+ }
+
+ void isTop(DartType type) {
+ expect(typeSystem.isTop(type), isTrue, reason: _typeString(type));
+ }
+
+ test_isBottom() {
+ TypeParameterElement T;
+ TypeParameterMember T2;
+
+ // BOTTOM(Never) is true
+ isBottom(neverNone);
+ isNotBottom(neverQuestion);
+ isNotBottom(neverStar);
+
+ // BOTTOM(X&T) is true iff BOTTOM(T)
+ T = typeParameter('T', bound: objectQuestion);
+
+ T2 = promoteTypeParameter(T, neverNone);
+ isBottom(typeParameterTypeNone(T2));
+ isBottom(typeParameterTypeQuestion(T2));
+ isBottom(typeParameterTypeStar(T2));
+
+ T2 = promoteTypeParameter(T, neverQuestion);
+ isNotBottom(typeParameterTypeNone(T2));
+ isNotBottom(typeParameterTypeQuestion(T2));
+ isNotBottom(typeParameterTypeStar(T2));
+
+ // BOTTOM(X extends T) is true iff BOTTOM(T)
+ T = typeParameter('T', bound: neverNone);
+ isBottom(typeParameterTypeNone(T));
+ isBottom(typeParameterTypeQuestion(T));
+ isBottom(typeParameterTypeStar(T));
+
+ T = typeParameter('T', bound: neverQuestion);
+ isNotBottom(typeParameterTypeNone(T));
+ isNotBottom(typeParameterTypeQuestion(T));
+ isNotBottom(typeParameterTypeStar(T));
+
+ // BOTTOM(T) is false otherwise
+ isNotBottom(dynamicNone);
+ isNotBottom(voidNone);
+
+ isNotBottom(objectNone);
+ isNotBottom(objectQuestion);
+ isNotBottom(objectStar);
+
+ isNotBottom(intNone);
+ isNotBottom(intQuestion);
+ isNotBottom(intStar);
+
+ T = typeParameter('T', bound: numNone);
+ isNotBottom(typeParameterTypeNone(T));
+ isNotBottom(typeParameterTypeQuestion(T));
+ isNotBottom(typeParameterTypeStar(T));
+
+ T = typeParameter('T', bound: numStar);
+ isNotBottom(typeParameterTypeNone(T));
+ isNotBottom(typeParameterTypeQuestion(T));
+ isNotBottom(typeParameterTypeStar(T));
+
+ T2 = promoteTypeParameter(typeParameter('T'), intNone);
+ isNotBottom(typeParameterTypeNone(T2));
+ isNotBottom(typeParameterTypeQuestion(T2));
+ isNotBottom(typeParameterTypeStar(T2));
+ }
+
+ test_isMoreBottom() {
+ // MOREBOTTOM(Never, T) = true
+ isMoreBottom(neverNone, neverNone);
+ isMoreBottom(neverNone, neverQuestion);
+ isMoreBottom(neverNone, neverStar);
+
+ isMoreBottom(neverNone, nullNone);
+ isMoreBottom(neverNone, nullQuestion);
+ isMoreBottom(neverNone, nullStar);
+
+ // MOREBOTTOM(T, Never) = false
+ isNotMoreBottom(neverQuestion, neverNone);
+ isNotMoreBottom(neverStar, neverNone);
+
+ isNotMoreBottom(nullNone, neverNone);
+ isNotMoreBottom(nullQuestion, neverNone);
+ isNotMoreBottom(nullStar, neverNone);
+
+ // MOREBOTTOM(Null, T) = true
+ isMoreBottom(nullNone, neverQuestion);
+ isMoreBottom(nullNone, neverStar);
+
+ isMoreBottom(nullNone, nullNone);
+ isMoreBottom(nullNone, nullQuestion);
+ isMoreBottom(nullNone, nullStar);
+
+ // MOREBOTTOM(T, Null) = false
+ isNotMoreBottom(neverQuestion, nullNone);
+ isNotMoreBottom(neverStar, nullNone);
+
+ isNotMoreBottom(nullQuestion, nullNone);
+ isNotMoreBottom(nullStar, nullNone);
+
+ // MOREBOTTOM(T?, S?) = MOREBOTTOM(T, S)
+ isMoreBottom(neverQuestion, nullQuestion);
+ isNotMoreBottom(nullQuestion, neverQuestion);
+
+ // MOREBOTTOM(T, S?) = true
+ isMoreBottom(neverStar, nullQuestion);
+ isMoreBottom(nullStar, neverQuestion);
+
+ // MOREBOTTOM(T?, S) = false
+ isNotMoreBottom(neverQuestion, nullStar);
+ isNotMoreBottom(nullQuestion, neverStar);
+
+ // MOREBOTTOM(T*, S*) = MOREBOTTOM(T, S)
+ isMoreBottom(neverStar, nullStar);
+ isNotMoreBottom(nullStar, neverStar);
+
+ // MOREBOTTOM(T, S*) = true
+ isMoreBottom(
+ typeParameterTypeNone(
+ typeParameter('S', bound: neverNone),
+ ),
+ nullStar,
+ );
+
+ // MOREBOTTOM(T*, S) = false
+ isNotMoreBottom(
+ nullStar,
+ typeParameterTypeNone(
+ typeParameter('S', bound: neverNone),
+ ),
+ );
+
+ // MOREBOTTOM(X&T, Y&S) = MOREBOTTOM(T, S)
+ isMoreBottom(
+ typeParameterTypeNone(
+ promoteTypeParameter(
+ typeParameter('T', bound: objectQuestion),
+ neverNone,
+ ),
+ ),
+ typeParameterTypeQuestion(
+ promoteTypeParameter(
+ typeParameter('S', bound: objectQuestion),
+ neverNone,
+ ),
+ ),
+ );
+
+ // MOREBOTTOM(X&T, S) = true
+ isMoreBottom(
+ typeParameterTypeNone(
+ promoteTypeParameter(
+ typeParameter('T', bound: objectQuestion),
+ neverNone,
+ ),
+ ),
+ typeParameterTypeNone(
+ typeParameter('S', bound: neverNone),
+ ),
+ );
+
+ // MOREBOTTOM(T, X&S) = false
+ isNotMoreBottom(
+ typeParameterTypeNone(
+ typeParameter('T', bound: neverNone),
+ ),
+ typeParameterTypeNone(
+ promoteTypeParameter(
+ typeParameter('S', bound: objectQuestion),
+ neverNone,
+ ),
+ ),
+ );
+
+ // MOREBOTTOM(X extends T, Y extends S) = MOREBOTTOM(T, S)
+ isMoreBottom(
+ typeParameterTypeNone(
+ typeParameter('T', bound: neverNone),
+ ),
+ typeParameterTypeQuestion(
+ typeParameter('S', bound: neverNone),
+ ),
+ );
+ }
+
+ test_isMoreTop() {
+ // MORETOP(void, T) = true
+ isMoreTop(voidNone, voidNone);
+ isMoreTop(voidNone, dynamicNone);
+ isMoreTop(voidNone, objectNone);
+ isMoreTop(voidNone, objectQuestion);
+ isMoreTop(voidNone, objectStar);
+ isMoreTop(voidNone, futureOrNone(objectNone));
+ isMoreTop(voidNone, futureOrNone(objectQuestion));
+ isMoreTop(voidNone, futureOrNone(objectStar));
+
+ // MORETOP(T, void) = false
+ isNotMoreTop(dynamicNone, voidNone);
+ isNotMoreTop(objectNone, voidNone);
+ isNotMoreTop(objectQuestion, voidNone);
+ isNotMoreTop(objectStar, voidNone);
+ isNotMoreTop(futureOrNone(objectNone), voidNone);
+ isNotMoreTop(futureOrNone(objectQuestion), voidNone);
+ isNotMoreTop(futureOrNone(objectStar), voidNone);
+
+ // MORETOP(dynamic, T) = true
+ isMoreTop(dynamicNone, dynamicNone);
+ isMoreTop(dynamicNone, objectNone);
+ isMoreTop(dynamicNone, objectQuestion);
+ isMoreTop(dynamicNone, objectStar);
+ isMoreTop(dynamicNone, futureOrNone(objectNone));
+ isMoreTop(dynamicNone, futureOrNone(objectQuestion));
+ isMoreTop(dynamicNone, futureOrNone(objectStar));
+
+ // MORETOP(T, dynamic) = false
+ isNotMoreTop(objectNone, dynamicNone);
+ isNotMoreTop(objectQuestion, dynamicNone);
+ isNotMoreTop(objectStar, dynamicNone);
+ isNotMoreTop(futureOrNone(objectNone), dynamicNone);
+ isNotMoreTop(futureOrNone(objectQuestion), dynamicNone);
+ isNotMoreTop(futureOrNone(objectStar), dynamicNone);
+
+ // MORETOP(Object, T) = true
+ isMoreTop(objectNone, objectNone);
+ isMoreTop(objectNone, objectQuestion);
+ isMoreTop(objectNone, objectStar);
+ isMoreTop(objectNone, futureOrNone(objectNone));
+ isMoreTop(objectNone, futureOrQuestion(objectNone));
+ isMoreTop(objectNone, futureOrStar(objectNone));
+
+ // MORETOP(T, Object) = false
+ isNotMoreTop(objectQuestion, objectNone);
+ isNotMoreTop(objectStar, objectNone);
+ isNotMoreTop(futureOrNone(objectNone), objectNone);
+ isNotMoreTop(futureOrQuestion(objectNone), objectNone);
+ isNotMoreTop(futureOrStar(objectNone), objectNone);
+
+ // MORETOP(T*, S*) = MORETOP(T, S)
+ isMoreTop(objectStar, objectStar);
+ isMoreTop(objectStar, futureOrStar(objectNone));
+ isMoreTop(objectStar, futureOrStar(objectQuestion));
+ isMoreTop(objectStar, futureOrStar(objectStar));
+ isMoreTop(futureOrStar(objectNone), futureOrStar(objectNone));
+
+ // MORETOP(T, S*) = true
+ isMoreTop(futureOrNone(objectNone), futureOrStar(voidNone));
+ isMoreTop(futureOrNone(objectNone), futureOrStar(dynamicNone));
+ isMoreTop(futureOrNone(objectNone), futureOrStar(objectNone));
+ isMoreTop(futureOrQuestion(objectNone), futureOrStar(voidNone));
+ isMoreTop(futureOrQuestion(objectNone), futureOrStar(dynamicNone));
+ isMoreTop(futureOrQuestion(objectNone), futureOrStar(objectNone));
+
+ // MORETOP(T*, S) = false
+ isNotMoreTop(futureOrStar(voidNone), futureOrNone(objectNone));
+ isNotMoreTop(futureOrStar(dynamicNone), futureOrNone(objectNone));
+ isNotMoreTop(futureOrStar(objectNone), futureOrNone(objectNone));
+ isNotMoreTop(futureOrStar(voidNone), futureOrQuestion(objectNone));
+ isNotMoreTop(futureOrStar(dynamicNone), futureOrQuestion(objectNone));
+ isNotMoreTop(futureOrStar(objectNone), futureOrQuestion(objectNone));
+
+ // MORETOP(T?, S?) = MORETOP(T, S)
+ isMoreTop(objectQuestion, objectQuestion);
+ isMoreTop(futureOrQuestion(voidNone), futureOrQuestion(voidNone));
+ isMoreTop(futureOrQuestion(voidNone), futureOrQuestion(dynamicNone));
+ isMoreTop(futureOrQuestion(voidNone), futureOrQuestion(objectNone));
+
+ // MORETOP(T, S?) = true
+ isMoreTop(futureOrNone(objectNone), futureOrQuestion(voidNone));
+ isMoreTop(futureOrNone(objectNone), futureOrQuestion(dynamicNone));
+ isMoreTop(futureOrNone(objectNone), futureOrQuestion(objectNone));
+
+ // MORETOP(T?, S) = false
+ isNotMoreTop(futureOrQuestion(voidNone), futureOrNone(objectNone));
+ isNotMoreTop(futureOrQuestion(dynamicNone), futureOrNone(objectNone));
+ isNotMoreTop(futureOrQuestion(objectNone), futureOrNone(objectNone));
+
+ // MORETOP(FutureOr<T>, FutureOr<S>) = MORETOP(T, S)
+ isMoreTop(futureOrNone(voidNone), futureOrNone(voidNone));
+ isMoreTop(futureOrNone(voidNone), futureOrNone(dynamicNone));
+ isMoreTop(futureOrNone(voidNone), futureOrNone(objectNone));
+ isNotMoreTop(futureOrNone(dynamicNone), futureOrNone(voidNone));
+ isNotMoreTop(futureOrNone(objectNone), futureOrNone(voidNone));
+ }
+
+ test_isNull() {
+ // NULL(Null) is true
+ isNull(nullNone);
+
+ // NULL(T?) is true iff NULL(T) or BOTTOM(T)
+ isNull(nullQuestion);
+ isNull(neverQuestion);
+ isNull(
+ typeParameterTypeQuestion(
+ typeParameter('T', bound: neverNone),
+ ),
+ );
+
+ // NULL(T*) is true iff NULL(T) or BOTTOM(T)
+ isNull(nullStar);
+ isNull(neverStar);
+ isNull(
+ typeParameterTypeStar(
+ typeParameter('T', bound: neverNone),
+ ),
+ );
+
+ // NULL(T) is false otherwise
+ isNotNull(dynamicNone);
+ isNotNull(voidNone);
+
+ isNotNull(objectNone);
+ isNotNull(objectQuestion);
+ isNotNull(objectStar);
+
+ isNotNull(intNone);
+ isNotNull(intQuestion);
+ isNotNull(intStar);
+
+ isNotNull(futureOrNone(nullNone));
+ isNotNull(futureOrNone(nullQuestion));
+ isNotNull(futureOrNone(nullStar));
+
+ isNotNull(futureOrQuestion(nullNone));
+ isNotNull(futureOrQuestion(nullQuestion));
+ isNotNull(futureOrQuestion(nullStar));
+
+ isNotNull(futureOrStar(nullNone));
+ isNotNull(futureOrStar(nullQuestion));
+ isNotNull(futureOrStar(nullStar));
+ }
+
+ test_isObject() {
+ // OBJECT(Object) is true
+ isObject(objectNone);
+ isNotObject(objectQuestion);
+ isNotObject(objectStar);
+
+ // OBJECT(FutureOr<T>) is OBJECT(T)
+ isObject(futureOrNone(objectNone));
+ isNotObject(futureOrNone(objectQuestion));
+ isNotObject(futureOrNone(objectStar));
+
+ isNotObject(futureOrQuestion(objectNone));
+ isNotObject(futureOrQuestion(objectQuestion));
+ isNotObject(futureOrQuestion(objectStar));
+
+ isNotObject(futureOrStar(objectNone));
+ isNotObject(futureOrStar(objectQuestion));
+ isNotObject(futureOrStar(objectStar));
+
+ // OBJECT(T) is false otherwise
+ isNotObject(dynamicNone);
+ isNotObject(voidNone);
+ isNotObject(intNone);
+ }
+
+ test_isTop() {
+ // TOP(T?) is true iff TOP(T) or OBJECT(T)
+ isTop(objectQuestion);
+ isTop(futureOrQuestion(dynamicNone));
+ isTop(futureOrQuestion(voidNone));
+
+ isTop(futureOrQuestion(objectNone));
+ isTop(futureOrQuestion(objectQuestion));
+ isTop(futureOrQuestion(objectStar));
+
+ isNotTop(futureOrQuestion(intNone));
+ isNotTop(futureOrQuestion(intQuestion));
+ isNotTop(futureOrQuestion(intStar));
+
+ // TOP(T*) is true iff TOP(T) or OBJECT(T)
+ isTop(objectStar);
+ isTop(futureOrStar(dynamicNone));
+ isTop(futureOrStar(voidNone));
+
+ isTop(futureOrStar(objectNone));
+ isTop(futureOrStar(objectQuestion));
+ isTop(futureOrStar(objectStar));
+
+ isNotTop(futureOrStar(intNone));
+ isNotTop(futureOrStar(intQuestion));
+ isNotTop(futureOrStar(intStar));
+
+ // TOP(dynamic) is true
+ isTop(dynamicNone);
+
+ // TOP(void) is true
+ isTop(voidNone);
+
+ // TOP(FutureOr<T>) is TOP(T)
+ isTop(futureOrNone(dynamicNone));
+ isTop(futureOrNone(voidNone));
+
+ isNotTop(futureOrNone(objectNone));
+ isTop(futureOrNone(objectQuestion));
+ isTop(futureOrNone(objectStar));
+
+ // TOP(T) is false otherwise
+ isNotTop(objectNone);
+
+ isNotTop(intNone);
+ isNotTop(intQuestion);
+ isNotTop(intStar);
+
+ isNotTop(neverNone);
+ isNotTop(neverQuestion);
+ isNotTop(neverStar);
+ }
+
+ /// [TypeSystemImpl.isMoreBottom] can be used only for `BOTTOM` or `NULL`
+ /// types. No need to check other types.
+ void _assertIsBottomOrNull(DartType type) {
+ expect(typeSystem.isBottom(type) || typeSystem.isNull(type), isTrue,
+ reason: _typeString(type));
+ }
+
+ /// [TypeSystemImpl.isMoreTop] can be used only for `TOP` or `OBJECT`
+ /// types. No need to check other types.
+ void _assertIsTopOrObject(DartType type) {
+ expect(typeSystem.isTop(type) || typeSystem.isObject(type), isTrue,
+ reason: _typeString(type));
+ }
+
+ void _checkUniqueTypeStr(Map<String, StackTrace> map, String str) {
+ var previousStack = map[str];
+ if (previousStack != null) {
+ fail('Not unique: $str\n$previousStack');
+ } else {
+ map[str] = StackTrace.current;
+ }
+ }
+
+ String _typeParametersStr(TypeImpl type) {
+ var typeStr = '';
+
+ var typeParameterCollector = _TypeParameterCollector();
+ DartTypeVisitor.visit(type, typeParameterCollector);
+ for (var typeParameter in typeParameterCollector.typeParameters) {
+ if (typeParameter is TypeParameterMember) {
+ var base = typeParameter.declaration;
+ var baseBound = base.bound as TypeImpl;
+ if (baseBound != null) {
+ var baseBoundStr = baseBound.toString(withNullability: true);
+ typeStr += ', ${typeParameter.name} extends ' + baseBoundStr;
+ }
+
+ var bound = typeParameter.bound as TypeImpl;
+ var boundStr = bound.toString(withNullability: true);
+ typeStr += ', ${typeParameter.name} & ' + boundStr;
+ } else {
+ var bound = typeParameter.bound as TypeImpl;
+ if (bound != null) {
+ var boundStr = bound.toString(withNullability: true);
+ typeStr += ', ${typeParameter.name} extends ' + boundStr;
+ }
+ }
+ }
+ return typeStr;
+ }
+}
+
+@reflectiveTest
+class UpperBoundTest extends _SubtypingTestBase {
+ test_bottom_any() {
+ void check(DartType T1, DartType T2) {
+ expect(typeSystem.isBottom(T1), isTrue, reason: _typeString(T1));
+ expect(typeSystem.isBottom(T2), isFalse, reason: _typeString(T2));
+ _checkLeastUpperBound(T1, T2, T2);
+ }
+
+ check(neverNone, objectNone);
+ check(neverNone, objectStar);
+ check(neverNone, objectQuestion);
+
+ check(neverNone, intNone);
+ check(neverNone, intQuestion);
+ check(neverNone, intStar);
+
+ check(neverNone, listNone(intNone));
+ check(neverNone, listQuestion(intNone));
+ check(neverNone, listStar(intNone));
+
+ check(neverNone, futureOrNone(intNone));
+ check(neverNone, futureOrQuestion(intNone));
+ check(neverNone, futureOrStar(intNone));
+
+ {
+ var T = typeParameterTypeNone(
+ typeParameter('T', bound: neverNone),
+ );
+ check(T, intNone);
+ check(T, intQuestion);
+ check(T, intStar);
+ }
+
+ {
+ var T = typeParameterTypeNone(
+ promoteTypeParameter(
+ typeParameter('T', bound: objectQuestion),
+ neverNone,
+ ),
+ );
+ check(T, intNone);
+ check(T, intQuestion);
+ check(T, intStar);
+ }
+ }
+
+ test_bottom_bottom() {
+ void check(DartType T1, DartType T2) {
+ expect(typeSystem.isBottom(T1), isTrue, reason: _typeString(T1));
+ expect(typeSystem.isBottom(T2), isTrue, reason: _typeString(T2));
+ _checkLeastUpperBound(T1, T2, T2);
+ }
+
+ check(
+ neverNone,
+ typeParameterTypeNone(
+ typeParameter('T', bound: neverNone),
+ ),
+ );
+
+ check(
+ neverNone,
+ typeParameterTypeNone(
+ promoteTypeParameter(
+ typeParameter('T', bound: objectQuestion),
+ neverNone,
+ ),
+ ),
+ );
+ }
+
+ test_functionType2_parameters_named() {
+ FunctionType build(Map<String, DartType> namedTypes) {
+ return functionTypeNone(
+ returnType: voidNone,
+ parameters: namedTypes.entries.map((entry) {
+ return namedParameter(name: entry.key, type: entry.value);
+ }).toList(),
+ );
+ }
+
+ void check(Map<String, DartType> T1_named, Map<String, DartType> T2_named,
+ Map<String, DartType> expected_named) {
+ var T1 = build(T1_named);
+ var T2 = build(T2_named);
+ var expected = build(expected_named);
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check({'a': intNone}, {}, {});
+ check({'a': intNone}, {'b': intNone}, {});
+
+ check({'a': intNone}, {'a': intNone}, {'a': intNone});
+ check({'a': intNone}, {'a': intQuestion}, {'a': intNone});
+
+ check({'a': intNone, 'b': doubleNone}, {'a': intNone}, {'a': intNone});
+ }
+
+ test_functionType2_parameters_optionalPositional() {
+ FunctionType build(List<DartType> positionalTypes) {
+ return functionTypeNone(
+ returnType: voidNone,
+ parameters: positionalTypes.map((type) {
+ return positionalParameter(type: type);
+ }).toList(),
+ );
+ }
+
+ void check(List<DartType> T1_positional, List<DartType> T2_positional,
+ DartType expected) {
+ var T1 = build(T1_positional);
+ var T2 = build(T2_positional);
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check([intNone], [], build([]));
+ check([intNone, doubleNone], [intNone], build([intNone]));
+
+ check([intNone], [intNone], build([intNone]));
+ check([intNone], [intQuestion], build([intNone]));
+
+ // TODO(scheglov) Uncomment when DOWN is NNBD based.
+// check([intNone], [intStar], build([intNone]));
+// check([intNone], [doubleNone], build([neverNone]));
+
+ check([intNone], [numNone], build([intNone]));
+
+ check(
+ [doubleNone, numNone],
+ [numNone, intNone],
+ build([doubleNone, intNone]),
+ );
+ }
+
+ test_functionType2_parameters_required() {
+ FunctionType build(List<DartType> requiredTypes) {
+ return functionTypeNone(
+ returnType: voidNone,
+ parameters: requiredTypes.map((type) {
+ return requiredParameter(type: type);
+ }).toList(),
+ );
+ }
+
+ void check(List<DartType> T1_required, List<DartType> T2_required,
+ DartType expected) {
+ var T1 = build(T1_required);
+ var T2 = build(T2_required);
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check([intNone], [], functionNone);
+
+ check([intNone], [intNone], build([intNone]));
+ check([intNone], [intQuestion], build([intNone]));
+
+ // TODO(scheglov) Uncomment when DOWN is NNBD based.
+// check([intNone], [intStar], build([intNone]));
+// check([intNone], [doubleNone], build([neverNone]));
+
+ check([intNone], [numNone], build([intNone]));
+
+ check(
+ [doubleNone, numNone],
+ [numNone, intNone],
+ build([doubleNone, intNone]),
+ );
+ }
+
+ test_functionType2_returnType() {
+ void check(DartType T1_ret, DartType T2_ret, DartType expected_ret) {
+ _checkLeastUpperBound(
+ functionTypeNone(returnType: T1_ret),
+ functionTypeNone(returnType: T2_ret),
+ functionTypeNone(returnType: expected_ret),
+ );
+ }
+
+ check(intNone, intNone, intNone);
+ check(intNone, intQuestion, intQuestion);
+ check(intNone, intStar, intStar);
+
+ check(intNone, numNone, numNone);
+ check(intQuestion, numNone, numQuestion);
+ check(intStar, numNone, numStar);
+
+ check(intNone, dynamicNone, dynamicNone);
+ check(intNone, neverNone, intNone);
+ }
+
+ test_functionType2_typeParameters() {
+ void check(FunctionType T1, FunctionType T2, DartType expected) {
+ _assertNullabilityNone(T1);
+ _assertNullabilityNone(T2);
+
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check(
+ functionTypeNone(
+ returnType: voidNone,
+ typeFormals: [
+ typeParameter('T'),
+ ],
+ ),
+ functionTypeNone(returnType: voidNone),
+ functionNone,
+ );
+
+ check(
+ functionTypeNone(
+ returnType: voidNone,
+ typeFormals: [
+ typeParameter('T', bound: intNone),
+ ],
+ ),
+ functionTypeNone(
+ returnType: voidNone,
+ typeFormals: [
+ typeParameter('T', bound: numNone),
+ ],
+ ),
+ functionNone,
+ );
+
+ {
+ var T = typeParameter('T', bound: numNone);
+ var U = typeParameter('U', bound: numNone);
+ var R = typeParameter('R', bound: numNone);
+ check(
+ functionTypeNone(
+ returnType: typeParameterTypeNone(T),
+ typeFormals: [T],
+ ),
+ functionTypeNone(
+ returnType: typeParameterTypeNone(U),
+ typeFormals: [U],
+ ),
+ functionTypeNone(
+ returnType: typeParameterTypeNone(R),
+ typeFormals: [R],
+ ),
+ );
+ }
+ }
+
+ test_functionType_interfaceType() {
+ void check(FunctionType T1, InterfaceType T2, InterfaceType expected) {
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check(
+ functionTypeNone(returnType: voidNone),
+ intNone,
+ objectNone,
+ );
+ }
+
+ test_functionType_interfaceType_Function() {
+ void check(FunctionType T1, InterfaceType T2, InterfaceType expected) {
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ void checkNone(FunctionType T1) {
+ _assertNullabilityNone(T1);
+ check(T1, functionNone, functionNone);
+ }
+
+ checkNone(functionTypeNone(returnType: voidNone));
+
+ checkNone(
+ functionTypeNone(
+ returnType: intNone,
+ parameters: [
+ requiredParameter(type: numQuestion),
+ ],
+ ),
+ );
+
+ check(
+ functionTypeQuestion(returnType: voidNone),
+ functionNone,
+ functionQuestion,
+ );
+ }
+
+ test_identical() {
+ void check(DartType type) {
+ _checkLeastUpperBound(type, type, type);
+ }
+
+ check(intNone);
+ check(intQuestion);
+ check(intStar);
+ check(listNone(intNone));
+ }
+
+ test_none_question() {
+ void check(DartType T1, DartType T2, DartType expected) {
+ _assertNullabilityNone(T1);
+ _assertNullabilityQuestion(T2);
+
+ _assertNotSpecial(T1);
+ _assertNotSpecial(T2);
+
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check(doubleNone, intQuestion, numQuestion);
+ check(numNone, doubleQuestion, numQuestion);
+ check(numNone, intQuestion, numQuestion);
+ }
+
+ test_none_star() {
+ void check(DartType T1, DartType T2, DartType expected) {
+ _assertNullabilityNone(T1);
+ _assertNullabilityStar(T2);
+
+ _assertNotSpecial(T1);
+ _assertNotSpecial(T2);
+
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check(doubleNone, intStar, numStar);
+ check(numNone, doubleStar, numStar);
+ check(numNone, intStar, numStar);
+ }
+
+ test_null_any() {
+ void check(DartType T1, DartType T2, DartType expected) {
+ var T1_str = _typeString(T1);
+ var T2_str = _typeString(T2);
+
+ expect(typeSystem.isNull(T1), isTrue, reason: 'isNull: $T1_str');
+ expect(typeSystem.isNull(T2), isFalse, reason: 'isNull: $T2_str');
+
+ expect(typeSystem.isTop(T1), isFalse, reason: 'isTop: $T1_str');
+ expect(typeSystem.isTop(T2), isFalse, reason: 'isTop: $T2_str');
+
+ expect(typeSystem.isBottom(T1), isFalse, reason: 'isBottom: $T1_str');
+ expect(typeSystem.isBottom(T2), isFalse, reason: 'isBottom: $T2_str');
+
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check(nullNone, objectNone, objectQuestion);
+
+ check(nullNone, intNone, intQuestion);
+ check(nullNone, intQuestion, intQuestion);
+ check(nullNone, intStar, intQuestion);
+
+ check(nullQuestion, intNone, intQuestion);
+ check(nullQuestion, intQuestion, intQuestion);
+ check(nullQuestion, intStar, intQuestion);
+
+ check(nullStar, intNone, intQuestion);
+ check(nullStar, intQuestion, intQuestion);
+ check(nullStar, intStar, intQuestion);
+
+ check(nullNone, listNone(intNone), listQuestion(intNone));
+ check(nullNone, listQuestion(intNone), listQuestion(intNone));
+ check(nullNone, listStar(intNone), listQuestion(intNone));
+
+ check(nullNone, futureOrNone(intNone), futureOrQuestion(intNone));
+ check(nullNone, futureOrQuestion(intNone), futureOrQuestion(intNone));
+ check(nullNone, futureOrStar(intNone), futureOrQuestion(intNone));
+
+ check(nullNone, futureOrNone(intQuestion), futureOrNone(intQuestion));
+ check(nullNone, futureOrStar(intQuestion), futureOrStar(intQuestion));
+
+ check(
+ nullNone,
+ functionTypeNone(returnType: intNone),
+ functionTypeQuestion(returnType: intNone),
+ );
+ }
+
+ test_null_null() {
+ void check(DartType T1, DartType T2) {
+ var T1_str = _typeString(T1);
+ var T2_str = _typeString(T2);
+
+ expect(typeSystem.isNull(T1), isTrue, reason: 'isNull: $T1_str');
+ expect(typeSystem.isNull(T2), isTrue, reason: 'isNull: $T2_str');
+
+ expect(typeSystem.isBottom(T1), isFalse, reason: 'isBottom: $T1_str');
+ expect(typeSystem.isBottom(T2), isFalse, reason: 'isBottom: $T2_str');
+
+ _checkLeastUpperBound(T1, T2, T2);
+ }
+
+ check(nullNone, nullQuestion);
+ check(nullNone, nullStar);
+ }
+
+ test_object_any() {
+ void check(DartType T1, DartType T2, DartType expected) {
+ var T1_str = _typeString(T1);
+ var T2_str = _typeString(T2);
+
+ expect(typeSystem.isObject(T1), isTrue, reason: 'isObject: $T1_str');
+ expect(typeSystem.isObject(T2), isFalse, reason: 'isObject: $T2_str');
+
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check(objectNone, intNone, objectNone);
+ check(objectNone, intQuestion, objectQuestion);
+ check(objectNone, intStar, objectNone);
+
+ check(objectNone, futureOrNone(intQuestion), objectQuestion);
+
+ check(futureOrNone(objectNone), intNone, futureOrNone(objectNone));
+ check(futureOrNone(objectNone), intQuestion, futureOrQuestion(objectNone));
+ check(futureOrNone(objectNone), intStar, futureOrNone(objectNone));
+ }
+
+ test_object_object() {
+ void check(DartType T1, DartType T2) {
+ var T1_str = _typeString(T1);
+ var T2_str = _typeString(T2);
+
+ expect(typeSystem.isObject(T1), isTrue, reason: 'isObject: $T1_str');
+ expect(typeSystem.isObject(T2), isTrue, reason: 'isObject: $T2_str');
+
+ _checkLeastUpperBound(T1, T2, T2);
+ }
+
+ check(futureOrNone(objectNone), objectNone);
+
+ check(
+ futureOrNone(
+ futureOrNone(objectNone),
+ ),
+ futureOrNone(objectNone),
+ );
+ }
+
+ test_question_question() {
+ void check(DartType T1, DartType T2, DartType expected) {
+ _assertNullabilityQuestion(T1);
+ _assertNullabilityQuestion(T2);
+
+ _assertNotSpecial(T1);
+ _assertNotSpecial(T2);
+
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check(doubleQuestion, intQuestion, numQuestion);
+ check(numQuestion, doubleQuestion, numQuestion);
+ check(numQuestion, intQuestion, numQuestion);
+ }
+
+ test_question_star() {
+ void check(DartType T1, DartType T2, DartType expected) {
+ _assertNullabilityQuestion(T1);
+ _assertNullabilityStar(T2);
+
+ _assertNotSpecial(T1);
+ _assertNotSpecial(T2);
+
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check(doubleQuestion, intStar, numQuestion);
+ check(numQuestion, doubleStar, numQuestion);
+ check(numQuestion, intStar, numQuestion);
+ }
+
+ test_star_star() {
+ void check(DartType T1, DartType T2, DartType expected) {
+ _assertNullabilityStar(T1);
+ _assertNullabilityStar(T2);
+
+ _assertNotSpecial(T1);
+ _assertNotSpecial(T2);
+
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ check(doubleStar, intStar, numStar);
+ check(numStar, doubleStar, numStar);
+ check(numStar, intStar, numStar);
+ }
+
+ test_top_any() {
+ void check(DartType T1, DartType T2) {
+ expect(typeSystem.isTop(T1), isTrue, reason: _typeString(T1));
+ expect(typeSystem.isTop(T2), isFalse, reason: _typeString(T2));
+ _checkLeastUpperBound(T1, T2, T1);
+ }
+
+ check(voidNone, objectNone);
+ check(voidNone, intNone);
+ check(voidNone, intQuestion);
+ check(voidNone, intStar);
+ check(voidNone, listNone(intNone));
+ check(voidNone, futureOrNone(intNone));
+
+ check(dynamicNone, objectNone);
+ check(dynamicNone, intNone);
+ check(dynamicNone, intQuestion);
+ check(dynamicNone, intStar);
+ check(dynamicNone, listNone(intNone));
+ check(dynamicNone, futureOrNone(intNone));
+
+ check(objectQuestion, objectNone);
+ check(objectQuestion, intNone);
+ check(objectQuestion, intQuestion);
+ check(objectQuestion, intStar);
+ check(objectQuestion, listNone(intNone));
+ check(objectQuestion, futureOrNone(intNone));
+
+ check(objectStar, objectNone);
+ check(objectStar, intNone);
+ check(objectStar, intQuestion);
+ check(objectStar, intStar);
+ check(objectStar, listNone(intNone));
+ check(objectStar, futureOrNone(intNone));
+
+ check(futureOrNone(voidNone), intNone);
+ check(futureOrQuestion(voidNone), intNone);
+ check(futureOrStar(voidNone), intNone);
+ }
+
+ test_top_top() {
+ void check(DartType T1, DartType T2) {
+ expect(typeSystem.isTop(T1), isTrue, reason: _typeString(T1));
+ expect(typeSystem.isTop(T2), isTrue, reason: _typeString(T2));
+ _checkLeastUpperBound(T1, T2, T1);
+ }
+
+ check(voidNone, dynamicNone);
+ check(voidNone, objectStar);
+ check(voidNone, objectQuestion);
+ check(voidNone, futureOrNone(voidNone));
+ check(voidNone, futureOrNone(dynamicNone));
+ check(voidNone, futureOrNone(objectQuestion));
+ check(voidNone, futureOrNone(objectStar));
+
+ check(dynamicNone, objectStar);
+ check(dynamicNone, objectQuestion);
+ check(dynamicNone, futureOrNone(voidNone));
+ check(dynamicNone, futureOrNone(dynamicNone));
+ check(dynamicNone, futureOrNone(objectQuestion));
+ check(dynamicNone, futureOrNone(objectStar));
+ check(
+ dynamicNone,
+ futureOrStar(objectStar),
+ );
+
+ check(objectQuestion, futureOrQuestion(voidNone));
+ check(objectQuestion, futureOrQuestion(dynamicNone));
+ check(objectQuestion, futureOrQuestion(objectNone));
+ check(objectQuestion, futureOrQuestion(objectQuestion));
+ check(objectQuestion, futureOrQuestion(objectStar));
+
+ check(objectQuestion, futureOrStar(voidNone));
+ check(objectQuestion, futureOrStar(dynamicNone));
+ check(objectQuestion, futureOrStar(objectNone));
+ check(objectQuestion, futureOrStar(objectQuestion));
+ check(objectQuestion, futureOrStar(objectStar));
+
+ check(objectStar, futureOrStar(voidNone));
+ check(objectStar, futureOrStar(dynamicNone));
+ check(objectStar, futureOrStar(objectNone));
+ check(objectStar, futureOrStar(objectQuestion));
+ check(objectStar, futureOrStar(objectStar));
+
+ check(futureOrNone(voidNone), objectQuestion);
+ check(futureOrNone(dynamicNone), objectQuestion);
+ check(futureOrNone(objectQuestion), objectQuestion);
+ check(futureOrNone(objectStar), objectQuestion);
+
+ check(futureOrNone(voidNone), futureOrNone(dynamicNone));
+ check(futureOrNone(voidNone), futureOrNone(objectQuestion));
+ check(futureOrNone(voidNone), futureOrNone(objectStar));
+ check(futureOrNone(dynamicNone), futureOrNone(objectQuestion));
+ check(futureOrNone(dynamicNone), futureOrNone(objectStar));
+ }
+
+ test_typeParameter_bound() {
+ void check(TypeParameterType T1, DartType T2, DartType expected) {
+ _assertNullabilityNone(T1);
+ _assertNullabilityNone(T2);
+
+ _assertNotSpecial(T1);
+ _assertNotSpecial(T2);
+
+ _checkLeastUpperBound(T1, T2, expected);
+ }
+
+ {
+ var T = typeParameter('T', bound: intNone);
+ check(typeParameterTypeNone(T), numNone, numNone);
+ }
+
+ {
+ var T = typeParameter('T', bound: intNone);
+ var U = typeParameter('U', bound: numNone);
+ check(typeParameterTypeNone(T), typeParameterTypeNone(U), numNone);
+ }
+
+ {
+ var T = typeParameter('T', bound: intNone);
+ var U = typeParameter('U', bound: numQuestion);
+ check(typeParameterTypeNone(T), typeParameterTypeNone(U), numQuestion);
+ }
+
+ {
+ var T = typeParameter('T', bound: intQuestion);
+ var U = typeParameter('U', bound: numNone);
+ check(typeParameterTypeNone(T), typeParameterTypeNone(U), numQuestion);
+ }
+
+ {
+ var T = typeParameter('T', bound: numNone);
+ var T_none = typeParameterTypeNone(T);
+ var U = typeParameter('U', bound: T_none);
+ check(T_none, typeParameterTypeNone(U), T_none);
+ }
+ }
+
+ void _assertNotBottom(DartType type) {
+ if (typeSystem.isBottom(type)) {
+ fail('isBottom must be false: ' + _typeString(type));
+ }
+ }
+
+ void _assertNotNull(DartType type) {
+ if (typeSystem.isNull(type)) {
+ fail('isNull must be false: ' + _typeString(type));
+ }
+ }
+
+ void _assertNotObject(DartType type) {
+ if (typeSystem.isObject(type)) {
+ fail('isObject must be false: ' + _typeString(type));
+ }
+ }
+
+ void _assertNotSpecial(DartType type) {
+ _assertNotBottom(type);
+ _assertNotNull(type);
+ _assertNotObject(type);
+ _assertNotTop(type);
+ }
+
+ void _assertNotTop(DartType type) {
+ if (typeSystem.isTop(type)) {
+ fail('isTop must be false: ' + _typeString(type));
+ }
+ }
+
+ void _assertNullability(DartType type, NullabilitySuffix expected) {
+ if ((type as TypeImpl).nullabilitySuffix != expected) {
+ fail('Expected $expected in ' + _typeString(type));
+ }
+ }
+
+ void _assertNullabilityNone(DartType type) {
+ _assertNullability(type, NullabilitySuffix.none);
+ }
+
+ void _assertNullabilityQuestion(DartType type) {
+ _assertNullability(type, NullabilitySuffix.question);
+ }
+
+ void _assertNullabilityStar(DartType type) {
+ _assertNullability(type, NullabilitySuffix.star);
+ }
+
+ void _checkLeastUpperBound(DartType T1, DartType T2, DartType expected) {
+ var expectedStr = _typeString(expected);
+
+ var result = typeSystem.getLeastUpperBound(T1, T2);
+ var resultStr = _typeString(result);
+ expect(result, expected, reason: '''
+expected: $expectedStr
+actual: $resultStr
+''');
+
+ // Check that the result is an upper bound.
+ expect(typeSystem.isSubtypeOf(T1, result), true);
+ expect(typeSystem.isSubtypeOf(T2, result), true);
+
+ // Check for symmetry.
+ result = typeSystem.getLeastUpperBound(T2, T1);
+ resultStr = _typeString(result);
+ expect(result, expected, reason: '''
+expected: $expectedStr
+actual: $resultStr
+''');
+ }
+}
+
+@reflectiveTest
+class _SubtypingTestBase with ElementsTypesMixin {
+ TypeProvider typeProvider;
+
+ TypeSystemImpl typeSystem;
+
+ FeatureSet get testFeatureSet {
+ return FeatureSet.forTesting();
+ }
+
+ void setUp() {
+ var analysisContext = TestAnalysisContext(
+ featureSet: testFeatureSet,
+ );
+ typeProvider = analysisContext.typeProvider;
+ typeSystem = analysisContext.typeSystem;
+ }
+
+ String _typeParametersStr(TypeImpl type) {
+ var typeStr = '';
+
+ var typeParameterCollector = _TypeParameterCollector();
+ DartTypeVisitor.visit(type, typeParameterCollector);
+ for (var typeParameter in typeParameterCollector.typeParameters) {
+ if (typeParameter is TypeParameterMember) {
+ var base = typeParameter.declaration;
+ var baseBound = base.bound as TypeImpl;
+ if (baseBound != null) {
+ var baseBoundStr = baseBound.toString(withNullability: true);
+ typeStr += ', ${typeParameter.name} extends ' + baseBoundStr;
+ }
+
+ var bound = typeParameter.bound as TypeImpl;
+ var boundStr = bound.toString(withNullability: true);
+ typeStr += ', ${typeParameter.name} & ' + boundStr;
+ } else {
+ var bound = typeParameter.bound as TypeImpl;
+ if (bound != null) {
+ var boundStr = bound.toString(withNullability: true);
+ typeStr += ', ${typeParameter.name} extends ' + boundStr;
+ }
+ }
+ }
+ return typeStr;
+ }
+
+ String _typeString(TypeImpl type) {
+ if (type == null) return null;
+ return type.toString(withNullability: true) + _typeParametersStr(type);
+ }
+}
+
+class _TypeParameterCollector extends DartTypeVisitor<void> {
+ final Set<TypeParameterElement> typeParameters = Set();
+
+ /// We don't need to print bounds for these type parameters, because
+ /// they are already included into the function type itself, and cannot
+ /// be promoted.
+ final Set<TypeParameterElement> functionTypeParameters = Set();
+
+ @override
+ void defaultDartType(DartType type) {
+ throw UnimplementedError('(${type.runtimeType}) $type');
+ }
+
+ @override
+ void visitDynamicType(DynamicTypeImpl type) {}
+
+ @override
+ void visitFunctionType(FunctionType type) {
+ functionTypeParameters.addAll(type.typeFormals);
+ for (var typeParameter in type.typeFormals) {
+ var bound = typeParameter.bound;
+ if (bound != null) {
+ DartTypeVisitor.visit(bound, this);
+ }
+ }
+ for (var parameter in type.parameters) {
+ DartTypeVisitor.visit(parameter.type, this);
+ }
+ DartTypeVisitor.visit(type.returnType, this);
+ }
+
+ @override
+ void visitInterfaceType(InterfaceType type) {
+ for (var typeArgument in type.typeArguments) {
+ DartTypeVisitor.visit(typeArgument, this);
+ }
+ }
+
+ @override
+ void visitNeverType(NeverTypeImpl type) {}
+
+ @override
+ void visitTypeParameterType(TypeParameterType type) {
+ if (!functionTypeParameters.contains(type.element)) {
+ typeParameters.add(type.element);
+ }
+ }
+
+ @override
+ void visitVoidType(VoidType type) {}
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/class_test.dart b/pkg/analyzer/test/src/dart/resolution/class_test.dart
index 752cb6f..57da4e7 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_test.dart
@@ -154,28 +154,6 @@
assertElement(findNode.simple('foo = 0;'), findElement.setter('foo'));
}
- test_conflictingGenericInterfaces_simple() async {
- await resolveTestCode('''
-class I<T> {}
-class A implements I<int> {}
-class B implements I<String> {}
-class C extends A implements B {}
-''');
- assertTestErrorsWithCodes(
- [CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES]);
- }
-
- test_conflictingGenericInterfaces_viaMixin() async {
- await resolveTestCode('''
-class I<T> {}
-class A implements I<int> {}
-class B implements I<String> {}
-class C extends A with B {}
-''');
- assertTestErrorsWithCodes(
- [CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES]);
- }
-
test_element_allSupertypes() async {
await resolveTestCode(r'''
class A {}
@@ -198,11 +176,11 @@
var d = findElement.class_('D');
var e = findElement.class_('E');
- var typeA = interfaceType(a);
- var typeB = interfaceType(b);
- var typeC = interfaceType(c);
- var typeD = interfaceType(d);
- var typeE = interfaceType(e);
+ var typeA = interfaceTypeStar(a);
+ var typeB = interfaceTypeStar(b);
+ var typeC = interfaceTypeStar(c);
+ var typeD = interfaceTypeStar(d);
+ var typeE = interfaceTypeStar(e);
assertElementTypes(
findElement.class_('X1').allSupertypes,
@@ -244,16 +222,16 @@
assertElementTypes(
findElement.class_('X1').allSupertypes,
[
- interfaceType(a, typeArguments: [stringType]),
+ interfaceTypeStar(a, typeArguments: [stringType]),
objectType
],
);
assertElementTypes(
findElement.class_('X2').allSupertypes,
[
- interfaceType(b, typeArguments: [
+ interfaceTypeStar(b, typeArguments: [
stringType,
- interfaceType(listElement, typeArguments: [intType])
+ interfaceTypeStar(listElement, typeArguments: [intType])
]),
objectType
],
@@ -261,8 +239,8 @@
assertElementTypes(
findElement.class_('X3').allSupertypes,
[
- interfaceType(c, typeArguments: [doubleType]),
- interfaceType(b, typeArguments: [intType, doubleType]),
+ interfaceTypeStar(c, typeArguments: [doubleType]),
+ interfaceTypeStar(b, typeArguments: [intType, doubleType]),
objectType
],
);
@@ -283,7 +261,7 @@
var c = findElement.class_('C');
assertElementTypes(
findElement.class_('X').allSupertypes,
- [interfaceType(a), interfaceType(b), interfaceType(c)],
+ [interfaceTypeStar(a), interfaceTypeStar(b), interfaceTypeStar(c)],
);
}
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
index d09efd3..cacc3459 100644
--- a/pkg/analyzer/test/src/dart/resolution/constant_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -116,4 +116,69 @@
expect(typeArgument.element.enclosingElement, elementF);
assertElementTypeStrings(typeArgument.typeArguments, ['double']);
}
+
+ test_imported_prefixedIdentifier_staticField_class() async {
+ newFile('/test/lib/a.dart', content: r'''
+const a = C.f;
+
+class C {
+ static const int f = 42;
+}
+''');
+ await resolveTestCode(r'''
+import 'a.dart';
+''');
+
+ var import_ = findElement.importFind('package:test/a.dart');
+ var a = import_.topVar('a') as ConstVariableElement;
+ expect(a.computeConstantValue().toIntValue(), 42);
+ }
+
+ test_imported_prefixedIdentifier_staticField_extension() async {
+ newFile('/test/lib/a.dart', content: r'''
+const a = E.f;
+
+extension E on int {
+ static const int f = 42;
+}
+''');
+ await resolveTestCode(r'''
+import 'a.dart';
+''');
+
+ var import_ = findElement.importFind('package:test/a.dart');
+ var a = import_.topVar('a') as ConstVariableElement;
+ expect(a.computeConstantValue().toIntValue(), 42);
+ }
+
+ test_imported_prefixedIdentifier_staticField_mixin() async {
+ newFile('/test/lib/a.dart', content: r'''
+const a = M.f;
+
+class C {}
+
+mixin M on C {
+ static const int f = 42;
+}
+''');
+ await resolveTestCode(r'''
+import 'a.dart';
+''');
+
+ var import_ = findElement.importFind('package:test/a.dart');
+ var a = import_.topVar('a') as ConstVariableElement;
+ expect(a.computeConstantValue().toIntValue(), 42);
+ }
+
+ test_local_prefixedIdentifier_staticField_extension() async {
+ await assertNoErrorsInCode(r'''
+const a = E.f;
+
+extension E on int {
+ static const int f = 42;
+}
+''');
+ var a = findElement.topVar('a') as ConstVariableElement;
+ expect(a.computeConstantValue().toIntValue(), 42);
+ }
}
diff --git a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart b/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
index b8b7e2a..abc3a93 100644
--- a/pkg/analyzer/test/src/dart/resolution/for_element_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/for_element_test.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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'driver_resolution.dart';
@@ -9,13 +11,14 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ForEachElementTest);
+ defineReflectiveTests(ForEachElementWithNnbdTest);
defineReflectiveTests(ForLoopElementTest);
});
}
@reflectiveTest
class ForEachElementTest extends DriverResolutionTest {
- test_declaredIdentifierScope() async {
+ test_withDeclaration_scope() async {
await resolveTestCode(r'''
main() {
<int>[for (var i in [1, 2, 3]) i]; // 1
@@ -33,6 +36,27 @@
findNode.simple('i in [1.1').staticElement,
);
}
+
+ test_withIdentifier_topLevelVariable() async {
+ await assertNoErrorsInCode(r'''
+int v = 0;
+main() {
+ <int>[for (v in [1, 2, 3]) v];
+}
+''');
+ assertElement(
+ findNode.simple('v];'),
+ findElement.topGet('v'),
+ );
+ }
+}
+
+@reflectiveTest
+class ForEachElementWithNnbdTest extends ForEachElementTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = FeatureSet.forTesting(
+ sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
}
@reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart
index 3d89872..774f965 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_type_alias_test.dart
@@ -25,7 +25,7 @@
FunctionType type = findElement.topVar('g').type;
assertElementTypeString(type, 'int Function()');
- var typedefG = findElement.genericTypeAlias('G');
+ var typedefG = findElement.functionTypeAlias('G');
var functionG = typedefG.function;
expect(type.element, functionG);
diff --git a/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart b/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
index ae124eb..e1ff7a0 100644
--- a/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'driver_resolution.dart';
@@ -47,6 +48,17 @@
''');
}
+ test_metadata_typeParameter() async {
+ await assertNoErrorsInCode(r'''
+const a = 42;
+
+Function<@a T>() x;
+''');
+ var T = findNode.typeParameter('T');
+ var annotation = T.declaredElement.metadata[0];
+ expect(annotation.element, findElement.topGet('a'));
+ }
+
/// Test that when multiple [GenericFunctionType]s are used in a
/// [FunctionDeclaration], all of them are resolved correctly.
test_typeAnnotation_function() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart
index 36c3d81..2760699 100644
--- a/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/generic_type_alias_test.dart
@@ -152,7 +152,7 @@
FunctionType type = findElement.topVar('g').type;
assertElementTypeString(type, 'int Function(double)');
- var typedefG = findElement.genericTypeAlias('G');
+ var typedefG = findElement.functionTypeAlias('G');
var functionG = typedefG.function;
expect(type.element, functionG);
@@ -169,7 +169,7 @@
typedef F<T extends A> = B<T> Function<U extends B>(T a, U b);
''');
- var f = findElement.genericTypeAlias('F');
+ var f = findElement.functionTypeAlias('F');
expect(f.typeParameters, hasLength(1));
var t = f.typeParameters[0];
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index 9ca7b0d..f521fdb 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -1160,7 +1160,7 @@
var foo = invocation.function as PrefixedIdentifier;
assertType(foo, 'T Function<T>(T, T)');
- assertElement(foo.identifier, import.topGetter('foo'));
+ assertElement(foo.identifier, import.topGet('foo'));
assertType(foo.identifier, 'T Function<T>(T, T)');
assertImportPrefix(foo.prefix, import.prefix);
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index 942563e..e84b1ab 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -95,7 +95,7 @@
var mElement = findElement.mixin('M');
var aElement = findElement.class_('A');
- assertElementTypes(aElement.mixins, [interfaceType(mElement)]);
+ assertElementTypes(aElement.mixins, [interfaceTypeStar(mElement)]);
var mRef = findNode.typeName('M {} // A');
assertTypeName(mRef, mElement, 'M');
@@ -110,7 +110,7 @@
var mElement = findElement.mixin('M');
var aElement = findElement.class_('A');
- assertElementTypes(aElement.mixins, [interfaceType(mElement)]);
+ assertElementTypes(aElement.mixins, [interfaceTypeStar(mElement)]);
var mRef = findNode.typeName('M;');
assertTypeName(mRef, mElement, 'M');
@@ -129,17 +129,6 @@
assertTypeNull(aRef);
}
- test_conflictingGenericInterfaces() async {
- await assertErrorsInCode('''
-class I<T> {}
-class A implements I<int> {}
-class B implements I<String> {}
-mixin M on A implements B {}
-''', [
- error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 75, 28),
- ]);
- }
-
test_element() async {
await assertNoErrorsInCode(r'''
mixin M {}
@@ -156,7 +145,7 @@
expect(element.isEnum, isFalse);
expect(element.isMixin, isTrue);
expect(element.isMixinApplication, isFalse);
- expect(interfaceType(element).isObject, isFalse);
+ expect(interfaceTypeStar(element).isObject, isFalse);
expect(element.isDartCoreObject, isFalse);
assertElementTypes(element.superclassConstraints, [objectType]);
@@ -178,11 +167,16 @@
var c = findElement.class_('C');
assertElementTypes(
findElement.mixin('M1').allSupertypes,
- [interfaceType(a), interfaceType(b), objectType],
+ [interfaceTypeStar(a), interfaceTypeStar(b), objectType],
);
assertElementTypes(
findElement.mixin('M2').allSupertypes,
- [interfaceType(a), objectType, interfaceType(b), interfaceType(c)],
+ [
+ interfaceTypeStar(a),
+ objectType,
+ interfaceTypeStar(b),
+ interfaceTypeStar(c)
+ ],
);
}
@@ -200,15 +194,15 @@
assertElementTypes(
findElement.mixin('M1').allSupertypes,
[
- interfaceType(a, typeArguments: [intType, doubleType]),
+ interfaceTypeStar(a, typeArguments: [intType, doubleType]),
objectType
],
);
assertElementTypes(
findElement.mixin('M2').allSupertypes,
[
- interfaceType(b, typeArguments: [stringType]),
- interfaceType(a, typeArguments: [intType, stringType]),
+ interfaceTypeStar(b, typeArguments: [stringType]),
+ interfaceTypeStar(a, typeArguments: [intType, stringType]),
objectType
],
);
@@ -357,7 +351,7 @@
var randomElement = mathImport.importedLibrary.getType('Random');
var element = findElement.mixin('M');
- assertElementTypes(element.interfaces, [interfaceType(randomElement)]);
+ assertElementTypes(element.interfaces, [interfaceTypeStar(randomElement)]);
var typeRef = findNode.typeName('Random {}');
assertTypeName(typeRef, randomElement, 'Random',
@@ -920,7 +914,7 @@
var element = findElement.mixin('M');
assertElementTypes(element.superclassConstraints, [
- interfaceType(randomElement),
+ interfaceTypeStar(randomElement),
]);
var typeRef = findNode.typeName('Random {}');
@@ -999,7 +993,7 @@
var a = findElement.mixin('A');
var b = findElement.mixin('B');
assertElementTypes(b.superclassConstraints, [
- interfaceType(a),
+ interfaceTypeStar(a),
]);
}
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 3190200..86ebbb9 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -5,6 +5,8 @@
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/type_system.dart';
+import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'driver_resolution.dart';
@@ -70,6 +72,26 @@
);
}
+ test_library_typeProvider_typeSystem() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+''');
+ await resolveTestCode(r'''
+// @dart = 2.5
+import 'a.dart';
+''');
+ var testLibrary = result.libraryElement;
+ var testTypeSystem = testLibrary.typeSystem as TypeSystemImpl;
+ assertElementTypeString(testLibrary.typeProvider.intType, 'int*');
+ expect(testTypeSystem.isNonNullableByDefault, isFalse);
+
+ var aImport = findElement.importFind('package:test/a.dart');
+ var aLibrary = aImport.importedLibrary;
+ var aTypeSystem = aLibrary.typeSystem as TypeSystemImpl;
+ assertElementTypeString(aLibrary.typeProvider.intType, 'int');
+ expect(aTypeSystem.isNonNullableByDefault, isTrue);
+ }
+
test_local_getterNullAwareAccess_interfaceType() async {
await resolveTestCode(r'''
main() {
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index efd4af8..803474c 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -13,6 +13,7 @@
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/error/hint_codes.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/test_utilities/find_element.dart';
@@ -84,10 +85,7 @@
expect(actual.declaration, same(expectedBase));
- var actualMapString = actual.substitution.map.map(
- (k, v) => MapEntry(k.name, '$v'),
- );
- expect(actualMapString, expectedSubstitution);
+ assertSubstitution(actual.substitution, expectedSubstitution);
}
/// Assert that the given [identifier] is a reference to a class, in the
@@ -154,9 +152,7 @@
}
void assertElementTypeString(DartType type, String expected) {
- TypeImpl typeImpl = type;
- expect(typeImpl.toString(withNullability: typeToStringWithNullability),
- expected);
+ expect(typeString(type), expected);
}
void assertElementTypeStrings(List<DartType> types, List<String> expected) {
@@ -275,8 +271,15 @@
expectedPrefix: expectedPrefix);
}
- void assertInvokeType(InvocationExpression node, String expected) {
- TypeImpl actual = node.staticInvokeType;
+ void assertInvokeType(Expression node, String expected) {
+ DartType actual;
+ if (node is BinaryExpression) {
+ actual = node.staticInvokeType;
+ } else if (node is InvocationExpression) {
+ actual = node.staticInvokeType;
+ } else {
+ fail('Unsupported node: (${node.runtimeType}) $node');
+ }
expect(typeString(actual), expected);
}
@@ -307,10 +310,7 @@
var actual = actualElement as Member;
expect(actual.declaration, same(expectedBase));
- var actualMapString = actual.substitution.map.map(
- (k, v) => MapEntry(k.name, '$v'),
- );
- expect(actualMapString, expectedSubstitution);
+ assertSubstitution(actual.substitution, expectedSubstitution);
}
void assertMethodInvocation(
@@ -373,6 +373,15 @@
expect(expression.staticParameterElement, expected);
}
+ void assertParameterType(Expression expression, String expected) {
+ var parameterElement = expression.staticParameterElement;
+ if (expected == null) {
+ expect(parameterElement, isNull);
+ } else {
+ assertElementTypeString(parameterElement.type, expected);
+ }
+ }
+
void assertPropertyAccess(
PropertyAccess access,
Element expectedElement,
@@ -382,6 +391,16 @@
assertType(access, expectedType);
}
+ void assertSubstitution(
+ MapSubstitution substitution,
+ Map<String, String> expected,
+ ) {
+ var actualMapString = substitution.map.map(
+ (k, v) => MapEntry(k.name, '$v'),
+ );
+ expect(actualMapString, expected);
+ }
+
void assertSuperExpression(SuperExpression superExpression) {
// TODO(scheglov) I think `super` does not have type itself.
// It is just a signal to look for implemented method in the supertype.
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
index ec7660c..2e27d71 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
@@ -49,4 +49,13 @@
''');
assertInvokeType(findNode.methodInvocation('d)'), 'bool Function()');
}
+
+ test_type() async {
+ await assertNoErrorsInCode('''
+main(bool b) {
+ return b ? 42 : null;
+}
+''');
+ assertType(findNode.conditionalExpression('b ?'), 'int?');
+ }
}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
new file mode 100644
index 0000000..0b63163
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2019, 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.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(FunctionExpressionTest);
+ defineReflectiveTests(FunctionExpressionWithNnbdTest);
+ });
+}
+
+@reflectiveTest
+class FunctionExpressionTest extends DriverResolutionTest {
+ test_returnType_notNullable() async {
+ await resolveTestCode('''
+var v = (bool b) {
+ if (b) return 0;
+ return 1.2;
+};
+''');
+ var element = findNode.functionExpression('(bool').declaredElement;
+ assertElementTypeString(element.returnType, 'num');
+ }
+
+ test_returnType_null_hasReturn() async {
+ await resolveTestCode('''
+var v = (bool b) {
+ if (b) return;
+};
+''');
+ var element = findNode.functionExpression('(bool').declaredElement;
+ assertElementTypeString(element.returnType, 'Null');
+ }
+
+ test_returnType_null_noReturn() async {
+ await resolveTestCode('''
+var v = () {};
+''');
+ var element = findNode.functionExpression('() {}').declaredElement;
+ assertElementTypeString(element.returnType, 'Null');
+ }
+
+ test_returnType_nullable() async {
+ await resolveTestCode('''
+var v = (bool b) {
+ if (b) return 0;
+};
+''');
+ var element = findNode.functionExpression('(bool').declaredElement;
+ if (typeToStringWithNullability) {
+ assertElementTypeString(element.returnType, 'int?');
+ } else {
+ assertElementTypeString(element.returnType, 'int');
+ }
+ }
+}
+
+@reflectiveTest
+class FunctionExpressionWithNnbdTest extends FunctionExpressionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
index a2f10f6..d5ebe59 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../driver_resolution.dart';
@@ -9,6 +11,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ListLiteralTest);
+ defineReflectiveTests(ListLiteralWithNnbdTest);
});
}
@@ -283,3 +286,35 @@
assertType(findNode.listLiteral('['), 'List<num>');
}
}
+
+@reflectiveTest
+class ListLiteralWithNnbdTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ test_nested_hasNull_1() async {
+ await assertNoErrorsInCode('''
+main() {
+ [[0], null];
+}
+''');
+ assertType(findNode.listLiteral('[0'), 'List<int>');
+ assertType(findNode.listLiteral('[[0'), 'List<List<int>?>');
+ }
+
+ test_nested_hasNull_2() async {
+ await assertNoErrorsInCode('''
+main() {
+ [[0], [1, null]];
+}
+''');
+ assertType(findNode.listLiteral('[0'), 'List<int>');
+ assertType(findNode.listLiteral('[1,'), 'List<int?>');
+ assertType(findNode.listLiteral('[[0'), 'List<List<int?>>');
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
index baeec95..05e682f 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
@@ -8,6 +8,7 @@
import 'conditional_expression_test.dart' as conditional_expression;
import 'equality_expressions_test.dart' as equality_expressions;
import 'extension_methods_test.dart' as extension_methods;
+import 'function_expression_test.dart' as function_expression;
import 'list_literal_test.dart' as list_literal;
import 'logical_boolean_expressions_test.dart' as logical_boolean_expressions;
import 'map_literal_test.dart' as map_literal;
@@ -24,6 +25,7 @@
conditional_expression.main();
equality_expressions.main();
extension_methods.main();
+ function_expression.main();
list_literal.main();
logical_boolean_expressions.main();
map_literal.main();
diff --git a/pkg/analyzer/test/src/diagnostics/conflicting_generic_interfaces_test.dart b/pkg/analyzer/test/src/diagnostics/conflicting_generic_interfaces_test.dart
new file mode 100644
index 0000000..b9a0264
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/conflicting_generic_interfaces_test.dart
@@ -0,0 +1,127 @@
+// Copyright (c) 2019, 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.
+
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConflictingGenericInterfacesTest);
+ defineReflectiveTests(ConflictingGenericInterfacesWithNnbdTest);
+ });
+}
+
+@reflectiveTest
+class ConflictingGenericInterfacesTest extends DriverResolutionTest {
+ disabled_test_hierarchyLoop_infinite() async {
+ // There is an interface conflict here due to a loop in the class
+ // hierarchy leading to an infinite set of implemented types; this loop
+ // shouldn't cause non-termination.
+
+ // TODO(paulberry): this test is currently disabled due to non-termination
+ // bugs elsewhere in the analyzer.
+ await assertErrorsInCode('''
+class A<T> implements B<List<T>> {}
+class B<T> implements A<List<T>> {}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 0, 0),
+ ]);
+ }
+
+ test_class_extends_implements() async {
+ await assertErrorsInCode('''
+class I<T> {}
+class A implements I<int> {}
+class B implements I<String> {}
+class C extends A implements B {}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 75, 33),
+ ]);
+ }
+
+ test_class_extends_with() async {
+ await assertErrorsInCode('''
+class I<T> {}
+class A implements I<int> {}
+class B implements I<String> {}
+class C extends A with B {}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 75, 27),
+ ]);
+ }
+
+ test_classTypeAlias_extends_with() async {
+ await assertErrorsInCode('''
+class I<T> {}
+class A implements I<int> {}
+mixin M implements I<String> {}
+class C = A with M;
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 75, 19),
+ ]);
+ }
+
+ test_mixin_on_implements() async {
+ await assertErrorsInCode('''
+class I<T> {}
+class A implements I<int> {}
+class B implements I<String> {}
+mixin M on A implements B {}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 75, 28),
+ ]);
+ }
+}
+
+@reflectiveTest
+class ConflictingGenericInterfacesWithNnbdTest
+ extends ConflictingGenericInterfacesTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
+
+ test_class_extends_implements_nullability() async {
+ await assertErrorsInCode('''
+class I<T> {}
+class A implements I<int> {}
+class B implements I<int?> {}
+class C extends A implements B {}
+''', [
+ error(CompileTimeErrorCode.CONFLICTING_GENERIC_INTERFACES, 73, 33),
+ ]);
+ }
+
+ test_class_extends_implements_optOut() async {
+ newFile('/test/lib/a.dart', content: r'''
+class I<T> {}
+class A implements I<int> {}
+class B implements I<int?> {}
+''');
+ await assertNoErrorsInCode('''
+// @dart = 2.5
+import 'a.dart';
+
+class C extends A implements B {}
+''');
+ }
+
+ test_class_extends_optIn_implements_optOut() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A<T> {}
+
+class B extends A<int> {}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class C extends B implements A<int> {}
+''');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
index 0ed9acc..5e19d96 100644
--- a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
@@ -51,9 +51,6 @@
''');
}
- @FailingTest(
- reason: 'The type of the parameterElement for `3` is non-nullable',
- )
test_optOut() async {
await assertNoErrorsInCode('''
// @dart = 2.2
diff --git a/pkg/analyzer/test/src/diagnostics/deferred_import_of_extension_test.dart b/pkg/analyzer/test/src/diagnostics/deferred_import_of_extension_test.dart
index 39ae942..bfd4e14 100644
--- a/pkg/analyzer/test/src/diagnostics/deferred_import_of_extension_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/deferred_import_of_extension_test.dart
@@ -71,4 +71,12 @@
}
''');
}
+
+ test_invalidUri() {
+ assertErrorsInCode('''
+import '' deferred as foo;
+''', [
+ error(CompileTimeErrorCode.INVALID_URI, 7, 2),
+ ]);
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/mixed_return_types_test.dart b/pkg/analyzer/test/src/diagnostics/mixed_return_types_test.dart
deleted file mode 100644
index 8cbb93f..0000000
--- a/pkg/analyzer/test/src/diagnostics/mixed_return_types_test.dart
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2019, 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.
-
-import 'package:analyzer/src/error/codes.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../dart/resolution/driver_resolution.dart';
-
-main() {
- defineReflectiveSuite(() {
- defineReflectiveTests(MixedReturnTypesTest);
- });
-}
-
-@reflectiveTest
-class MixedReturnTypesTest extends DriverResolutionTest {
- test_method() async {
- await assertErrorsInCode('''
-class C {
- m(int x) {
- if (x < 0) {
- return;
- }
- return 0;
- }
-}
-''', [
- error(StaticWarningCode.MIXED_RETURN_TYPES, 46, 6),
- error(StaticWarningCode.MIXED_RETURN_TYPES, 64, 6),
- ]);
- }
-
- test_topLevelFunction() async {
- await assertErrorsInCode('''
-f(int x) {
- if (x < 0) {
- return;
- }
- return 0;
-}
-''', [
- error(StaticWarningCode.MIXED_RETURN_TYPES, 30, 6),
- error(StaticWarningCode.MIXED_RETURN_TYPES, 44, 6),
- ]);
- }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart b/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart
index 45a9406..546aea3 100644
--- a/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_null_opt_out_test.dart
@@ -4,8 +4,13 @@
//import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/test_utilities/find_element.dart';
+import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/driver_resolution.dart';
@@ -21,7 +26,736 @@
@override
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
..contextFeatures = new FeatureSet.forTesting(
- sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+ sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ ImportFindElement get _import_a {
+ return findElement.importFind('package:test/a.dart');
+ }
+
+ test_assignment_indexExpression() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ void operator[]=(int a, int b) {}
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a[null] = null;
+}
+''');
+ var assignment = findNode.assignment('= null;');
+ assertType(assignment, 'Null*');
+
+ var indexExpression = assignment.leftHandSide as IndexExpression;
+ assertType(indexExpression, 'int*');
+
+ var element = indexExpression.staticElement;
+ _assertLegacyMember(element, _import_a.method('[]='));
+ }
+
+ test_assignment_prefixedIdentifier_instanceTarget_class_field() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo = 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a.foo = 0;
+}
+''');
+ var assignment = findNode.assignment('foo = 0');
+ assertType(assignment, 'int*');
+
+ PrefixedIdentifier prefixedIdentifier = assignment.leftHandSide;
+ assertType(prefixedIdentifier, 'int*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement setter = identifier.staticElement;
+ _assertLegacyMember(setter, _import_a.setter('foo'));
+ }
+
+ test_assignment_prefixedIdentifier_instanceTarget_extension_setter() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+extension E on A {
+ void set foo(int _) {}
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a.foo = 0;
+}
+''');
+ var assignment = findNode.assignment('foo = 0');
+ assertType(assignment, 'int*');
+
+ PrefixedIdentifier prefixedIdentifier = assignment.leftHandSide;
+ assertType(prefixedIdentifier, 'int*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement setter = identifier.staticElement;
+ _assertLegacyMember(setter, _import_a.setter('foo'));
+ }
+
+ test_assignment_prefixedIdentifier_staticTarget_class_field() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ static int foo = 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ A.foo = 0;
+}
+''');
+ var assignment = findNode.assignment('foo = 0');
+ assertType(assignment, 'int*');
+
+ PrefixedIdentifier prefixedIdentifier = assignment.leftHandSide;
+ assertType(prefixedIdentifier, 'int*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement setter = identifier.staticElement;
+ _assertLegacyMember(setter, _import_a.setter('foo'));
+ }
+
+ test_assignment_prefixedIdentifier_staticTarget_extension_field() async {
+ newFile('/test/lib/a.dart', content: r'''
+extension E on int {
+ static int foo = 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ E.foo = 0;
+}
+''');
+ var assignment = findNode.assignment('foo = 0');
+ assertType(assignment, 'int*');
+
+ PrefixedIdentifier prefixedIdentifier = assignment.leftHandSide;
+ assertType(prefixedIdentifier, 'int*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement setter = identifier.staticElement;
+ _assertLegacyMember(setter, _import_a.setter('foo'));
+ }
+
+ test_assignment_prefixedIdentifier_topLevelVariable() async {
+ newFile('/test/lib/a.dart', content: r'''
+int foo = 0;
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart' as p;
+
+main() {
+ p.foo = 0;
+}
+''');
+ var assignment = findNode.assignment('foo = 0');
+ assertType(assignment, 'int*');
+
+ PrefixedIdentifier prefixedIdentifier = assignment.leftHandSide;
+ assertType(prefixedIdentifier, 'int*');
+
+ PropertyAccessorElement setter = prefixedIdentifier.staticElement;
+ _assertLegacyMember(setter, _import_a.topSet('foo'));
+ }
+
+ test_assignment_propertyAccess_class_field() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo = 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ A().foo = 0;
+}
+''');
+ var assignment = findNode.assignment('foo = 0');
+ assertType(assignment, 'int*');
+
+ PropertyAccess propertyAccess = assignment.leftHandSide;
+ assertType(propertyAccess, 'int*');
+
+ PropertyAccessorElement setter = propertyAccess.propertyName.staticElement;
+ _assertLegacyMember(setter, _import_a.setter('foo'));
+ }
+
+ test_assignment_propertyAccess_extension_setter() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+extension E on A {
+ void set foo(int a) {}
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ A().foo = 0;
+}
+''');
+ var assignment = findNode.assignment('foo = 0');
+ assertType(assignment, 'int*');
+
+ PropertyAccess propertyAccess = assignment.leftHandSide;
+ assertType(propertyAccess, 'int*');
+
+ PropertyAccessorElement setter = propertyAccess.propertyName.staticElement;
+ _assertLegacyMember(setter, _import_a.setter('foo'));
+ }
+
+ test_assignment_propertyAccess_extensionOverride_setter() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+extension E on A {
+ void set foo(int a) {}
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ E(a).foo = 0;
+}
+''');
+ var assignment = findNode.assignment('foo = 0');
+ assertType(assignment, 'int*');
+
+ PropertyAccess propertyAccess = assignment.leftHandSide;
+ assertType(propertyAccess, 'int*');
+
+ PropertyAccessorElement setter = propertyAccess.propertyName.staticElement;
+ _assertLegacyMember(setter, _import_a.setter('foo'));
+ }
+
+ test_assignment_propertyAccess_superTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo = 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class B extends A {
+ void bar() {
+ super.foo = 0;
+ }
+}
+''');
+ var assignment = findNode.assignment('foo = 0');
+ assertType(assignment, 'int*');
+
+ PropertyAccess propertyAccess = assignment.leftHandSide;
+ assertType(propertyAccess, 'int*');
+
+ PropertyAccessorElement setter = propertyAccess.propertyName.staticElement;
+ _assertLegacyMember(setter, _import_a.setter('foo'));
+ }
+
+ test_assignment_simpleIdentifier_topLevelVariable() async {
+ newFile('/test/lib/a.dart', content: r'''
+int foo = 0;
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ foo = null;
+}
+''');
+ var assignment = findNode.assignment('foo =');
+ assertType(assignment, 'Null*');
+
+ SimpleIdentifier identifier = assignment.leftHandSide;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement setter = identifier.staticElement;
+ _assertLegacyMember(setter, _import_a.topSet('foo'));
+ }
+
+ test_binaryExpression() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int operator+(int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a + null;
+}
+''');
+ var binaryExpression = findNode.binary('a +');
+ assertInvokeType(binaryExpression, 'int* Function(int*)*');
+ assertType(binaryExpression, 'int*');
+
+ MethodElement element = binaryExpression.staticElement;
+ _assertLegacyMember(element, _import_a.method('+'));
+ }
+
+ test_functionExpressionInvocation() async {
+ newFile('/test/lib/a.dart', content: r'''
+int Function(int, int?)? foo;
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ foo(null, null);
+}
+''');
+ var invocation = findNode.functionExpressionInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*, int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*, int*)*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.topGet('foo'));
+ }
+
+ test_functionExpressionInvocation_call() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int call(int a, int? b) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a(null, null);
+}
+''');
+ var invocation = findNode.functionExpressionInvocation('a(null');
+ assertInvokeType(invocation, 'int* Function(int*, int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = invocation.function;
+ assertType(identifier, 'A*');
+
+ MethodElement element = invocation.staticElement;
+ _assertLegacyMember(element, _import_a.method('call'));
+ }
+
+ test_functionExpressionInvocation_extension_staticTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+extension E on int {
+ static int Function(int) get foo => (_) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ E.foo(null);
+}
+''');
+ var invocation = findNode.functionExpressionInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*)*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.getter('foo'));
+ }
+
+ test_instanceCreation() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ A(int a, int? b);
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ A(null, null);
+}
+''');
+ var instanceCreation = findNode.instanceCreation('A(null');
+ assertType(instanceCreation, 'A*');
+
+ _assertLegacyMember(
+ instanceCreation.staticElement,
+ _import_a.unnamedConstructor('A'),
+ );
+ }
+
+ test_instanceCreation_generic() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A<T> {
+ A(T a, T? b);
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ A<int>(null, null);
+}
+''');
+ var instanceCreation = findNode.instanceCreation('A<int>(null');
+ assertType(instanceCreation, 'A<int*>*');
+
+ _assertLegacyMember(
+ instanceCreation.staticElement,
+ _import_a.unnamedConstructor('A'),
+ expectedSubstitution: {'T': 'int'},
+ );
+ }
+
+ test_methodInvocation_extension_functionTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+extension E on void Function() {
+ int foo(int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(void Function() a) {
+ a.foo(null);
+}
+''');
+ var invocation = findNode.methodInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*)*');
+
+ MethodElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.method('foo'));
+ }
+
+ test_methodInvocation_extension_interfaceTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+extension E on int {
+ int foo(int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ 0.foo(null);
+}
+''');
+ var invocation = findNode.methodInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*)*');
+
+ MethodElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.method('foo'));
+ }
+
+ test_methodInvocation_extension_nullTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+extension E on A {
+ int foo(int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class B extends A {
+ void bar() {
+ foo(null);
+ }
+}
+''');
+ var invocation = findNode.methodInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*)*');
+
+ MethodElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.method('foo'));
+ }
+
+ test_methodInvocation_extension_staticTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+extension E on int {
+ static int foo(int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ E.foo(null);
+}
+''');
+ var invocation = findNode.methodInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*)*');
+
+ MethodElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.method('foo'));
+ }
+
+ test_methodInvocation_extensionOverride() async {
+ newFile('/test/lib/a.dart', content: r'''
+extension E on int {
+ int foo(int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ E(0).foo(null);
+}
+''');
+ var invocation = findNode.methodInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*)*');
+
+ MethodElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.method('foo'));
+ }
+
+ test_methodInvocation_function() async {
+ newFile('/test/lib/a.dart', content: r'''
+int foo(int a, int? b) => 0;
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ foo(null, null);
+}
+''');
+ var invocation = findNode.methodInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*, int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*, int*)*');
+
+ FunctionElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.topFunction('foo'));
+ }
+
+ test_methodInvocation_function_prefixed() async {
+ newFile('/test/lib/a.dart', content: r'''
+int foo(int a, int? b) => 0;
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart' as p;
+
+main() {
+ p.foo(null, null);
+}
+''');
+ var invocation = findNode.methodInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*, int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*, int*)*');
+
+ FunctionElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.topFunction('foo'));
+ }
+
+ test_methodInvocation_method_cascade() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo(int a, int? b) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a..foo(null, null);
+}
+''');
+ var invocation = findNode.methodInvocation('foo(');
+ assertInvokeType(invocation, 'int* Function(int*, int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*, int*)*');
+
+ MethodElement element = identifier.staticElement;
+ assertElementTypeString(element.type, 'int* Function(int*, int*)*');
+ }
+
+ test_methodInvocation_method_interfaceTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo(int a, int? b) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a.foo(null, null);
+}
+''');
+ var invocation = findNode.methodInvocation('a.foo');
+ assertInvokeType(invocation, 'int* Function(int*, int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*, int*)*');
+
+ MethodElement element = identifier.staticElement;
+ assertElementTypeString(element.type, 'int* Function(int*, int*)*');
+ }
+
+ test_methodInvocation_method_nullTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo(int a, int? b) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class B extends A {
+ m() {
+ foo(null, null);
+ }
+}
+''');
+ var invocation = findNode.methodInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*, int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*, int*)*');
+
+ MethodElement element = identifier.staticElement;
+ assertElementTypeString(element.type, 'int* Function(int*, int*)*');
+ }
+
+ test_methodInvocation_method_staticTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ static int foo(int a, int? b) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ A.foo(null, null);
+}
+''');
+ var invocation = findNode.methodInvocation('A.foo');
+ assertInvokeType(invocation, 'int* Function(int*, int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*, int*)*');
+
+ MethodElement element = identifier.staticElement;
+ assertElementTypeString(element.type, 'int* Function(int*, int*)*');
+ }
+
+ test_methodInvocation_method_superTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo(int a, int? b) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class B extends A {
+ m() {
+ super.foo(null, null);
+ }
+}
+''');
+ var invocation = findNode.methodInvocation('foo');
+ assertInvokeType(invocation, 'int* Function(int*, int*)*');
+ assertType(invocation, 'int*');
+
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*, int*)*');
+
+ MethodElement element = identifier.staticElement;
+ assertElementTypeString(element.type, 'int* Function(int*, int*)*');
+ }
test_nnbd_optOut_invalidSyntax() async {
await assertErrorsInCode('''
@@ -41,9 +775,7 @@
''');
}
- @failingTest
test_nnbd_optOut_transformsOptedInSignatures() async {
- // Failing because we don't transform opted out signatures.
await assertNoErrorsInCode('''
// @dart = 2.2
f(String x) {
@@ -51,4 +783,479 @@
}
''');
}
+
+ test_postfixExpression() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ A operator+(int a) => this;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a++;
+}
+''');
+ var prefixExpression = findNode.postfix('a++');
+ assertType(prefixExpression, 'A*');
+
+ MethodElement element = prefixExpression.staticElement;
+ _assertLegacyMember(element, _import_a.method('+'));
+ }
+
+ test_prefixExpression() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int operator-() => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ -a;
+}
+''');
+ var prefixExpression = findNode.prefix('-a');
+ assertType(prefixExpression, 'int*');
+
+ MethodElement element = prefixExpression.staticElement;
+ _assertLegacyMember(element, _import_a.method('unary-'));
+ }
+
+ test_read_indexExpression_class() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int operator[](int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a[null];
+}
+''');
+ var indexExpression = findNode.index('a[');
+ assertType(indexExpression, 'int*');
+
+ MethodElement element = indexExpression.staticElement;
+ _assertLegacyMember(element, _import_a.method('[]'));
+ }
+
+ test_read_prefixedIdentifier_instanceTarget_class_field() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a.foo;
+}
+''');
+ var prefixedIdentifier = findNode.prefixed('a.foo');
+ assertType(prefixedIdentifier, 'int*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.getter('foo'));
+ }
+
+ test_read_prefixedIdentifier_instanceTarget_extension_getter() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+extension E on A {
+ int get foo => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ a.foo;
+}
+''');
+ var prefixedIdentifier = findNode.prefixed('a.foo');
+ assertType(prefixedIdentifier, 'int*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.getter('foo'));
+ }
+
+ test_read_prefixedIdentifier_staticTarget_class_field() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ static int foo;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ A.foo;
+}
+''');
+ var prefixedIdentifier = findNode.prefixed('A.foo');
+ assertType(prefixedIdentifier, 'int*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.getter('foo'));
+ }
+
+ test_read_prefixedIdentifier_staticTarget_class_method() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ static int foo(int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ A.foo;
+}
+''');
+ var prefixedIdentifier = findNode.prefixed('A.foo');
+ assertType(prefixedIdentifier, 'int* Function(int*)*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int* Function(int*)*');
+
+ MethodElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.method('foo'));
+ }
+
+ test_read_prefixedIdentifier_staticTarget_extension_field() async {
+ newFile('/test/lib/a.dart', content: r'''
+extension E {
+ static int foo;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ E.foo;
+}
+''');
+ var prefixedIdentifier = findNode.prefixed('E.foo');
+ assertType(prefixedIdentifier, 'int*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.getter('foo'));
+ }
+
+ test_read_prefixedIdentifier_staticTarget_extension_method() async {
+ newFile('/test/lib/a.dart', content: r'''
+extension E {
+ static int foo(int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ E.foo;
+}
+''');
+ var prefixedIdentifier = findNode.prefixed('E.foo');
+ assertType(prefixedIdentifier, 'int* Function(int*)*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int* Function(int*)*');
+
+ MethodElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.method('foo'));
+ }
+
+ test_read_prefixedIdentifier_topLevelVariable() async {
+ newFile('/test/lib/a.dart', content: r'''
+int foo = 0;
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart' as p;
+
+main() {
+ p.foo;
+}
+''');
+ var prefixedIdentifier = findNode.prefixed('p.foo');
+ assertType(prefixedIdentifier, 'int*');
+
+ var identifier = prefixedIdentifier.identifier;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.topGet('foo'));
+ }
+
+ test_read_propertyAccessor_class_field() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo = 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ A().foo;
+}
+''');
+ var propertyAccess = findNode.propertyAccess('foo');
+ assertType(propertyAccess, 'int*');
+
+ var identifier = propertyAccess.propertyName;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.getter('foo'));
+ }
+
+ test_read_propertyAccessor_class_method() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo() => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ A().foo;
+}
+''');
+ var propertyAccess = findNode.propertyAccess('foo');
+ assertType(propertyAccess, 'int* Function()*');
+
+ var identifier = propertyAccess.propertyName;
+ assertType(identifier, 'int* Function()*');
+
+ MethodElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.method('foo'));
+ }
+
+ test_read_propertyAccessor_extensionOverride_getter() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+extension E on A {
+ int get foo => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main(A a) {
+ E(a).foo;
+}
+''');
+ var propertyAccess = findNode.propertyAccess('foo');
+ assertType(propertyAccess, 'int*');
+
+ var identifier = propertyAccess.propertyName;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.getter('foo'));
+ }
+
+ test_read_propertyAccessor_superTarget() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo = 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class B extends A {
+ void bar() {
+ super.foo;
+ }
+}
+''');
+ var propertyAccess = findNode.propertyAccess('foo');
+ assertType(propertyAccess, 'int*');
+
+ var identifier = propertyAccess.propertyName;
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.getter('foo'));
+ }
+
+ test_read_simpleIdentifier_class_field() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo = 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class B extends A {
+ void bar() {
+ foo;
+ }
+}
+''');
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.getter('foo'));
+ }
+
+ test_read_simpleIdentifier_class_method() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ int foo(int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class B extends A {
+ void bar() {
+ foo;
+ }
+}
+''');
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*)*');
+
+ MethodElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.method('foo'));
+ }
+
+ test_read_simpleIdentifier_extension_getter() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+extension E on A {
+ int get foo => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class B extends A {
+ void bar() {
+ foo;
+ }
+}
+''');
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.getter('foo'));
+ }
+
+ test_read_simpleIdentifier_extension_method() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {}
+extension E on A {
+ int foo(int a) => 0;
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class B extends A {
+ void bar() {
+ foo;
+ }
+}
+''');
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int* Function(int*)*');
+
+ MethodElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.method('foo'));
+ }
+
+ test_read_simpleIdentifier_topLevelVariable() async {
+ newFile('/test/lib/a.dart', content: r'''
+int foo = 0;
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+main() {
+ foo;
+}
+''');
+ var identifier = findNode.simple('foo');
+ assertType(identifier, 'int*');
+
+ PropertyAccessorElement element = identifier.staticElement;
+ _assertLegacyMember(element, _import_a.topGet('foo'));
+ }
+
+ test_superConstructorInvocation() async {
+ newFile('/test/lib/a.dart', content: r'''
+class A {
+ A(int a, int? b);
+}
+''');
+ await assertNoErrorsInCode(r'''
+// @dart = 2.5
+import 'a.dart';
+
+class B extends A {
+ B() : super(null, null);
+}
+''');
+ var instanceCreation = findNode.superConstructorInvocation('super(');
+
+ _assertLegacyMember(
+ instanceCreation.staticElement,
+ _import_a.unnamedConstructor('A'),
+ );
+ }
+
+ void _assertLegacyMember(
+ Element actualElement,
+ Element declaration, {
+ Map<String, String> expectedSubstitution = const {},
+ }) {
+ var actualMember = actualElement as Member;
+ expect(actualMember.declaration, same(declaration));
+ expect(actualMember.isLegacy, isTrue);
+ assertSubstitution(actualMember.substitution, expectedSubstitution);
+ }
}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index d003c07..d7b3a4f 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -30,6 +30,8 @@
import 'cast_to_non_type_test.dart' as cast_to_non_type;
import 'concrete_class_with_abstract_member_test.dart'
as concrete_class_with_abstract_member;
+import 'conflicting_generic_interfaces_test.dart'
+ as conflicting_generic_interfaces;
import 'conflicting_static_and_instance_test.dart'
as conflicting_static_and_instance;
import 'const_constructor_param_type_mismatch_test.dart'
@@ -193,7 +195,6 @@
import 'missing_js_lib_annotation_test.dart' as missing_js_lib_annotation;
import 'missing_required_param_test.dart' as missing_required_param;
import 'missing_return_test.dart' as missing_return;
-import 'mixed_return_types_test.dart' as mixed_return_types;
import 'mixin_of_disallowed_class_test.dart' as mixin_of_disallowed_class;
import 'mixin_of_non_class_test.dart' as mixin_of_non_class;
import 'mixin_on_sealed_class_test.dart' as mixin_on_sealed_class;
@@ -388,6 +389,7 @@
case_block_not_terminated.main();
cast_to_non_type.main();
concrete_class_with_abstract_member.main();
+ conflicting_generic_interfaces.main();
conflicting_static_and_instance.main();
const_constructor_param_type_mismatch.main();
const_constructor_with_mixin_with_field.main();
@@ -497,7 +499,6 @@
missing_js_lib_annotation.main();
missing_required_param.main();
missing_return.main();
- mixed_return_types.main();
mixin_of_disallowed_class.main();
mixin_of_non_class.main();
mixin_on_sealed_class.main();
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
index 84a31f0..502c6a3 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
@@ -157,11 +157,4 @@
AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
..contextFeatures = new FeatureSet.forTesting(
sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
-
- @failingTest
- @override
- test_forElement_inList_insideElement() async {
- // todo: fails w/ StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
- await super.test_forElement_inList_insideElement();
- }
}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
index ef38d33..66f4f04 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
@@ -164,6 +164,15 @@
]);
}
+ test_fieldImplicitGetter_isUsed() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int _g;
+ int get g => this._g;
+}
+''');
+ }
+
test_functionLocal_isUsed_closure() async {
await assertNoErrorsInCode(r'''
main() {
@@ -303,6 +312,27 @@
]);
}
+ test_getter_isUsed_invocation_deepSubclass() async {
+ await assertNoErrorsInCode(r'''
+abstract class A {
+ String get _debugName;
+
+ String toString() {
+ return _debugName;
+ }
+}
+
+class B extends A {
+ @override
+ String get _debugName => "B";
+}
+
+class C extends B {
+ String get _debugName => "C";
+}
+''');
+ }
+
test_getter_isUsed_invocation_implicitThis() async {
await assertNoErrorsInCode(r'''
class A {
@@ -314,6 +344,42 @@
''');
}
+ test_getter_isUsed_invocation_parameterized() async {
+ await assertNoErrorsInCode(r'''
+class A<T> {
+ List<int> _list = List(1);
+ int get _item => _list.first;
+ set _item(int item) => _list[0] = item;
+}
+class B<T> {
+ A<T> a;
+}
+void main() {
+ B<int> b = B();
+ b.a._item = 3;
+ print(b.a._item == 7);
+}
+''');
+ }
+
+ test_getter_isUsed_invocation_parameterized_subclass() async {
+ await assertNoErrorsInCode(r'''
+abstract class A<T> {
+ T get _defaultThing;
+ T _thing;
+
+ void main() {
+ _thing ??= _defaultThing;
+ print(_thing);
+ }
+}
+class B extends A<int> {
+ @override
+ int get _defaultThing => 7;
+}
+''');
+ }
+
test_getter_isUsed_invocation_PrefixedIdentifier() async {
await assertNoErrorsInCode(r'''
class A {
@@ -336,6 +402,43 @@
''');
}
+ test_getter_isUsed_invocation_subclass_plusPlus() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ int __a = 0;
+ int get _a => __a;
+ void set _a(int val) {
+ __a = val;
+ }
+ int b() => _a++;
+}
+class B extends A {
+ @override
+ int get _a => 3;
+}
+''');
+ }
+
+ test_getter_notUsed_invocation_subclass() async {
+ await assertErrorsInCode(r'''
+class A {
+ int __a = 0;
+ int get _a => __a;
+ void set _a(int val) {
+ __a = val;
+ }
+ int b() => _a = 7;
+}
+class B extends A {
+ @override
+ int get _a => 3;
+}
+''', [
+ error(HintCode.UNUSED_ELEMENT, 35, 2),
+ error(HintCode.UNUSED_ELEMENT, 155, 2),
+ ]);
+ }
+
test_getter_notUsed_noReference() async {
await assertErrorsInCode(r'''
class A {
@@ -358,6 +461,20 @@
]);
}
+ test_method_isNotUsed_hasSameNameAsUsed() async {
+ await assertErrorsInCode(r'''
+class A {
+ void _m1() {}
+}
+class B {
+ void public() => _m1();
+ void _m1() {}
+}
+''', [
+ error(HintCode.UNUSED_ELEMENT, 17, 3),
+ ]);
+ }
+
test_method_isUsed_hasReference_implicitThis() async {
await assertNoErrorsInCode(r'''
class A {
@@ -407,6 +524,32 @@
''');
}
+ test_method_isUsed_invocation_fromMixinApplication() async {
+ await assertNoErrorsInCode(r'''
+mixin A {
+ _m() {}
+}
+class C with A {
+ useMethod() {
+ _m();
+ }
+}
+''');
+ }
+
+ test_method_isUsed_invocation_fromMixinWithConstraint() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ _m() {}
+}
+mixin M on A {
+ useMethod() {
+ _m();
+ }
+}
+''');
+ }
+
test_method_isUsed_invocation_implicitThis() async {
await assertNoErrorsInCode(r'''
class A {
diff --git a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
index fa17061..2bb674f 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
@@ -18,7 +18,7 @@
@override
bool get enableUnusedElement => true;
- test_unusedField_isUsed_argument() async {
+ test_isUsed_argument() async {
await assertNoErrorsInCode(r'''
class A {
int _f = 0;
@@ -30,7 +30,23 @@
''');
}
- test_unusedField_isUsed_reference_implicitThis() async {
+ test_isUsed_parameterized_subclass() async {
+ await assertNoErrorsInCode(r'''
+class A<T extends num> {
+ T _f;
+ A._(this._f);
+}
+class B extends A<int> {
+ B._(int f) : super._(f);
+}
+void main() {
+ B b = B._(7);
+ print(b._f == 7);
+}
+''');
+ }
+
+ test_isUsed_reference_implicitThis() async {
await assertNoErrorsInCode(r'''
class A {
int _f;
@@ -42,7 +58,7 @@
''');
}
- test_unusedField_isUsed_reference_implicitThis_expressionFunctionBody() async {
+ test_isUsed_reference_implicitThis_expressionFunctionBody() async {
await assertNoErrorsInCode(r'''
class A {
int _f;
@@ -51,7 +67,7 @@
''');
}
- test_unusedField_isUsed_reference_implicitThis_subclass() async {
+ test_isUsed_reference_implicitThis_subclass() async {
await assertNoErrorsInCode(r'''
class A {
int _f;
@@ -66,7 +82,7 @@
''');
}
- test_unusedField_isUsed_reference_qualified_propagatedElement() async {
+ test_isUsed_reference_qualified_propagatedElement() async {
await assertNoErrorsInCode(r'''
class A {
int _f;
@@ -79,7 +95,7 @@
''');
}
- test_unusedField_isUsed_reference_qualified_staticElement() async {
+ test_isUsed_reference_qualified_staticElement() async {
await assertNoErrorsInCode(r'''
class A {
int _f;
@@ -92,7 +108,7 @@
''');
}
- test_unusedField_isUsed_reference_qualified_unresolved() async {
+ test_isUsed_reference_qualified_unresolved() async {
await assertNoErrorsInCode(r'''
class A {
int _f;
@@ -104,7 +120,7 @@
''');
}
- test_unusedField_notUsed_compoundAssign() async {
+ test_notUsed_compoundAssign() async {
await assertErrorsInCode(r'''
class A {
int _f;
@@ -117,7 +133,7 @@
]);
}
- test_unusedField_notUsed_constructorFieldInitializers() async {
+ test_notUsed_constructorFieldInitializers() async {
await assertErrorsInCode(r'''
class A {
int _f;
@@ -128,7 +144,7 @@
]);
}
- test_unusedField_notUsed_fieldFormalParameter() async {
+ test_notUsed_fieldFormalParameter() async {
await assertErrorsInCode(r'''
class A {
int _f;
@@ -139,7 +155,7 @@
]);
}
- test_unusedField_notUsed_noReference() async {
+ test_notUsed_noReference() async {
await assertErrorsInCode(r'''
class A {
int _f;
@@ -149,7 +165,7 @@
]);
}
- test_unusedField_notUsed_nullAssign() async {
+ test_notUsed_nullAssign() async {
await assertNoErrorsInCode(r'''
class A {
var _f;
@@ -161,7 +177,7 @@
''');
}
- test_unusedField_notUsed_postfixExpr() async {
+ test_notUsed_postfixExpr() async {
await assertErrorsInCode(r'''
class A {
int _f = 0;
@@ -174,7 +190,7 @@
]);
}
- test_unusedField_notUsed_prefixExpr() async {
+ test_notUsed_prefixExpr() async {
await assertErrorsInCode(r'''
class A {
int _f = 0;
@@ -187,7 +203,7 @@
]);
}
- test_unusedField_notUsed_simpleAssignment() async {
+ test_notUsed_simpleAssignment() async {
await assertErrorsInCode(r'''
class A {
int _f;
diff --git a/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart b/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
index 99fd027..7efa6ae 100644
--- a/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
@@ -529,7 +529,7 @@
return x;
}
''', [
- error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, 36, 1),
+ error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 36, 1),
]);
}
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
index 8e48671..754b7ad 100644
--- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -16,6 +16,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(CanBeConstConstructorTest);
defineReflectiveTests(CanBeConstTest);
+ defineReflectiveTests(EvaluateExpressionTest);
});
}
@@ -41,7 +42,7 @@
result.session.declaredVariables,
result.typeProvider,
result.typeSystem,
- InheritanceManager3(result.typeSystem),
+ InheritanceManager3(),
analysisOptions,
// todo (pq): test package or consider passing in null
workspacePackage,
@@ -243,3 +244,38 @@
assertCanBeConst("A();", true);
}
}
+
+@reflectiveTest
+class EvaluateExpressionTest extends AbstractLinterContextTest {
+ test_hasError_methodInvocation() async {
+ await resolve('''
+var x = 42.abs();
+''');
+ var result = _evaluateX();
+ expect(result.errors, isNotNull);
+ expect(result.value, isNull);
+ }
+
+ test_hasValue_binaryExpression() async {
+ await resolve('''
+var x = 1 + 2;
+''');
+ var result = _evaluateX();
+ expect(result.errors, isEmpty);
+ expect(result.value.toIntValue(), 3);
+ }
+
+ test_hasValue_intLiteral() async {
+ await resolve('''
+var x = 42;
+''');
+ var result = _evaluateX();
+ expect(result.errors, isEmpty);
+ expect(result.value.toIntValue(), 42);
+ }
+
+ LinterConstantEvaluationResult _evaluateX() {
+ var node = findNode.topVariableDeclarationByName('x').initializer;
+ return context.evaluateConstant(node);
+ }
+}
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 8ecf7ea..0555d63 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -1078,6 +1078,12 @@
void writeTypeParameterElement(TypeParameterElement e) {
writeMetadata(e, '', '\n');
+ // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
+ // variance is added to the interface.
+ if (!(e as TypeParameterElementImpl).isLegacyCovariant) {
+ buffer.write(
+ (e as TypeParameterElementImpl).variance.toKeywordString() + ' ');
+ }
writeName(e);
writeCodeRange(e);
if (e.bound != null && !e.bound.isObject) {
diff --git a/pkg/analyzer/test/src/summary/in_summary_source_test.dart b/pkg/analyzer/test/src/summary/in_summary_source_test.dart
index c6d5879..1ce0664 100644
--- a/pkg/analyzer/test/src/summary/in_summary_source_test.dart
+++ b/pkg/analyzer/test/src/summary/in_summary_source_test.dart
@@ -4,8 +4,6 @@
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/summary/format.dart';
-import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -44,19 +42,12 @@
}
class MockSummaryDataStore implements SummaryDataStore {
- final Map<String, LinkedLibrary> linkedMap;
- final Map<String, UnlinkedUnit> unlinkedMap;
final Map<String, String> uriToSummaryPath;
- MockSummaryDataStore(this.linkedMap, this.unlinkedMap, this.uriToSummaryPath);
+ MockSummaryDataStore(this.uriToSummaryPath);
factory MockSummaryDataStore.fake(Map<String, String> uriToSummary) {
- // Create fake unlinked map.
- // We don't populate the values as it is not needed for the test.
- var unlinkedMap = new Map<String, UnlinkedUnit>.fromIterable(
- uriToSummary.keys,
- value: (uri) => new UnlinkedUnitBuilder());
- return new MockSummaryDataStore(null, unlinkedMap, uriToSummary);
+ return new MockSummaryDataStore(uriToSummary);
}
noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index ed41fb1..11739dc 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -7,6 +7,7 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -1316,6 +1317,12 @@
_writeln('TypeParameter');
_withIndent(() {
var properties = _Properties();
+ // TODO (kallentu) : Clean up TypeParameterImpl casting once variance is
+ // added to the interface.
+ if ((node as TypeParameterImpl).varianceKeyword != null) {
+ properties.addToken(
+ 'variance', (node as TypeParameterImpl).varianceKeyword);
+ }
properties.addNode('bound', node.bound);
properties.addNode('name', node.name);
_addDeclaration(properties, node);
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index f9edcbf..28c0898 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -5,10 +5,9 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
+import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/idl.dart';
@@ -62,7 +61,7 @@
}
var elementFactory = LinkedElementFactory(
- RestrictedAnalysisContext(
+ AnalysisContextImpl(
SynchronousSession(
AnalysisOptionsImpl(),
declaredVariables,
@@ -92,7 +91,7 @@
var inputLibraries = <LinkInputLibrary>[];
_addNonDartLibraries(Set(), inputLibraries, source);
- var analysisContext = RestrictedAnalysisContext(
+ var analysisContext = AnalysisContextImpl(
SynchronousSession(
AnalysisOptionsImpl()..contextFeatures = featureSet,
declaredVariables,
@@ -138,11 +137,7 @@
if (analysisContext.typeProvider == null) {
var dartCore = elementFactory.libraryOfUri('dart:core');
var dartAsync = elementFactory.libraryOfUri('dart:async');
- var typeProvider = TypeProviderImpl(dartCore, dartAsync);
- analysisContext.typeProvider = typeProvider;
-
- dartCore.createLoadLibraryFunction(typeProvider);
- dartAsync.createLoadLibraryFunction(typeProvider);
+ elementFactory.createTypeProviders(dartCore, dartAsync);
}
return elementFactory.libraryOfUri('${source.uri}');
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 41ac8c8..d0f08cd 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1643,6 +1643,38 @@
''');
}
+ test_class_type_parameters_variance_covariant() async {
+ var library = await checkLibrary('class C<out T> {}');
+ checkElementText(library, r'''
+class C<out T> {
+}
+''');
+ }
+
+ test_class_type_parameters_variance_contravariant() async {
+ var library = await checkLibrary('class C<in T> {}');
+ checkElementText(library, r'''
+class C<in T> {
+}
+''');
+ }
+
+ test_class_type_parameters_variance_invariant() async {
+ var library = await checkLibrary('class C<inout T> {}');
+ checkElementText(library, r'''
+class C<inout T> {
+}
+''');
+ }
+
+ test_class_type_parameters_variance_multiple() async {
+ var library = await checkLibrary('class C<inout T, in U, out V> {}');
+ checkElementText(library, r'''
+class C<inout T, in U, out V> {
+}
+''');
+ }
+
test_classes() async {
var library = await checkLibrary('class C {} class D {}');
checkElementText(library, r'''
@@ -9137,6 +9169,38 @@
''');
}
+ test_mixin_type_parameters_variance_covariant() async {
+ var library = await checkLibrary('mixin M<out T> {}');
+ checkElementText(library, r'''
+mixin M<out T> on Object {
+}
+''');
+ }
+
+ test_mixin_type_parameters_variance_contravariant() async {
+ var library = await checkLibrary('mixin M<in T> {}');
+ checkElementText(library, r'''
+mixin M<in T> on Object {
+}
+''');
+ }
+
+ test_mixin_type_parameters_variance_invariant() async {
+ var library = await checkLibrary('mixin M<inout T> {}');
+ checkElementText(library, r'''
+mixin M<inout T> on Object {
+}
+''');
+ }
+
+ test_mixin_type_parameters_variance_multiple() async {
+ var library = await checkLibrary('mixin M<inout T, in U, out V> {}');
+ checkElementText(library, r'''
+mixin M<inout T, in U, out V> on Object {
+}
+''');
+ }
+
test_nameConflict_exportedAndLocal() async {
addLibrarySource('/a.dart', 'class C {}');
addLibrarySource('/c.dart', '''
diff --git a/pkg/analyzer/test/src/summary/test_strategies.dart b/pkg/analyzer/test/src/summary/test_strategies.dart
index 5f16bb4..0d3d18e 100644
--- a/pkg/analyzer/test/src/summary/test_strategies.dart
+++ b/pkg/analyzer/test/src/summary/test_strategies.dart
@@ -12,7 +12,6 @@
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'resynthesize_common.dart';
@@ -76,8 +75,5 @@
final Set<Source> serializedSources = new Set<Source>();
- final Map<String, UnlinkedUnitBuilder> uriToUnit =
- <String, UnlinkedUnitBuilder>{};
-
PackageBundleAssembler bundleAssembler = new PackageBundleAssembler();
}
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 50455ea..d080c3b 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -184,7 +184,7 @@
m(A a);
}
-class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/Base
+class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER*/Base
implements I1 {}
class T1 extends Base {
@@ -752,7 +752,7 @@
dynamic get /*error:INVALID_OVERRIDE*/f4 => null;
}
-class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR*/Child2 implements Base {
+class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER*/Child2 implements Base {
A get /*error:INVALID_OVERRIDE*/f1 => null;
C get f2 => null;
get f3 => null;
@@ -2605,15 +2605,15 @@
B /*error:INVALID_OVERRIDE, error:INVALID_OVERRIDE*/f;
}
-class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T5 implements Base {
+class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER*/T5 implements Base {
/**/B get /*error:INVALID_OVERRIDE, error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f => null;
}
-class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T6 implements Base {
+class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER*/T6 implements Base {
set /*error:INVALID_OVERRIDE, error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f(B b) => null;
}
-class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/T7 implements Base {
+class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER*/T7 implements Base {
final B /*error:INVALID_OVERRIDE, error:MISMATCHED_GETTER_AND_SETTER_TYPES*/f = null;
}
class T8 implements Base {
@@ -3433,7 +3433,7 @@
m(A a);
}
-class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE*/Base
+class /*error:NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER*/Base
implements I1 {}
class M {
diff --git a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
index fc52165..5068c51 100644
--- a/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
+++ b/pkg/analyzer/test/src/task/strong/strong_test_helper.dart
@@ -279,8 +279,10 @@
analysisOptions.strictRawTypes = strictRawTypes;
analysisOptions.enabledExperiments = enabledExperiments;
- var mockSdk = new MockSdk(resourceProvider: resourceProvider);
- mockSdk.context.analysisOptions = analysisOptions;
+ var mockSdk = new MockSdk(
+ resourceProvider: resourceProvider,
+ analysisOptions: analysisOptions,
+ );
SourceFactory sourceFactory = new SourceFactory([
new DartUriResolver(mockSdk),
diff --git a/pkg/analyzer/test/src/workspace/basic_test.dart b/pkg/analyzer/test/src/workspace/basic_test.dart
index a4d4752..8fb66aa 100644
--- a/pkg/analyzer/test/src/workspace/basic_test.dart
+++ b/pkg/analyzer/test/src/workspace/basic_test.dart
@@ -33,6 +33,7 @@
newFolder('/workspace');
workspace = BasicWorkspace.find(
resourceProvider, convertPath('/workspace'), contextBuilder);
+ expect(workspace.isBazel, isFalse);
}
void test_contains_differentWorkspace() {
@@ -94,6 +95,7 @@
BasicWorkspace workspace = BasicWorkspace.find(
resourceProvider, convertPath('/workspace'), new MockContextBuilder());
expect(workspace.root, convertPath('/workspace'));
+ expect(workspace.isBazel, isFalse);
}
void test_find_fail_notAbsolute() {
@@ -109,6 +111,7 @@
convertPath('/workspace/project/lib/lib1.dart'),
new MockContextBuilder());
expect(workspace.root, convertPath('/workspace/project/lib'));
+ expect(workspace.isBazel, isFalse);
}
}
diff --git a/pkg/analyzer/test/src/workspace/bazel_test.dart b/pkg/analyzer/test/src/workspace/bazel_test.dart
index f2080c5..5a9a643 100644
--- a/pkg/analyzer/test/src/workspace/bazel_test.dart
+++ b/pkg/analyzer/test/src/workspace/bazel_test.dart
@@ -35,6 +35,7 @@
newFile('/workspace/test.dart');
newFile('/workspace/bazel-bin/gen1.dart');
newFile('/workspace/bazel-genfiles/gen2.dart');
+ expect(workspace.isBazel, isTrue);
}
void test_resolveAbsolute_doesNotExist() {
@@ -573,7 +574,22 @@
expect(package, isNull);
}
- void test_findPackageFor_packagesFileInBinExists() {
+ void test_findPackageFor_packagesFileExistsInOneOfSeveralBinPaths() {
+ _addResources([
+ '/ws/blaze-out/host/bin/some/code/code.packages',
+ '/ws/blaze-out/k8-opt/bin/some/code/',
+ '/ws/some/code/lib/code.dart',
+ ]);
+ workspace =
+ BazelWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
+
+ package = workspace.findPackageFor('/ws/some/code/lib/code.dart');
+ expect(package, isNotNull);
+ expect(package.root, convertPath('/ws/some/code'));
+ expect(package.workspace, equals(workspace));
+ }
+
+ void test_findPackageFor_packagesFileExistsInOnlyBinPath() {
_addResources([
'/ws/blaze-out/host/bin/some/code/code.packages',
'/ws/some/code/lib/code.dart',
@@ -650,7 +666,8 @@
resourceProvider, convertPath('/workspace/my/module'));
expect(workspace.root, convertPath('/workspace'));
expect(workspace.readonly, isNull);
- expect(workspace.bin, convertPath('/workspace/blaze-out/host/bin'));
+ expect(workspace.binPaths.single,
+ convertPath('/workspace/blaze-out/host/bin'));
expect(workspace.genfiles, convertPath('/workspace/blaze-genfiles'));
}
@@ -664,7 +681,25 @@
resourceProvider, convertPath('/workspace/my/module'));
expect(workspace.root, convertPath('/workspace'));
expect(workspace.readonly, isNull);
- expect(workspace.bin, convertPath('/workspace/blaze-bin'));
+ expect(workspace.binPaths.single, convertPath('/workspace/blaze-bin'));
+ expect(workspace.genfiles, convertPath('/workspace/blaze-genfiles'));
+ }
+
+ void test_find_hasMultipleBlazeBinFolderInOutFolder() {
+ _addResources([
+ '/workspace/blaze-out/host/bin/',
+ '/workspace/blaze-out/k8-fastbuild/bin/',
+ '/workspace/my/module/',
+ ]);
+ BazelWorkspace workspace = BazelWorkspace.find(
+ resourceProvider, convertPath('/workspace/my/module'));
+ expect(workspace.root, convertPath('/workspace'));
+ expect(workspace.readonly, isNull);
+ expect(workspace.binPaths, hasLength(2));
+ expect(workspace.binPaths,
+ contains(convertPath('/workspace/blaze-out/host/bin')));
+ expect(workspace.binPaths,
+ contains(convertPath('/workspace/blaze-out/k8-fastbuild/bin')));
expect(workspace.genfiles, convertPath('/workspace/blaze-genfiles'));
}
@@ -678,7 +713,8 @@
resourceProvider, convertPath('/Users/user/test/prime/my/module'));
expect(workspace.root, convertPath('/Users/user/test/prime'));
expect(workspace.readonly, convertPath('/Users/user/test/READONLY/prime'));
- expect(workspace.bin, convertPath('/Users/user/test/prime/bazel-bin'));
+ expect(workspace.binPaths.single,
+ convertPath('/Users/user/test/prime/bazel-bin'));
expect(workspace.genfiles,
convertPath('/Users/user/test/prime/bazel-genfiles'));
}
@@ -693,7 +729,8 @@
resourceProvider, convertPath('/Users/user/test/prime/my/module'));
expect(workspace.root, convertPath('/Users/user/test/prime'));
expect(workspace.readonly, isNull);
- expect(workspace.bin, convertPath('/Users/user/test/prime/bazel-bin'));
+ expect(workspace.binPaths.single,
+ convertPath('/Users/user/test/prime/bazel-bin'));
expect(workspace.genfiles,
convertPath('/Users/user/test/prime/bazel-genfiles'));
}
@@ -708,7 +745,8 @@
resourceProvider, convertPath('/Users/user/test/prime/my/module'));
expect(workspace.root, convertPath('/Users/user/test/prime'));
expect(workspace.readonly, convertPath('/Users/user/test/READONLY/prime'));
- expect(workspace.bin, convertPath('/Users/user/test/prime/blaze-bin'));
+ expect(workspace.binPaths.single,
+ convertPath('/Users/user/test/prime/blaze-bin'));
expect(workspace.genfiles,
convertPath('/Users/user/test/prime/blaze-genfiles'));
}
@@ -722,7 +760,7 @@
resourceProvider, convertPath('/workspace/my/module'));
expect(workspace.root, convertPath('/workspace'));
expect(workspace.readonly, isNull);
- expect(workspace.bin, convertPath('/workspace/bazel-bin'));
+ expect(workspace.binPaths.single, convertPath('/workspace/bazel-bin'));
expect(workspace.genfiles, convertPath('/workspace/bazel-genfiles'));
}
@@ -735,7 +773,7 @@
resourceProvider, convertPath('/workspace/my/module'));
expect(workspace.root, convertPath('/workspace'));
expect(workspace.readonly, isNull);
- expect(workspace.bin, convertPath('/workspace/bazel-bin'));
+ expect(workspace.binPaths.single, convertPath('/workspace/bazel-bin'));
expect(workspace.genfiles, convertPath('/workspace/bazel-genfiles'));
}
@@ -748,7 +786,7 @@
BazelWorkspace.find(resourceProvider, convertPath('/workspace'));
expect(workspace.root, convertPath('/workspace'));
expect(workspace.readonly, isNull);
- expect(workspace.bin, convertPath('/workspace/bazel-bin'));
+ expect(workspace.binPaths.single, convertPath('/workspace/bazel-bin'));
expect(workspace.genfiles, convertPath('/workspace/bazel-genfiles'));
}
@@ -761,7 +799,7 @@
BazelWorkspace.find(resourceProvider, convertPath('/workspace'));
expect(workspace.root, convertPath('/workspace'));
expect(workspace.readonly, isNull);
- expect(workspace.bin, convertPath('/workspace/blaze-bin'));
+ expect(workspace.binPaths.single, convertPath('/workspace/blaze-bin'));
expect(workspace.genfiles, convertPath('/workspace/blaze-genfiles'));
}
@@ -784,7 +822,7 @@
resourceProvider, convertPath('/workspace/my/module'));
expect(workspace.root, convertPath('/workspace'));
expect(workspace.readonly, isNull);
- expect(workspace.bin, convertPath('/workspace/$prefix-bin'));
+ expect(workspace.binPaths.single, convertPath('/workspace/$prefix-bin'));
expect(workspace.genfiles, convertPath('/workspace/$prefix-genfiles'));
}
diff --git a/pkg/analyzer/test/src/workspace/gn_test.dart b/pkg/analyzer/test/src/workspace/gn_test.dart
index b3348de..0ed21d5 100644
--- a/pkg/analyzer/test/src/workspace/gn_test.dart
+++ b/pkg/analyzer/test/src/workspace/gn_test.dart
@@ -99,7 +99,10 @@
newFile('/ws/.fx-build-dir', content: '$buildDir\n');
newFile('/ws/out/debug-x87_128/dartlang/gen/some/code/foo.packages');
newFolder('/ws/some/code');
- return GnWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
+ var gnWorkspace =
+ GnWorkspace.find(resourceProvider, convertPath('/ws/some/code'));
+ expect(gnWorkspace.isBazel, isFalse);
+ return gnWorkspace;
}
}
diff --git a/pkg/analyzer/test/src/workspace/package_build_test.dart b/pkg/analyzer/test/src/workspace/package_build_test.dart
index 6045fb1..0a25d2c 100644
--- a/pkg/analyzer/test/src/workspace/package_build_test.dart
+++ b/pkg/analyzer/test/src/workspace/package_build_test.dart
@@ -66,6 +66,7 @@
resolver = new PackageBuildFileUriResolver(workspace);
newFile('/workspace/test.dart');
newFile('/workspace/.dart_tool/build/generated/project/gen.dart');
+ expect(workspace.isBazel, isFalse);
}
void test_resolveAbsolute_doesNotExist() {
diff --git a/pkg/analyzer/test/src/workspace/pub_test.dart b/pkg/analyzer/test/src/workspace/pub_test.dart
index 7d7e987..5257ee9 100644
--- a/pkg/analyzer/test/src/workspace/pub_test.dart
+++ b/pkg/analyzer/test/src/workspace/pub_test.dart
@@ -51,6 +51,7 @@
newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
workspace = PubWorkspace.find(
resourceProvider, convertPath('/workspace'), contextBuilder);
+ expect(workspace.isBazel, isFalse);
}
void test_contains_differentWorkspace() {
@@ -108,6 +109,7 @@
newFileWithBytes('/workspace/pubspec.yaml', 'name: project'.codeUnits);
PubWorkspace workspace = PubWorkspace.find(
resourceProvider, convertPath('/workspace'), new MockContextBuilder());
+ expect(workspace.isBazel, isFalse);
expect(workspace.root, convertPath('/workspace'));
}
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index e829ba7..280363c 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -36,7 +36,12 @@
/// A list of the diagnostic codes that are not being verified. These should
/// ony include docs that cannot be verified because of missing support in the
/// verifier.
- static const List<String> unverifiedDocs = ['HintCode.DEPRECATED_MEMBER_USE'];
+ static const List<String> unverifiedDocs = [
+ // The code has been replaced but is not yet removed.
+ 'HintCode.DEPRECATED_MEMBER_USE',
+ // Needs two expected errors.
+ 'StaticWarningCode.AMBIGUOUS_IMPORT',
+ ];
/// The prefix used on directive lines to indicate the uri of an auxiliary
/// file that is needed for testing purposes.
@@ -231,14 +236,24 @@
List<_SnippetData> exampleSnippets =
_extractSnippets(docs, exampleStart + 1, fixesStart, true);
- for (_SnippetData snippet in exampleSnippets) {
- await _validateSnippet(snippet);
+ _SnippetData firstExample;
+ if (exampleSnippets.isEmpty) {
+ _reportProblem('No example.');
+ } else {
+ firstExample = exampleSnippets[0];
+ }
+ for (int i = 0; i < exampleSnippets.length; i++) {
+ await _validateSnippet('example', i, exampleSnippets[i]);
}
List<_SnippetData> fixesSnippets =
_extractSnippets(docs, fixesStart + 1, docs.length, false);
- for (_SnippetData snippet in fixesSnippets) {
- await _validateSnippet(snippet);
+ for (int i = 0; i < fixesSnippets.length; i++) {
+ _SnippetData snippet = fixesSnippets[i];
+ if (firstExample != null) {
+ snippet.auxiliaryFiles.addAll(firstExample.auxiliaryFiles);
+ }
+ await _validateSnippet('fixes', i, snippet);
}
}
}
@@ -251,7 +266,8 @@
/// verify that no diagnostics are reported. If the offset is greater than or
/// equal to zero, verify that one error whose name matches the current code
/// is reported at that offset with the expected length.
- Future<void> _validateSnippet(_SnippetData snippet) async {
+ Future<void> _validateSnippet(
+ String section, int index, _SnippetData snippet) async {
_SnippetTest test = _SnippetTest(snippet);
test.setUp();
await test.resolveTestFile();
@@ -259,28 +275,30 @@
int errorCount = errors.length;
if (snippet.offset < 0) {
if (errorCount > 0) {
- _reportProblem('Expected no errors but found $errorCount:',
+ _reportProblem(
+ 'Expected no errors but found $errorCount ($section $index):',
errors: errors);
}
} else {
if (errorCount == 0) {
- _reportProblem('Expected one error but found none.');
+ _reportProblem('Expected one error but found none ($section $index).');
} else if (errorCount == 1) {
AnalysisError error = errors[0];
if (error.errorCode.uniqueName != codeName) {
- _reportProblem(
- 'Expected an error with code $codeName, found ${error.errorCode}.');
+ _reportProblem('Expected an error with code $codeName, '
+ 'found ${error.errorCode} ($section $index).');
}
if (error.offset != snippet.offset) {
- _reportProblem(
- 'Expected an error at ${snippet.offset}, found ${error.offset}.');
+ _reportProblem('Expected an error at ${snippet.offset}, '
+ 'found ${error.offset} ($section $index).');
}
if (error.length != snippet.length) {
- _reportProblem(
- 'Expected an error of length ${snippet.length}, found ${error.length}.');
+ _reportProblem('Expected an error of length ${snippet.length}, '
+ 'found ${error.length} ($section $index).');
}
} else {
- _reportProblem('Expected one error but found $errorCount:',
+ _reportProblem(
+ 'Expected one error but found $errorCount ($section $index):',
errors: errors);
}
}
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 3df5e19..107a489 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -74,7 +74,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `B` doesn't inherit a
+concrete implementation of `a`:
{% prettify dart %}
abstract class A {
@@ -150,6 +151,72 @@
}
{% endprettify %}
+### ambiguous_import
+
+_The name '{0}' is defined in the libraries {1}._
+
+#### Description
+
+The analyzer produces this diagnostic when a name is referenced that is
+declared in two or more imported libraries.
+
+#### Example
+
+Given a library (`a.dart`) that defines a class (`C` in this example):
+
+{% prettify dart %}
+class A {}
+class C {}
+{% endprettify %}
+
+And a library (`b.dart`) that defines a different class with the same name:
+
+{% prettify dart %}
+class B {}
+class C {}
+{% endprettify %}
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+import 'a.dart';
+import 'b.dart';
+
+void f([!C!] c1, [!C!] c2) {}
+{% endprettify %}
+
+#### Common fixes
+
+If any of the libraries aren't needed, then remove the import directives
+for them:
+
+{% prettify dart %}
+import 'a.dart';
+
+void f(C c1, C c2) {}
+{% endprettify %}
+
+If the name is still defined by more than one library, then add a `hide`
+clause to the import directives for all except one library:
+
+{% prettify dart %}
+import 'a.dart' hide C;
+import 'b.dart';
+
+void f(C c1, C c2) {}
+{% endprettify %}
+
+If you must be able to reference more than one of these types, then add a
+prefix to each of the import directives, and qualify the references with
+the appropriate prefix:
+
+{% prettify dart %}
+import 'a.dart' as a;
+import 'b.dart' as b;
+
+void f(a.C c1, b.C c2) {}
+{% endprettify %}
+
### ambiguous_set_or_map_literal_both
_This literal contains both 'Map' and 'Iterable' spreads, which makes it
@@ -288,7 +355,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because a `num` can't be
+assigned to a `String`:
{% prettify dart %}
String f(String x) => x;
@@ -330,6 +398,62 @@
String g(num y) => f(y as String);
{% endprettify %}
+### assignment_to_final_no_setter
+
+_There isn’t a setter named '{0}' in class '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when a reference to a setter is
+found; there is no setter defined for the type; but there is a getter
+defined with the same name.
+
+#### Example
+
+The following code produces this diagnostic because there is no setter
+named `x` in `C`, but there is a getter named `x`:
+
+{% prettify dart %}
+class C {
+ int get x => 0;
+ set y(int p) {}
+}
+
+void f(C c) {
+ c.[!x!] = 1;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you want to invoke an existing setter, then correct the name:
+
+{% prettify dart %}
+class C {
+ int get x => 0;
+ set y(int p) {}
+}
+
+void f(C c) {
+ c.y = 1;
+}
+{% endprettify %}
+
+If you want to invoke the setter but it just doesn't exist yet, then
+declare it:
+
+{% prettify dart %}
+class C {
+ int get x => 0;
+ set x(int p) {}
+ set y(int p) {}
+}
+
+void f(C c) {
+ c.x = 1;
+}
+{% endprettify %}
+
### built_in_identifier_as_extension_name
_The built-in identifier '{0}' can't be used as an extension name._
@@ -341,7 +465,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `mixin` is a built-in
+identifier:
{% prettify dart %}
extension [!mixin!] on int {}
@@ -362,7 +487,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `x` is a variable, not
+a type:
{% prettify dart %}
num x = 0;
@@ -378,6 +504,47 @@
int y = x as int;
{% endprettify %}
+### concrete_class_with_abstract_member
+
+_'{0}' must have a method body because '{1}' isn't abstract._
+
+#### Description
+
+The analyzer produces this diagnostic when a member of a concrete class is
+found that doesn't have a concrete implementation. Concrete classes aren't
+allowed to contain abstract members.
+
+#### Example
+
+The following code produces this diagnostic because `m` is an abstract
+method but `C` isn't an abstract class:
+
+{% prettify dart %}
+class C {
+ [!void m();!]
+}
+{% endprettify %}
+
+#### Common fixes
+
+If it's valid to create instances of the class, provide an implementation
+for the member:
+
+{% prettify dart %}
+class C {
+ void m() {}
+}
+{% endprettify %}
+
+If it isn't valid to create instances of the class, mark the class as being
+abstract:
+
+{% prettify dart %}
+abstract class C {
+ void m();
+}
+{% endprettify %}
+
### const_initialized_with_non_constant_value
_Const variables must be initialized with a constant value._
@@ -416,6 +583,31 @@
final y = x;
{% endprettify %}
+### const_not_initialized
+
+_The constant '{0}' must be initialized._
+
+#### Description
+
+The analyzer produces this diagnostic when a variable that is declared to
+be a constant doesn't have an initializer.
+
+#### Example
+
+The following code produces this diagnostic because `c` isn't initialized:
+
+{% prettify dart %}
+const [!c!];
+{% endprettify %}
+
+#### Common fixes
+
+Add an initializer:
+
+{% prettify dart %}
+const c = 'c';
+{% endprettify %}
+
### const_spread_expected_list_or_set
_A list or a set is expected in this spread._
@@ -428,7 +620,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the value of `list1` is
+`null`, which is neither a list nor a set:
{% prettify dart %}
const List<int> list1 = null;
@@ -456,7 +649,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the value of `map1` is
+`null`, which isn't a map:
{% prettify dart %}
const Map<String, int> map1 = null;
@@ -483,7 +677,7 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `i` isn't a constant:
{% prettify dart %}
class C {
@@ -506,6 +700,159 @@
C f(int i) => C(i);
{% endprettify %}
+### dead_code
+
+_Dead code._
+
+#### Description
+
+The analyzer produces this diagnostic when code is found that won't be
+executed because execution will never reach the code.
+
+#### Example
+
+The following code produces this diagnostic because the invocation of
+`print` occurs after the function has returned:
+
+{% prettify dart %}
+void f() {
+ return;
+ [!print('here');!]
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the code isn't needed, then remove it:
+
+{% prettify dart %}
+void f() {
+ return;
+}
+{% endprettify %}
+
+If the code needs to be executed, then either move the code to a place
+where it will be executed:
+
+{% prettify dart %}
+void f() {
+ print('here');
+ return;
+}
+{% endprettify %}
+
+Or, rewrite the code before it, so that it can be reached:
+
+{% prettify dart %}
+void f({bool skipPrinting = true}) {
+ if (skipPrinting) {
+ return;
+ }
+ print('here');
+}
+{% endprettify %}
+
+### dead_code_catch_following_catch
+
+_Dead code: Catch clauses after a 'catch (e)' or an 'on Object catch (e)' are
+never reached._
+
+#### Description
+
+The analyzer produces this diagnostic when a catch clause is found that
+can't be executed because it’s after a catch clause of the form `catch (e)`
+or `on Object catch (e)`. The first catch clause that matches the thrown
+object is selected, and both of those forms will match any object, so no
+catch clauses that follow them will be selected.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+void f() {
+ try {
+ } catch (e) {
+ } [!on String {
+ }!]
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the clause should be selectable, then move the clause before the general
+clause:
+
+{% prettify dart %}
+void f() {
+ try {
+ } on String {
+ } catch (e) {
+ }
+}
+{% endprettify %}
+
+If the clause doesn't need to be selectable, then remove it:
+
+{% prettify dart %}
+void f() {
+ try {
+ } catch (e) {
+ }
+}
+{% endprettify %}
+
+### dead_code_on_catch_subtype
+
+_Dead code: This on-catch block won’t be executed because '{0}' is a subtype of
+'{1}' and hence will have been caught already._
+
+#### Description
+
+The analyzer produces this diagnostic when a catch clause is found that
+can't be executed because it is after a catch clause that catches either
+the same type or a supertype of the clause's type. The first catch clause
+that matches the thrown object is selected, and the earlier clause l always
+matches anything matchable by the highlighted clause, so the highlighted
+clause will never be selected.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+void f() {
+ try {
+ } on num {
+ } [!on int {
+ }!]
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the clause should be selectable, then move the clause before the general
+clause:
+
+{% prettify dart %}
+void f() {
+ try {
+ } on int {
+ } on num {
+ }
+}
+{% endprettify %}
+
+If the clause doesn't need to be selectable, then remove it:
+
+{% prettify dart %}
+void f() {
+ try {
+ } on num {
+ }
+}
+{% endprettify %}
+
### deprecated_member_use
_'{0}' is deprecated and shouldn't be used._
@@ -546,7 +893,7 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `x` is deprecated:
{% prettify dart %}
@deprecated
@@ -571,7 +918,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the name `x` is
+declared twice:
{% prettify dart %}
int x = 0;
@@ -587,6 +935,37 @@
int y = 1;
{% endprettify %}
+### duplicate_import
+
+_Duplicate import._
+
+#### Description
+
+The analyzer produces this diagnostic when an import directive is found
+that is the same as an import before it in the file. The second import
+doesn’t add value and should be removed.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+import [!'package:meta/meta.dart'!];
+
+@sealed class C {}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the unnecessary import:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+
+@sealed class C {}
+{% endprettify %}
+
### equal_elements_in_const_set
_Two values in a constant set can't be equal._
@@ -599,7 +978,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the string `'a'` is
+specified twice:
{% prettify dart %}
const Set<String> set = {'a', [!'a'!]};
@@ -630,7 +1010,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the key `1` is used
+twice:
{% prettify dart %}
const map = <int, String>{1: 'a', 2: 'b', [!1!]: 'c', 4: 'd'};
@@ -683,6 +1064,47 @@
var map = <String, int>{'a': 0, 'b': 1, 'c': 2};
{% endprettify %}
+### extends_non_class
+
+_Classes can only extend other classes._
+
+#### Description
+
+The analyzer produces this diagnostic when an extends clause contains a
+name that is declared to be something other than a class.
+
+#### Example
+
+The following code produces this diagnostic because `f` is declared to be a
+function:
+
+{% prettify dart %}
+void f() {}
+
+class C extends [!f!] {}
+{% endprettify %}
+
+#### Common fixes
+
+If you want the class to extend a class other than `Object`, then replace
+the name in the extends clause with the name of that class:
+
+{% prettify dart %}
+void f() {}
+
+class C extends B {}
+
+class B {}
+{% endprettify %}
+
+If you want the class to extend `Object`, then remove the extends clause:
+
+{% prettify dart %}
+void f() {}
+
+class C {}
+{% endprettify %}
+
### extension_as_expression
_Extension '{0}' can't be used as an expression._
@@ -691,11 +1113,14 @@
The analyzer produces this diagnostic when the name of an extension is used
in an expression other than in an extension override or to qualify an
-access to a static member of the extension.
+access to a static member of the extension. Because classes define a type,
+the name of a class can be used to refer to the instance of `Type`
+representing the type of the class. Extensions, on the other hand, don't
+define a type and can't be used as a type literal.
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `E` is an extension:
{% prettify dart %}
extension E on int {
@@ -733,7 +1158,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the name `a` is being
+used for two different members:
{% prettify dart %}
extension E on Object {
@@ -764,7 +1190,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the method `a` doesn't
+have a body:
{% prettify dart %}
extension E on String {
@@ -789,7 +1216,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because there is a constructor
+declaration in `E`:
{% prettify dart %}
extension E on String {
@@ -813,7 +1241,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `s` is an instance
+field:
{% prettify dart %}
extension E on String {
@@ -840,7 +1269,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `toString` is defined
+by `Object`:
{% prettify dart %}
extension E on String {
@@ -873,15 +1303,15 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `m` is static:
{% prettify dart %}
extension E on String {
- static void staticMethod() {}
+ static void m() {}
}
void f() {
- E('').[!staticMethod!]();
+ E('').[!m!]();
}
{% endprettify %}
@@ -891,11 +1321,11 @@
{% prettify dart %}
extension E on String {
- static void staticMethod() {}
+ static void m() {}
}
void f() {
- E.staticMethod();
+ E.m();
}
{% endprettify %}
@@ -911,7 +1341,7 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `3` isn't a `String`:
{% prettify dart %}
extension E on String {
@@ -955,7 +1385,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `E(i)` isn't an
+expression:
{% prettify dart %}
extension E on int {
@@ -1002,11 +1433,14 @@
#### Description
The analyzer produces this diagnostic when an extension override is used as
-the target of a cascade expression.
+the target of a cascade expression. The value of a cascade expression
+`e..m` is the value of the target `e`, but extension overrides are not
+expressions and don't have a value.
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `E(3)` isn't an
+expression:
{% prettify dart %}
extension E on int {
@@ -1044,7 +1478,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `f` defines 2
+parameters but is invoked with 3 arguments:
{% prettify dart %}
void f(int a, int b) {}
@@ -1076,7 +1511,9 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `f` defines 2
+positional parameters but has a named parameter that could be used for the
+third argument:
{% prettify dart %}
void f(int a, int b, {int c}) {}
@@ -1118,7 +1555,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `x` doesn't have an
+initializer:
{% prettify dart %}
final [!x!];
@@ -1153,6 +1591,97 @@
}
{% endprettify %}
+### final_not_initialized_constructor
+
+_All final variables must be initialized, but '{0}' and '{1}' are not._
+
+_All final variables must be initialized, but '{0}' is not._
+
+_All final variables must be initialized, but '{0}', '{1}', and {2} others are
+not._
+
+#### Description
+
+The analyzer produces this diagnostic when a class defines one or more
+final instance fields without initializers and has at least one constructor
+that doesn't initialize those fields. All final instance fields must be
+initialized when the instance is created, either by the field's initializer
+or by the constructor.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+class C {
+ final String value;
+
+ [!C!]();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the value should be passed in to the constructor directly, then use a
+field formal parameter to initialize the field `value`:
+
+{% prettify dart %}
+class C {
+ final String value;
+
+ C(this.value);
+}
+{% endprettify %}
+
+If the value should be computed indirectly from a value provided by the
+caller, then add a parameter and include an initializer:
+
+{% prettify dart %}
+class C {
+ final String value;
+
+ C(Object o) : value = o.toString();
+}
+{% endprettify %}
+
+If the value of the field doesn't depend on values that can be passed to
+the constructor, then add an initializer for the field as part of the field
+declaration:
+
+{% prettify dart %}
+class C {
+ final String value = '';
+
+ C();
+}
+{% endprettify %}
+
+If the value of the field doesn't depend on values that can be passed to
+the constructor but different constructors need to initialize it to
+different values, then add an initializer for the field in the initializer
+list:
+
+{% prettify dart %}
+class C {
+ final String value;
+
+ C() : value = '';
+
+ C.named() : value = 'c';
+}
+{% endprettify %}
+
+However, if the value is the same for all instances, then consider using a
+static field instead of an instance field:
+
+{% prettify dart %}
+class C {
+ static const String value = '';
+
+ C();
+}
+{% endprettify %}
+
### implements_non_class
_Classes and mixins can only implement other classes and mixins._
@@ -1165,7 +1694,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `x` is a variable
+rather than a class or mixin:
{% prettify dart %}
var x;
@@ -1186,6 +1716,126 @@
of an existing class or mixin, or remove the name from the implements
clause.
+### implicit_this_reference_in_initializer
+
+_Only static members can be accessed in initializers._
+
+#### Description
+
+The analyzer produces this diagnostic when it finds a reference to an
+instance member in a constructor's initializer list.
+
+#### Example
+
+The following code produces this diagnostic because `defaultX` is an
+instance member:
+
+{% prettify dart %}
+class C {
+ int x;
+
+ C() : x = [!defaultX!];
+
+ int get defaultX => 0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the member can be made static, then do so:
+
+{% prettify dart %}
+class C {
+ int x;
+
+ C() : x = defaultX;
+
+ static int get defaultX => 0;
+}
+{% endprettify %}
+
+If not, then replace the reference in the initializer with a different
+expression that doesn't use an instance member:
+
+{% prettify dart %}
+class C {
+ int x;
+
+ C() : x = 0;
+
+ int get defaultX => 0;
+}
+{% endprettify %}
+
+### initializing_formal_for_non_existent_field
+
+_'{0}' isn't a field in the enclosing class._
+
+#### Description
+
+The analyzer produces this diagnostic when a field formal parameter is
+found in a constructor in a class that doesn't declare the field being
+initialized.
+
+#### Example
+
+The following code produces this diagnostic because the field `x` isn't
+defined:
+
+{% prettify dart %}
+class C {
+ int y;
+
+ C([!this.x!]);
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the field name was wrong, then change it to the name of an existing
+field:
+
+{% prettify dart %}
+class C {
+ int y;
+
+ C(this.y);
+}
+{% endprettify %}
+
+If the field name is correct but hasn't yet been defined, then declare the
+field:
+
+{% prettify dart %}
+class C {
+ int x;
+ int y;
+
+ C(this.x);
+}
+{% endprettify %}
+
+If the parameter is needed but shouldn't initialize a field, then convert
+it to a normal parameter and use it:
+
+{% prettify dart %}
+class C {
+ int y;
+
+ C(int x) : y = x * 2;
+}
+{% endprettify %}
+
+If the parameter isn't needed, then remove it:
+
+{% prettify dart %}
+class C {
+ int y;
+
+ C();
+}
+{% endprettify %}
+
### invalid_assignment
_A value of type '{0}' can't be assigned to a variable of type '{1}'._
@@ -1287,12 +1937,25 @@
#### Description
-The meaning of the `@literal` annotation is only defined when it's applied
-to a const constructor.
+The analyzer produces this diagnostic when the `@literal` annotation is
+applied to anything other than a const constructor.
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the constructor is not
+a `const` constructor:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+
+class C {
+ [!@literal!]
+ C();
+}
+{% endprettify %}
+
+The following code produces this diagnostic because `x` isn't a
+constructor:
{% prettify dart %}
import 'package:meta/meta.dart';
@@ -1303,12 +1966,89 @@
#### Common fixes
-Remove the annotation:
+If the annotation is on a constructor and the constructor should always be
+invoked with `const`, when possible, then mark the constructor with the
+`const` keyword:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+
+class C {
+ @literal
+ const C();
+}
+{% endprettify %}
+
+If the constructor can't be marked as `const`, then remove the annotation.
+
+If the annotation is on anything other than a constructor, then remove the
+annotation:
{% prettify dart %}
var x;
{% endprettify %}
+### invalid_override
+
+_'{1}.{0}' ('{2}') isn't a valid override of '{3}.{0}' ('{4}')._
+
+#### Description
+
+The analyzer produces this diagnostic when a member of a class is found
+that overrides a member from a supertype and the override isn't valid. An
+override is valid if all of these are true:
+* It allows all of the arguments allowed by the overridden member.
+* It doesn't require any arguments that aren't required by the overridden
+ member.
+* The type of every parameter of the overridden member is assignable to the
+ corresponding parameter of the override.
+* The return type of the override is assignable to the return type of the
+ overridden member.
+
+#### Example
+
+The following code produces this diagnostic because the type of the
+parameter `s` (`String`) isn't assignable to the type of the parameter `i`
+(`int`):
+
+{% prettify dart %}
+class A {
+ void m(int i) {}
+}
+
+class B extends A {
+ void [!m!](String s) {}
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the invalid method is intended to override the method from the
+superclass, then change it to conform:
+
+{% prettify dart %}
+class A {
+ void m(int i) {}
+}
+
+class B extends A {
+ void m(int i) {}
+}
+{% endprettify %}
+
+If it isn't intended to override the method from the superclass, then
+rename it:
+
+{% prettify dart %}
+class A {
+ void m(int i) {}
+}
+
+class B extends A {
+ void m2(String s) {}
+}
+{% endprettify %}
+
### invalid_use_of_covariant_in_extension
_Can't have modifier '#lexeme' in an extension._
@@ -1322,7 +2062,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `i` is marked as being
+covariant:
{% prettify dart %}
extension E on String {
@@ -1340,6 +2081,94 @@
}
{% endprettify %}
+### invalid_visibility_annotation
+
+_The member '{0}' is annotated with '{1}', but this annotation is only
+meaningful on declarations of public members._
+
+#### Description
+
+The analyzer produces this diagnostic when either the `@visibleForTemplate`
+or `@visibleForTesting` annotation is applied to a non-public declaration.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+
+[!@visibleForTesting!]
+void _someFunction() {}
+
+void f() => _someFunction();
+{% endprettify %}
+
+#### Common fixes
+
+If the declaration doesn't need to be used by test code, then remove the
+annotation:
+
+{% prettify dart %}
+void _someFunction() {}
+
+void f() => _someFunction();
+{% endprettify %}
+
+If it does, then make it public:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+
+@visibleForTesting
+void someFunction() {}
+
+void f() => someFunction();
+{% endprettify %}
+
+### invocation_of_extension_without_call
+
+_The extension '{0}' doesn't define a 'call' method so the override can't be
+used in an invocation._
+
+#### Description
+
+The analyzer produces this diagnostic when an extension override is used to
+invoke a function but the extension doesn't declare a `call` method.
+
+#### Example
+
+The following code produces this diagnostic because the extension `E`
+doesn't define a `call` method:
+
+{% prettify dart %}
+extension E on String {}
+
+void f() {
+ [!E('')!]();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the extension is intended to define a `call` method, then declare it:
+
+{% prettify dart %}
+extension E on String {
+ int call() => 0;
+}
+
+void f() {
+ E('')();
+}
+{% endprettify %}
+
+If the extended type defines a `call` method, then remove the extension
+override.
+
+If the `call` method isn't defined, then rewrite the code so that it
+doesn't invoke the `call` method.
+
### invocation_of_non_function
_'{0}' isn't a function._
@@ -1352,7 +2181,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `Binary` is the name of
+a function type, not a function:
{% prettify dart %}
typedef Binary = int Function(int, int);
@@ -1366,6 +2196,46 @@
Replace the name with the name of a function.
+### list_element_type_not_assignable
+
+_The element type '{0}' can't be assigned to the list type '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when the type of an element in a list
+literal isn't assignable to the element type of the list.
+
+#### Example
+
+The following code produces this diagnostic because `2.5` is a double, and
+the list can hold only integers:
+
+{% prettify dart %}
+List<int> x = [1, [!2.5!], 3];
+{% endprettify %}
+
+#### Common fixes
+
+If you intended to add a different object to the list, then replace the
+element with an expression that computes the intended object:
+
+{% prettify dart %}
+List<int> x = [1, 2, 3];
+{% endprettify %}
+
+If the object shouldn't be in the list, then remove the element:
+
+{% prettify dart %}
+List<int> x = [1, 3];
+{% endprettify %}
+
+If the object being computed is correct, then widen the element type of the
+list to allow all of the different types of objects it needs to contain:
+
+{% prettify dart %}
+List<num> x = [1, 2.5, 3];
+{% endprettify %}
+
### map_entry_not_in_map
_Map entries can only be used in a map literal._
@@ -1377,7 +2247,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the literal has a map
+entry even though it's a set literal:
{% prettify dart %}
const collection = <String>{[!'a' : 'b'!]};
@@ -1404,6 +2275,47 @@
const collection = <String>{'a', 'b'};
{% endprettify %}
+### missing_required_param
+
+_The parameter '{0}' is required._
+
+_The parameter '{0}' is required. {1}._
+
+#### Description
+
+The analyzer produces this diagnostic when a method or function with a
+named parameter that is annotated as being required is invoked without
+providing a value for the parameter.
+
+#### Example
+
+The following code produces this diagnostic because the named parameter `x`
+is required:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+
+void f({@required int x}) {}
+
+void g() {
+ [!f!]();
+}
+{% endprettify %}
+
+#### Common fixes
+
+Provide the required value:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+
+void f({@required int x}) {}
+
+void g() {
+ f(x: 2);
+}
+{% endprettify %}
+
### missing_return
_This function has a return type of '{0}', but doesn't end with a return
@@ -1417,7 +2329,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `f` doesn't end with a
+return:
{% prettify dart %}
int [!f!](int x) {
@@ -1432,6 +2345,177 @@
Add a return statement that makes the return value explicit, even if `null`
is the appropriate value.
+### mixin_on_sealed_class
+
+_The class '{0}' shouldn't be used as a mixin constraint because it is sealed,
+and any class mixing in this mixin must have '{0}' as a superclass._
+
+#### Description
+
+The analyzer produces this diagnostic when the superclass constraint of a
+mixin is a class from a different package that was marked as `@sealed`.
+Classes that are sealed can't be extended, implemented, mixed in, or used
+as a superclass constraint.
+
+#### Example
+
+If the package 'p' defines a sealed class:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+
+@sealed
+class C {}
+{% endprettify %}
+
+Then, the following code, when in a package other than 'p', produces this
+diagnostic:
+
+{% prettify dart %}
+import 'package:p/p.dart';
+
+[!mixin M on C {}!]
+{% endprettify %}
+
+#### Common fixes
+
+If the classes that use the mixin don't need to be subclasses of the sealed
+class, then consider adding a field and delegating to the wrapped instance
+of the sealed class.
+
+### mixin_super_class_constraint_non_interface
+
+_Only classes and mixins can be used as superclass constraints._
+
+#### Description
+
+The analyzer produces this diagnostic when a type following the `on`
+keyword in a mixin declaration is neither a class nor a mixin.
+
+#### Example
+
+The following code produces this diagnostic because `F` is neither a class
+nor a mixin:
+
+{% prettify dart %}
+typedef F = void Function();
+
+mixin M on [!F!] {}
+{% endprettify %}
+
+#### Common fixes
+
+If the type was intended to be a class but was mistyped, then replace the
+name.
+
+Otherwise, remove the type from the on clause.
+
+### non_abstract_class_inherits_abstract_member
+
+_Missing concrete implementation of '{0}'._
+
+_Missing concrete implementations of '{0}' and '{1}'._
+
+_Missing concrete implementations of '{0}', '{1}', '{2}', '{3}', and {4} more._
+
+_Missing concrete implementations of '{0}', '{1}', '{2}', and '{3}'._
+
+_Missing concrete implementations of '{0}', '{1}', and '{2}'._
+
+#### Description
+
+The analyzer produces this diagnostic when a concrete class inherits one or
+more abstract members, and doesn't provide or inherit an implementation for
+at least one of those abstract members.
+
+#### Example
+
+The following code produces this diagnostic because the class `B` doesn't
+have a concrete implementation of `m`:
+
+{% prettify dart %}
+abstract class A {
+ void m();
+}
+
+class [!B!] extends A {}
+{% endprettify %}
+
+#### Common fixes
+
+If the subclass can provide a concrete implementation for some or all of
+the abstract inherited members, then add the concrete implementations:
+
+{% prettify dart %}
+abstract class A {
+ void m();
+}
+
+class B extends A {
+ void m() {}
+}
+{% endprettify %}
+
+If there is a mixin that provides an implementation of the inherited
+methods, then apply the mixin to the subclass:
+
+{% prettify dart %}
+abstract class A {
+ void m();
+}
+
+class B extends A with M {}
+
+mixin M {
+ void m() {}
+}
+{% endprettify %}
+
+If the subclass can't provide a concrete implementation for all of the
+abstract inherited members, then mark the subclass as being abstract:
+
+{% prettify dart %}
+abstract class A {
+ void m();
+}
+
+abstract class B extends A {}
+{% endprettify %}
+
+### non_bool_condition
+
+_Conditions must have a static type of 'bool'._
+
+#### Description
+
+The analyzer produces this diagnostic when a condition, such as an `if` or
+`while` loop, doesn't have the static type `bool`.
+
+#### Example
+
+The following code produces this diagnostic because `x` has the static type
+`int`:
+
+{% prettify dart %}
+void f(int x) {
+ if ([!x!]) {
+ // ...
+ }
+}
+{% endprettify %}
+
+#### Common fixes
+
+Change the condition so that it produces a Boolean value:
+
+{% prettify dart %}
+void f(int x) {
+ if (x == 0) {
+ // ...
+ }
+}
+{% endprettify %}
+
### non_constant_case_expression
_Case expressions must be constant._
@@ -1443,7 +2527,7 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `j` isn't a constant:
{% prettify dart %}
void f(int i, int j) {
@@ -1468,6 +2552,47 @@
}
{% endprettify %}
+### non_constant_default_value
+
+_The default value of an optional parameter must be constant._
+
+#### Description
+
+The analyzer produces this diagnostic when an optional parameter, either
+named or positional, has a default value that isn't a compile-time
+constant.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+var defaultValue = 3;
+
+void f([int value = [!defaultValue!]]) {}
+{% endprettify %}
+
+#### Common fixes
+
+If the default value can be converted to be a constant, then convert it:
+
+{% prettify dart %}
+const defaultValue = 3;
+
+void f([int value = defaultValue]) {}
+{% endprettify %}
+
+If the default value needs to change over time, then apply the default
+value inside the function:
+
+{% prettify dart %}
+var defaultValue = 3;
+
+void f([int value]) {
+ value ??= defaultValue;
+}
+{% endprettify %}
+
### non_constant_list_element
_The values in a const list literal must be constants._
@@ -1567,7 +2692,7 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic beause `a` isn't a constant:
{% prettify dart %}
var a = 'a';
@@ -1602,7 +2727,7 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `a` isn't a constant:
{% prettify dart %}
var a = 'a';
@@ -1626,6 +2751,52 @@
var m = {0: a};
{% endprettify %}
+### non_const_call_to_literal_constructor
+
+_This instance creation must be 'const', because the {0} constructor is marked
+as '@literal'._
+
+_This instance creation must be 'const', because the {0} constructor is marked
+as '@literal'._
+
+#### Description
+
+The analyzer produces this diagnostic when a constructor that has the
+`@literal` annotation is invoked without using the `const` keyword, but all
+of the arguments to the constructor are constants. The annotation indicates
+that the constructor should be used to create a constant value whenever
+possible.
+
+#### Example
+
+The following code produces this diagnostic:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+
+class C {
+ @literal
+ const C();
+}
+
+C f() => [!C()!];
+{% endprettify %}
+
+#### Common fixes
+
+Add the keyword `const` before the constructor invocation:
+
+{% prettify dart %}
+import 'package:meta/meta.dart';
+
+class C {
+ @literal
+ const C();
+}
+
+void f() => const C();
+{% endprettify %}
+
### non_type_as_type_argument
_The name '{0}' isn't a type so it can't be used as a type argument._
@@ -1688,7 +2859,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `f` declares two
+required parameters, but only one argument is provided:
{% prettify dart %}
void f(int a, int b) {}
@@ -1749,7 +2921,7 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `l` isn't a `Map`:
{% prettify dart %}
var l = <String>['a', 'b'];
@@ -1766,6 +2938,51 @@
var m = <int, String>{...l.asMap()};
{% endprettify %}
+### override_on_non_overriding_member
+
+_The field doesn't override an inherited getter or setter._
+
+_The getter doesn't override an inherited getter._
+
+_The method doesn't override an inherited method._
+
+_The setter doesn't override an inherited setter._
+
+#### Description
+
+The analyzer produces this diagnostic when a class member is annotated with
+the `@override` annotation, but the member isn’t declared in any of the
+supertypes of the class.
+
+#### Example
+
+The following code produces this diagnostic because `m` isn't declared in
+any of the supertypes of `C`:
+
+{% prettify dart %}
+class C {
+ @override
+ String [!m!]() => '';
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the member is intended to override a member with a different name, then
+update the member to have the same name:
+
+{% prettify dart %}
+class C {
+ @override
+ String toString() => '';
+}
+{% endprettify %}
+
+If the member is intended to override a member that was removed from the
+superclass, then consider removing the member from the subclass.
+
+If the member can't be removed, then remove the annotation.
+
### redirect_to_non_class
_The name '{0}' isn't a type and can't be used in a redirected constructor._
@@ -1824,7 +3041,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `i` is used before it
+is declared:
{% prettify dart %}
void f() {
@@ -1857,6 +3075,43 @@
}
{% endprettify %}
+### return_of_invalid_type
+
+_A value of type '{0} can't be returned from function '{2}' because it has a
+return type of '{1}'._
+
+_A value of type '{0} can't be returned from method '{2}' because it has a
+return type of '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when a method or function returns a
+value whose type isn't assignable to the declared return type.
+
+#### Example
+
+The following code produces this diagnostic because `f` has a return type
+of `String` but is returning an `int`:
+
+{% prettify dart %}
+String f() => [!3!];
+{% endprettify %}
+
+#### Common fixes
+
+If the return type is correct, then replace the value being returned with a
+value of the correct type, possibly by converting the existing value:
+
+{% prettify dart %}
+String f() => 3.toString();
+{% endprettify %}
+
+If the value is correct, then change the return type to match:
+
+{% prettify dart %}
+int f() => 3;
+{% endprettify %}
+
### sdk_version_async_exported_from_core
_The class '{0}' wasn't exported from 'dart:core' until version 2.1, but this
@@ -2344,7 +3599,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `super` can't be used
+in an extension:
{% prettify dart %}
extension E on Object {
@@ -2373,7 +3629,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `String` isn't a
+subclass of `num`:
{% prettify dart %}
class A<E extends num> {}
@@ -2402,7 +3659,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the name `Srting` isn't
+defined:
{% prettify dart %}
void f(Object o) {
@@ -2435,7 +3693,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the name `undefined`
+isn't defined:
{% prettify dart %}
[!@undefined!]
@@ -2475,7 +3734,7 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `Piont` isn't defined:
{% prettify dart %}
class Point {}
@@ -2791,7 +4050,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the name `emty` isn't
+defined:
{% prettify dart %}
List<int> empty() => [];
@@ -2830,7 +4090,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `String` has no member
+named `len`:
{% prettify dart %}
int f(String s) => s.[!len!];
@@ -2858,7 +4119,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the name `rihgt` isn't
+defined:
{% prettify dart %}
int min(int left, int right) => left <= [!rihgt!] ? left : right;
@@ -2889,7 +4151,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the identifier
+`removeMiddle` isn't defined:
{% prettify dart %}
int f(List<int> l) => l.[!removeMiddle!]();
@@ -2917,7 +4180,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `m` doesn't declare a
+named parameter named `a`:
{% prettify dart %}
class C {
@@ -2973,6 +4237,38 @@
}
{% endprettify %}
+### undefined_operator
+
+_The operator '{0}' isn't defined for the class '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when a user-definable operator is
+invoked on an object for which the operator isn't defined.
+
+#### Example
+
+The following code produces this diagnostic because the class `C` doesn't
+define the operator `+`:
+
+{% prettify dart %}
+class C {}
+
+C f(C c) => c [!+!] 2;
+{% endprettify %}
+
+#### Common fixes
+
+If the operator should be defined for the class, then define it:
+
+{% prettify dart %}
+class C {
+ C operator +(int i) => this;
+}
+
+C f(C c) => c + 2;
+{% endprettify %}
+
### undefined_prefixed_name
_The name '{0}' is being referenced through the prefix '{1}', but it isn't
@@ -2986,7 +4282,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `dart:core` doesn't
+define anything named `a`:
{% prettify dart %}
import 'dart:core' as p;
@@ -3016,7 +4313,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because there isn't a setter
+named `z`:
{% prettify dart %}
class C {
@@ -3054,7 +4352,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `Object` doesn't define
+a member named `n`:
{% prettify dart %}
class C {
@@ -3088,7 +4387,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `m` is a static member
+of the extended type `C`:
{% prettify dart %}
class C {
@@ -3172,7 +4472,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because `_x` isn't referenced
+anywhere in the library:
{% prettify dart %}
class Point {
@@ -3198,7 +4499,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because nothing defined in
+`dart:async` is referenced in the library:
{% prettify dart %}
import [!'dart:async'!];
@@ -3224,7 +4526,8 @@
#### Example
-The following code produces this diagnostic:
+The following code produces this diagnostic because the value of `count` is
+never read:
{% prettify dart %}
void main() {
@@ -3295,3 +4598,66 @@
If the file isn't a generated file, then check the spelling of the URI or
create the file.
+
+### wrong_number_of_parameters_for_operator
+
+_Operator '{0}' should declare exactly {1} parameters, but {2} found._
+
+#### Description
+
+The analyzer produces this diagnostic when a declaration of an operator has
+the wrong number of parameters.
+
+#### Example
+
+The following code produces this diagnostic because the operator `+` must
+have a single parameter corresponding to the right operand:
+
+{% prettify dart %}
+class C {
+ int operator [!+!](a, b) => 0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+Add or remove parameters to match the required number:
+
+{% prettify dart %}
+class C {
+ int operator +(a) => 0;
+}
+{% endprettify %}
+
+### wrong_number_of_type_arguments
+
+_The type '{0}' is declared with {1} type parameters, but {2} type arguments
+were given._
+
+#### Description
+
+The analyzer produces this diagnostic when a type that has type parameters
+is used and type arguments are provided, but the number of type arguments
+isn't the same as the number of type parameters.
+
+#### Example
+
+The following code produces this diagnostic because `C` has one type
+parameter but two type arguments are provided:
+
+{% prettify dart %}
+class C<E> {}
+
+void f([!C<int, int>!] x) {}
+{% endprettify %}
+
+#### Common fixes
+
+Add or remove type arguments, as necessary, to match the number of type
+parameters defined for the type:
+
+{% prettify dart %}
+class C<E> {}
+
+void f(C<int> x) {}
+{% endprettify %}
diff --git a/pkg/analyzer/tool/diagnostics/generate.dart b/pkg/analyzer/tool/diagnostics/generate.dart
index 580c05d..17ffb98 100644
--- a/pkg/analyzer/tool/diagnostics/generate.dart
+++ b/pkg/analyzer/tool/diagnostics/generate.dart
@@ -163,12 +163,6 @@
_writeDiagnostics(sink);
}
- /// Return a version of the [text] in which characters that have special
- /// meaning in markdown have been escaped.
- String _escape(String text) {
- return text.replaceAll('_', '\\_');
- }
-
/// Extract documentation from all of the files containing the definitions of
/// diagnostics.
void _extractAllDocs() {
diff --git a/pkg/analyzer/tool/messages/generate.dart b/pkg/analyzer/tool/messages/generate.dart
index 176b649..0566bdf 100644
--- a/pkg/analyzer/tool/messages/generate.dart
+++ b/pkg/analyzer/tool/messages/generate.dart
@@ -26,6 +26,8 @@
main() async {
String analyzerPkgPath = normalize(join(pkg_root.packageRoot, 'analyzer'));
String frontEndPkgPath = normalize(join(pkg_root.packageRoot, 'front_end'));
+ String frontEndSharedPkgPath =
+ normalize(join(pkg_root.packageRoot, '_fe_analyzer_shared'));
Map<dynamic, dynamic> messagesYaml = loadYaml(
new File(join(frontEndPkgPath, 'messages.yaml')).readAsStringSync());
@@ -35,8 +37,8 @@
String syntacticErrorsSource = new File(join(analyzerPkgPath,
joinAll(posix.split('lib/src/dart/error/syntactic_errors.dart'))))
.readAsStringSync();
- String parserSource = new File(join(frontEndPkgPath,
- joinAll(posix.split('lib/src/fasta/parser/parser.dart'))))
+ String parserSource = new File(join(frontEndSharedPkgPath,
+ joinAll(posix.split('lib/src/parser/parser.dart'))))
.readAsStringSync();
final codeGenerator = new _SyntacticErrorGenerator(
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 8c70966..12601f9 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -11,12 +11,12 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/cache.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
@@ -471,7 +471,7 @@
}
void _createLinkedElementFactory() {
- var analysisContext = RestrictedAnalysisContext(
+ var analysisContext = AnalysisContextImpl(
SynchronousSession(analysisOptions, declaredVariables),
sourceFactory,
);
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index 3356456..7ebd969 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -15,7 +15,6 @@
main() {
group('CommandLineOptions', () {
group('parse', () {
- int lastExitHandlerCode;
StringBuffer outStringBuffer = new StringBuffer();
StringBuffer errorStringBuffer = new StringBuffer();
@@ -28,9 +27,7 @@
savedErrorSink = errorSink;
savedExitHandler = exitHandler;
savedExitCode = exitCode;
- exitHandler = (int code) {
- lastExitHandlerCode = code;
- };
+ exitHandler = (int code) {};
outSink = outStringBuffer;
errorSink = errorStringBuffer;
});
diff --git a/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart b/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
index d0a3556..2b320e8 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
@@ -155,20 +155,8 @@
visitForStatement(ForStatement node) {
var forLoopParts = node.forLoopParts;
if (forLoopParts is ForEachPartsWithDeclaration) {
- DeclaredIdentifier loopVar = forLoopParts.loopVariable;
- if (loopVar != null) {
- SimpleIdentifier id = loopVar.identifier;
- if (id != null) {
- // If there is no loop variable, don't declare it.
- declaredLocalVar(id, loopVar.type);
- }
- }
- } else if (forLoopParts is ForEachPartsWithIdentifier) {
- SimpleIdentifier id = forLoopParts.identifier;
- if (id != null) {
- // If there is no loop variable, don't declare it.
- declaredLocalVar(id, null);
- }
+ DeclaredIdentifier loopVariable = forLoopParts.loopVariable;
+ declaredLocalVar(loopVariable.identifier, loopVariable.type);
} else if (forLoopParts is ForPartsWithDeclarations) {
VariableDeclarationList varList = forLoopParts.variables;
if (varList != null) {
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
index cf31db3..1b2a9d3 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/type_member_contributor.dart
@@ -246,7 +246,7 @@
@override
void declaredGenericTypeAlias(GenericTypeAlias declaration) {
if (declaration.name.name == targetName) {
- TypeAnnotation typeName = declaration.functionType.returnType;
+ TypeAnnotation typeName = declaration.functionType?.returnType;
if (typeName != null) {
typeFound = typeName.type;
}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index 64cba71..37ce297 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -10,7 +10,6 @@
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/test_utilities/find_node.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -2831,8 +2830,7 @@
nullabilitySuffix: NullabilitySuffix.star,
);
- TypeSystem typeSystem = await session.typeSystem;
- var inherited = new InheritanceManager3(typeSystem).getInherited(
+ var inherited = new InheritanceManager3().getInherited(
targetType,
new Name(null, nameToOverride),
);
diff --git a/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart b/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
index 08ba2a4..194ea25 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
@@ -2070,6 +2070,14 @@
expect(suggestion.element.parameters, '(int value)');
}
+ test_genericTypeAlias_noFunctionType() async {
+ addTestSource('''
+typedef F=;
+g(F.^
+''');
+ await computeSuggestions();
+ }
+
test_IfStatement() async {
// SimpleIdentifier IfStatement
addTestSource('''
diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
index 095bec3..0a6c24b 100644
--- a/pkg/compiler/lib/src/constants/expressions.dart
+++ b/pkg/compiler/lib/src/constants/expressions.dart
@@ -847,7 +847,7 @@
final String name;
TypeConstantExpression(this.type, this.name) {
- assert(type.isInterfaceType || type.isTypedef || type.isDynamic,
+ assert(type is InterfaceType || type is TypedefType || type is DynamicType,
"Unexpected type constant type: $type");
}
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 1c392c8..0276634 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -317,7 +317,7 @@
DartType type = typeUse.type;
switch (typeUse.kind) {
case TypeUseKind.TYPE_LITERAL:
- if (type.isInterfaceType) {
+ if (type is InterfaceType) {
InterfaceType interface = type;
dependencies.addClass(
interface.element, typeUse.deferredImport);
@@ -1659,12 +1659,27 @@
}
@override
+ void visitLegacyType(LegacyType type, Null argument) {
+ visit(type.baseType);
+ }
+
+ @override
+ void visitNullableType(NullableType type, Null argument) {
+ visit(type.baseType);
+ }
+
+ @override
void visitFutureOrType(FutureOrType type, Null argument) {
_dependencies.addClass(_commonElements.futureClass);
visit(type.typeArgument);
}
@override
+ void visitNeverType(NeverType type, Null argument) {
+ // Nothing to add.
+ }
+
+ @override
void visitDynamicType(DynamicType type, Null argument) {
// Nothing to add.
}
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index ee278b1..a5cee44 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -36,6 +36,7 @@
DartType get unaliased => this;
/// Is `true` if this type is a top type.
+ // TODO(fishythefish): Update this for normalization.
bool get isTop => false;
/// Is `true` if this type has no non-dynamic type arguments.
@@ -44,39 +45,6 @@
/// Is `true` if this type should be treated as the dynamic type.
bool get treatAsDynamic => false;
- /// Is `true` if this type is the dynamic type.
- bool get isDynamic => false;
-
- /// Is `true` if this type is an erased type.
- bool get isErased => false;
-
- /// Is `true` if this type is the any type.
- bool get isAny => false;
-
- /// Is `true` if this type is the void type.
- bool get isVoid => false;
-
- /// Is `true` if this type is an interface type.
- bool get isInterfaceType => false;
-
- /// Is `true` if this type is a typedef.
- bool get isTypedef => false;
-
- /// Is `true` if this type is a function type.
- bool get isFunctionType => false;
-
- /// Is `true` if this type is a type variable.
- bool get isTypeVariable => false;
-
- /// Is `true` if this type is a type variable declared on a function type
- ///
- /// For instance `T` in
- /// void Function<T>(T t)
- bool get isFunctionTypeVariable => false;
-
- /// Is `true` if this type is a `FutureOr` type.
- bool get isFutureOr => false;
-
/// Whether this type contains a type variable.
bool get containsTypeVariables => false;
@@ -176,6 +144,82 @@
}
}
+class LegacyType extends DartType {
+ final DartType baseType;
+
+ LegacyType(this.baseType);
+
+ @override
+ bool get containsTypeVariables => baseType.containsTypeVariables;
+
+ @override
+ void forEachTypeVariable(f(TypeVariableType variable)) {
+ baseType.forEachTypeVariable(f);
+ }
+
+ @override
+ R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
+ visitor.visitLegacyType(this, argument);
+
+ @override
+ int get hashCode => baseType.hashCode * 31;
+
+ @override
+ bool operator ==(other) {
+ if (identical(this, other)) return true;
+ if (other is! LegacyType) return false;
+ return _equalsInternal(other, null);
+ }
+
+ @override
+ bool _equals(DartType other, _Assumptions assumptions) {
+ if (identical(this, other)) return true;
+ if (other is! LegacyType) return false;
+ return _equalsInternal(other, assumptions);
+ }
+
+ bool _equalsInternal(LegacyType other, _Assumptions assumptions) =>
+ baseType._equals(other.baseType, assumptions);
+}
+
+class NullableType extends DartType {
+ final DartType baseType;
+
+ NullableType(this.baseType);
+
+ @override
+ bool get containsTypeVariables => baseType.containsTypeVariables;
+
+ @override
+ void forEachTypeVariable(f(TypeVariableType variable)) {
+ baseType.forEachTypeVariable(f);
+ }
+
+ @override
+ R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
+ visitor.visitNullableType(this, argument);
+
+ @override
+ int get hashCode => baseType.hashCode * 37;
+
+ @override
+ bool operator ==(other) {
+ if (identical(this, other)) return true;
+ if (other is! NullableType) return false;
+ return _equalsInternal(other, null);
+ }
+
+ @override
+ bool _equals(DartType other, _Assumptions assumptions) {
+ if (identical(this, other)) return true;
+ if (other is! NullableType) return false;
+ return _equalsInternal(other, assumptions);
+ }
+
+ bool _equalsInternal(NullableType other, _Assumptions assumptions) =>
+ baseType._equals(other.baseType, assumptions);
+}
+
class InterfaceType extends DartType {
final ClassEntity element;
final List<DartType> typeArguments;
@@ -187,9 +231,6 @@
bool get isTop => isObject;
@override
- bool get isInterfaceType => true;
-
- @override
bool get isObject {
return element.name == 'Object' &&
element.library.canonicalUri == Uris.dart_core;
@@ -258,9 +299,6 @@
bool get isTop => unaliased.isTop;
@override
- bool get isTypedef => true;
-
- @override
bool get containsTypeVariables =>
typeArguments.any((type) => type.containsTypeVariables);
@@ -317,9 +355,6 @@
TypeVariableType(this.element);
@override
- bool get isTypeVariable => true;
-
- @override
bool get containsTypeVariables => true;
@override
@@ -379,9 +414,6 @@
}
@override
- bool get isFunctionTypeVariable => true;
-
- @override
int get hashCode => index.hashCode * 19;
@override
@@ -404,6 +436,23 @@
visitor.visitFunctionTypeVariable(this, argument);
}
+class NeverType extends DartType {
+ const NeverType._();
+
+ factory NeverType() => const NeverType._();
+
+ @override
+ R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
+ visitor.visitNeverType(this, argument);
+
+ @override
+ int get hashCode => 41;
+
+ @override
+ bool _equals(DartType other, _Assumptions assumptions) =>
+ identical(this, other);
+}
+
class VoidType extends DartType {
const VoidType._();
@@ -413,9 +462,6 @@
bool get isTop => true;
@override
- bool get isVoid => true;
-
- @override
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitVoidType(this, argument);
@@ -437,9 +483,6 @@
bool get isTop => true;
@override
- bool get isDynamic => true;
-
- @override
bool get treatAsDynamic => true;
@override
@@ -467,9 +510,6 @@
bool get treatAsDynamic => true;
@override
- bool get isErased => true;
-
- @override
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitErasedType(this, argument);
@@ -501,9 +541,6 @@
bool get isTop => true;
@override
- bool get isAny => true;
-
- @override
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument) =>
visitor.visitAnyType(this, argument);
@@ -565,9 +602,6 @@
namedParameterTypes.forEach((type) => type.forEachTypeVariable(f));
}
- @override
- bool get isFunctionType => true;
-
FunctionType instantiate(List<DartType> arguments) {
return subst(arguments, typeVariables);
}
@@ -648,9 +682,6 @@
bool get isTop => typeArgument.isTop;
@override
- bool get isFutureOr => true;
-
- @override
bool get containsTypeVariables => typeArgument.containsTypeVariables;
@override
@@ -699,6 +730,12 @@
R visit(covariant DartType type, A argument) => type.accept(this, argument);
+ R visitLegacyType(covariant LegacyType type, A argument) => null;
+
+ R visitNullableType(covariant NullableType type, A argument) => null;
+
+ R visitNeverType(covariant NeverType type, A argument) => null;
+
R visitVoidType(covariant VoidType type, A argument) => null;
R visitTypeVariableType(covariant TypeVariableType type, A argument) => null;
@@ -728,6 +765,18 @@
R visitType(covariant DartType type, A argument);
@override
+ R visitLegacyType(covariant LegacyType type, A argument) =>
+ visitType(type, argument);
+
+ @override
+ R visitNullableType(covariant NullableType type, A argument) =>
+ visitType(type, argument);
+
+ @override
+ R visitNeverType(covariant NeverType type, A argument) =>
+ visitType(type, argument);
+
+ @override
R visitVoidType(covariant VoidType type, A argument) =>
visitType(type, argument);
@@ -794,6 +843,35 @@
type;
@override
+ DartType visitLegacyType(covariant LegacyType type, A argument) {
+ DartType probe = _map[type];
+ if (probe != null) return probe;
+
+ DartType newBaseType = visit(type.baseType, argument);
+ // Create a new type only if necessary.
+ if (identical(type.baseType, newBaseType)) {
+ return _mapped(type, type);
+ }
+ return _mapped(type, LegacyType(newBaseType));
+ }
+
+ @override
+ DartType visitNullableType(covariant NullableType type, A argument) {
+ DartType probe = _map[type];
+ if (probe != null) return probe;
+
+ DartType newBaseType = visit(type.baseType, argument);
+ // Create a new type only if necessary.
+ if (identical(type.baseType, newBaseType)) {
+ return _mapped(type, type);
+ }
+ return _mapped(type, NullableType(newBaseType));
+ }
+
+ @override
+ DartType visitNeverType(covariant NeverType type, A argument) => type;
+
+ @override
DartType visitTypeVariableType(covariant TypeVariableType type, A argument) {
return substituteTypeVariableType(type, argument, true);
}
@@ -803,8 +881,8 @@
covariant FunctionTypeVariable type, A argument) {
// Function type variables are added to the map only for type variables that
// need to be replaced with updated bounds.
- DartType seen = _map[type];
- if (seen != null) return seen;
+ DartType probe = _map[type];
+ if (probe != null) return probe;
return substituteFunctionTypeVariable(type, argument, true);
}
@@ -813,8 +891,8 @@
@override
DartType visitFunctionType(covariant FunctionType type, A argument) {
- DartType seen = _map[type];
- if (seen != null) return seen;
+ DartType probe = _map[type];
+ if (probe != null) return probe;
List<FunctionTypeVariable> newTypeVariables =
_handleFunctionTypeVariables(type.typeVariables, argument);
@@ -919,8 +997,8 @@
return type;
}
- DartType seen = _map[type];
- if (seen != null) return seen;
+ DartType probe = _map[type];
+ if (probe != null) return probe;
List<DartType> newTypeArguments = _substTypes(typeArguments, argument);
// Create a new type only if necessary.
@@ -932,8 +1010,8 @@
@override
DartType visitTypedefType(covariant TypedefType type, A argument) {
- DartType seen = _map[type];
- if (seen != null) return seen;
+ DartType probe = _map[type];
+ if (probe != null) return probe;
List<DartType> newTypeArguments = _substTypes(type.typeArguments, argument);
FunctionType newUnaliased = visit(type.unaliased, argument);
@@ -957,8 +1035,8 @@
@override
DartType visitFutureOrType(covariant FutureOrType type, A argument) {
- DartType seen = _map[type];
- if (seen != null) return seen;
+ DartType probe = _map[type];
+ if (probe != null) return probe;
DartType newTypeArgument = visit(type.typeArgument, argument);
// Create a new type only if necessary.
@@ -998,8 +1076,8 @@
bool handleFreeFunctionTypeVariable(FunctionTypeVariable type) {
// Function type variables are added to the map for type variables that need
// to be replaced with updated bounds.
- DartType seen = _substitutionVisitor._map[type];
- if (seen != null) return seen != type;
+ DartType probe = _substitutionVisitor._map[type];
+ if (probe != null) return probe != type;
return !identical(
type,
_substitutionVisitor.substituteFunctionTypeVariable(
@@ -1008,7 +1086,7 @@
}
/// A visitor that by default visits the substructure of the type until some
-/// visit returns `true`. The default handers return `false` which will search
+/// visit returns `true`. The default handlers return `false` which will search
/// the whole structure unless overridden.
abstract class DartTypeStructuralPredicateVisitor
extends DartTypeVisitor<bool, List<FunctionTypeVariable>> {
@@ -1016,6 +1094,9 @@
bool run(DartType type) => visit(type, null);
+ bool handleLegacyType(LegacyType type) => false;
+ bool handleNullableType(NullableType type) => false;
+ bool handleNeverType(NeverType type) => false;
bool handleVoidType(VoidType type) => false;
bool handleTypeVariableType(TypeVariableType type) => false;
bool handleBoundFunctionTypeVariable(FunctionTypeVariable type) => false;
@@ -1029,6 +1110,19 @@
bool handleFutureOrType(FutureOrType type) => false;
@override
+ bool visitLegacyType(LegacyType type, List<FunctionTypeVariable> bindings) =>
+ handleLegacyType(type) || visit(type.baseType, bindings);
+
+ @override
+ bool visitNullableType(
+ NullableType type, List<FunctionTypeVariable> bindings) =>
+ handleNullableType(type) || visit(type.baseType, bindings);
+
+ @override
+ bool visitNeverType(NeverType type, List<FunctionTypeVariable> bindings) =>
+ false;
+
+ @override
bool visitVoidType(VoidType type, List<FunctionTypeVariable> bindings) =>
handleVoidType(type);
@@ -1219,6 +1313,23 @@
}
@override
+ void visitLegacyType(covariant LegacyType type, _) {
+ _visit(type.baseType);
+ _token('*');
+ }
+
+ @override
+ void visitNullableType(covariant NullableType type, _) {
+ _visit(type.baseType);
+ _token('?');
+ }
+
+ @override
+ void visitNeverType(covariant NeverType type, _) {
+ _identifier('Never');
+ }
+
+ @override
void visitVoidType(covariant VoidType type, _) {
_identifier('void');
}
@@ -1365,6 +1476,8 @@
}
/// Abstract visitor for determining relations between types.
+// TODO(fishythefish): Rewrite type relations to support NNBD types and new
+// subtyping algorithm structure.
abstract class AbstractTypeRelation<T extends DartType>
extends BaseDartTypeVisitor<bool, T> {
CommonElements get commonElements;
@@ -1573,11 +1686,11 @@
bool visitTypeVariableType(TypeVariableType t, T s) {
// Identity check is handled in [isSubtype].
DartType bound = getTypeVariableBound(t.element);
- if (bound.isTypeVariable) {
+ if (bound is TypeVariableType) {
// The bound is potentially cyclic so we need to be extra careful.
Set<TypeVariableEntity> seenTypeVariables = new Set<TypeVariableEntity>();
seenTypeVariables.add(t.element);
- while (bound.isTypeVariable) {
+ while (bound is TypeVariableType) {
TypeVariableType typeVariable = bound;
if (bound == s) {
// [t] extends [s].
@@ -1599,7 +1712,7 @@
@override
bool visitFunctionTypeVariable(FunctionTypeVariable t, DartType s) {
- if (!s.isFunctionTypeVariable) return false;
+ if (s is! FunctionTypeVariable) return false;
return assumptions.isAssumed(t, s);
}
}
@@ -1608,10 +1721,10 @@
extends AbstractTypeRelation<T> {
bool isMoreSpecific(T t, T s) {
if (identical(t, s) ||
- t.isAny ||
- s.isAny ||
+ t is AnyType ||
+ s is AnyType ||
s.treatAsDynamic ||
- s.isVoid ||
+ s is VoidType ||
s == commonElements.objectType ||
t == commonElements.nullType) {
return true;
@@ -1633,8 +1746,8 @@
@override
bool invalidFunctionReturnTypes(T t, T s) {
- if (s.treatAsDynamic && t.isVoid) return true;
- return !s.isVoid && !isMoreSpecific(t, s);
+ if (s.treatAsDynamic && t is VoidType) return true;
+ return s is! VoidType && !isMoreSpecific(t, s);
}
@override
@@ -1662,12 +1775,12 @@
abstract class SubtypeVisitor<T extends DartType>
extends MoreSpecificVisitor<T> {
bool isSubtype(DartType t, DartType s) {
- if (t.isAny || s.isAny) return true;
- if (s.isFutureOr) {
+ if (t is AnyType || s is AnyType) return true;
+ if (s is FutureOrType) {
FutureOrType sFutureOr = s;
if (isSubtype(t, sFutureOr.typeArgument)) {
return true;
- } else if (t.isInterfaceType) {
+ } else if (t is InterfaceType) {
InterfaceType tInterface = t;
if (tInterface.element == commonElements.futureClass &&
isSubtype(
@@ -1710,7 +1823,7 @@
@override
bool visitFutureOrType(FutureOrType t, covariant DartType s) {
- if (s.isFutureOr) {
+ if (s is FutureOrType) {
FutureOrType sFutureOr = s;
return isSubtype(t.typeArgument, sFutureOr.typeArgument);
}
@@ -1727,7 +1840,7 @@
@override
bool isSubtype(DartType t, DartType s) {
- if (t.isAny || s.isAny) return true;
+ if (t is AnyType || s is AnyType) return true;
if (t is TypeVariableType || s is TypeVariableType) {
return true;
}
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index 4c49acb..48e3b92 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -1692,7 +1692,7 @@
DartType type = node.guard != null
? _elementMap.getDartType(node.guard)
: DynamicType();
- if (type.isInterfaceType) {
+ if (type is InterfaceType) {
InterfaceType interfaceType = type;
mask = _types.nonNullSubtype(interfaceType.element);
} else {
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index a4accab..98c43b2 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -387,11 +387,11 @@
mappedType = types.boolType;
} else if (type == commonElements.nullType) {
mappedType = types.nullType;
- } else if (type.isVoid) {
+ } else if (type is VoidType) {
mappedType = types.nullType;
- } else if (type.isDynamic) {
+ } else if (type is DynamicType) {
return types.dynamicType;
- } else if (type.isInterfaceType) {
+ } else if (type is InterfaceType) {
mappedType = types.nonNullSubtype(type.element);
} else {
mappedType = types.dynamicType;
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index f674734..af0410d 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -2275,21 +2275,21 @@
AbstractValue otherType;
if (annotation.treatAsDynamic) {
return type;
- } else if (annotation.isInterfaceType) {
- InterfaceType interfaceType = annotation;
- if (interfaceType.element == closedWorld.commonElements.objectClass) {
+ } else if (annotation is InterfaceType) {
+ if (annotation.element == closedWorld.commonElements.objectClass) {
return type;
}
- otherType = abstractValueDomain.createNonNullSubtype(interfaceType.element);
- } else if (annotation.isVoid) {
+ otherType = abstractValueDomain.createNonNullSubtype(annotation.element);
+ } else if (annotation is VoidType) {
return type;
- } else if (annotation.isTypedef || annotation.isFunctionType) {
+ } else if (annotation is TypedefType || annotation is FunctionType) {
otherType = closedWorld.abstractValueDomain.functionType;
- } else if (annotation.isFutureOr) {
+ } else if (annotation is FutureOrType) {
// TODO(johnniwinther): Narrow FutureOr types.
return type;
} else {
- assert(annotation.isTypeVariable || annotation.isFunctionTypeVariable);
+ assert(
+ annotation is TypeVariableType || annotation is FunctionTypeVariable);
// TODO(ngeoffray): Narrow to bound.
return type;
}
diff --git a/pkg/compiler/lib/src/inferrer/type_system.dart b/pkg/compiler/lib/src/inferrer/type_system.dart
index c5c32cf..2e05bac 100644
--- a/pkg/compiler/lib/src/inferrer/type_system.dart
+++ b/pkg/compiler/lib/src/inferrer/type_system.dart
@@ -318,14 +318,14 @@
TypeInformation narrowType(TypeInformation type, DartType annotation,
{bool isNullable: true}) {
AbstractValue otherType;
- if (annotation.isVoid) return type;
+ if (annotation is VoidType) return type;
if (annotation.treatAsDynamic) {
if (isNullable) return type;
// If the input is already narrowed to be not-null, there is no value
// in adding another narrowing node.
if (_isNonNullNarrow(type)) return type;
otherType = _abstractValueDomain.excludeNull(dynamicType.type);
- } else if (annotation.isInterfaceType) {
+ } else if (annotation is InterfaceType) {
InterfaceType interface = annotation;
if (interface.element == _closedWorld.commonElements.objectClass) {
if (isNullable) return type;
@@ -335,13 +335,13 @@
otherType =
_abstractValueDomain.createNonNullSubtype(interface.element);
}
- } else if (annotation.isTypedef || annotation.isFunctionType) {
+ } else if (annotation is TypedefType || annotation is FunctionType) {
otherType = functionType.type;
- } else if (annotation.isFutureOr) {
+ } else if (annotation is FutureOrType) {
// TODO(johnniwinther): Support narrowing of FutureOr.
return type;
} else {
- assert(annotation.isTypeVariable);
+ assert(annotation is TypeVariableType);
// TODO(ngeoffray): Narrow to bound.
return type;
}
diff --git a/pkg/compiler/lib/src/ir/annotations.dart b/pkg/compiler/lib/src/ir/annotations.dart
index 4e10bf8..899b8d0 100644
--- a/pkg/compiler/lib/src/ir/annotations.dart
+++ b/pkg/compiler/lib/src/ir/annotations.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
import '../common/names.dart';
import 'modular.dart';
@@ -125,13 +126,15 @@
IrAnnotationData data = new IrAnnotationData();
void processMember(ir.Member member) {
+ ir.StaticTypeContext staticTypeContext = new ir.StaticTypeContext(
+ member, modularCore.constantEvaluator.typeEnvironment);
List<PragmaAnnotationData> pragmaAnnotations;
List<String> createsAnnotations;
List<String> returnsAnnotations;
for (ir.Expression annotation in member.annotations) {
if (annotation is ir.ConstantExpression) {
- ir.Constant constant =
- modularCore.constantEvaluator.evaluate(annotation);
+ ir.Constant constant = modularCore.constantEvaluator
+ .evaluate(staticTypeContext, annotation);
String jsName = _getJsInteropName(constant);
if (jsName != null) {
@@ -176,10 +179,13 @@
}
for (ir.Library library in component.libraries) {
+ ir.StaticTypeContext staticTypeContext =
+ new ir.StaticTypeContext.forAnnotations(
+ library, modularCore.constantEvaluator.typeEnvironment);
for (ir.Expression annotation in library.annotations) {
if (annotation is ir.ConstantExpression) {
- ir.Constant constant =
- modularCore.constantEvaluator.evaluate(annotation);
+ ir.Constant constant = modularCore.constantEvaluator
+ .evaluate(staticTypeContext, annotation);
String jsName = _getJsInteropName(constant);
if (jsName != null) {
@@ -190,8 +196,8 @@
for (ir.Class cls in library.classes) {
for (ir.Expression annotation in cls.annotations) {
if (annotation is ir.ConstantExpression) {
- ir.Constant constant =
- modularCore.constantEvaluator.evaluate(annotation);
+ ir.Constant constant = modularCore.constantEvaluator
+ .evaluate(staticTypeContext, annotation);
String nativeClassName = _getNativeClassName(constant);
if (nativeClassName != null) {
diff --git a/pkg/compiler/lib/src/ir/cached_static_type.dart b/pkg/compiler/lib/src/ir/cached_static_type.dart
index ea00634..efda170 100644
--- a/pkg/compiler/lib/src/ir/cached_static_type.dart
+++ b/pkg/compiler/lib/src/ir/cached_static_type.dart
@@ -17,11 +17,13 @@
final StaticTypeCache _cache;
@override
+ final ir.StaticTypeContext staticTypeContext;
+
+ @override
final ThisInterfaceType thisType;
- CachedStaticType(
- ir.TypeEnvironment typeEnvironment, this._cache, this.thisType)
- : super(typeEnvironment);
+ CachedStaticType(this.staticTypeContext, this._cache, this.thisType)
+ : super(staticTypeContext.typeEnvironment);
@override
ir.DartType getStaticType(ir.Expression node) {
diff --git a/pkg/compiler/lib/src/ir/constants.dart b/pkg/compiler/lib/src/ir/constants.dart
index 5235031..fd7b002 100644
--- a/pkg/compiler/lib/src/ir/constants.dart
+++ b/pkg/compiler/lib/src/ir/constants.dart
@@ -34,12 +34,15 @@
ErrorReporter get errorReporter => super.errorReporter;
@override
- ir.Constant evaluate(ir.Expression node, {bool requireConstant: true}) {
+ ir.Constant evaluate(
+ ir.StaticTypeContext staticTypeContext, ir.Expression node,
+ {bool requireConstant: true}) {
errorReporter.requiresConstant = requireConstant;
if (node is ir.ConstantExpression) {
ir.Constant constant = node.constant;
if (constant is ir.UnevaluatedConstant) {
- ir.Constant result = super.evaluate(constant.expression);
+ ir.Constant result =
+ super.evaluate(staticTypeContext, constant.expression);
assert(
result is ir.UnevaluatedConstant ||
!result.accept(const UnevaluatedConstantFinder()),
@@ -54,10 +57,10 @@
if (requireConstant) {
// TODO(johnniwinther): Handle reporting of compile-time constant
// evaluation errors.
- return super.evaluate(node);
+ return super.evaluate(staticTypeContext, node);
} else {
try {
- return super.evaluate(node);
+ return super.evaluate(staticTypeContext, node);
} catch (e) {
return null;
}
diff --git a/pkg/compiler/lib/src/ir/element_map.dart b/pkg/compiler/lib/src/ir/element_map.dart
index 250c391..09aecbe 100644
--- a/pkg/compiler/lib/src/ir/element_map.dart
+++ b/pkg/compiler/lib/src/ir/element_map.dart
@@ -59,6 +59,7 @@
CommonElements get commonElements;
DiagnosticReporter get reporter;
+ ir.CoreTypes get coreTypes;
InterfaceType getThisType(IndexedClass cls);
InterfaceType getSuperType(IndexedClass cls);
OrderedTypeSet getOrderedTypeSet(IndexedClass cls);
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index 0954db8..8deb4c3 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -198,9 +198,12 @@
@override
final VariableScopeModel variableScopeModel;
- ImpactBuilderBase(ir.TypeEnvironment typeEnvironment,
- ir.ClassHierarchy classHierarchy, this.variableScopeModel)
- : super(typeEnvironment, classHierarchy);
+ @override
+ final ir.StaticTypeContext staticTypeContext;
+
+ ImpactBuilderBase(this.staticTypeContext, ir.ClassHierarchy classHierarchy,
+ this.variableScopeModel)
+ : super(staticTypeContext.typeEnvironment, classHierarchy);
@override
void handleIntLiteral(ir.IntLiteral node) {
@@ -668,10 +671,10 @@
@override
final inferEffectivelyFinalVariableTypes;
- ImpactBuilder(ir.TypeEnvironment typeEnvironment,
+ ImpactBuilder(ir.StaticTypeContext staticTypeContext,
ir.ClassHierarchy classHierarchy, VariableScopeModel variableScopeModel,
{this.useAsserts: false, this.inferEffectivelyFinalVariableTypes: true})
- : super(typeEnvironment, classHierarchy, variableScopeModel);
+ : super(staticTypeContext, classHierarchy, variableScopeModel);
ImpactBuilderData computeImpact(ir.Member node) {
if (retainDataForTesting) {
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 82402b7..21db425 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
import 'closure.dart';
@@ -15,6 +16,7 @@
class ScopeModelBuilder extends ir.Visitor<InitializerComplexity>
with VariableCollectorMixin {
final ir.ConstantEvaluator _constantEvaluator;
+ ir.StaticTypeContext _staticTypeContext;
final ClosureScopeModel _model = new ClosureScopeModel();
@@ -85,6 +87,8 @@
initializerComplexity: const InitializerComplexity.lazy());
}
+ _staticTypeContext =
+ new ir.StaticTypeContext(node, _constantEvaluator.typeEnvironment);
if (node is ir.Constructor) {
_hasThisLocal = true;
} else if (node is ir.Procedure && node.kind == ir.ProcedureKind.Factory) {
@@ -1074,7 +1078,7 @@
@override
InitializerComplexity visitConstantExpression(ir.ConstantExpression node) {
if (node.constant is ir.UnevaluatedConstant) {
- node.constant = _constantEvaluator.evaluate(node);
+ node.constant = _constantEvaluator.evaluate(_staticTypeContext, node);
}
return const InitializerComplexity.constant();
}
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index b54d98c..716567a 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -392,7 +392,9 @@
ir.DartType _narrowInstanceReceiver(
ir.Member interfaceTarget, ir.DartType receiverType) {
if (interfaceTarget != null && receiverType == const ir.DynamicType()) {
- receiverType = interfaceTarget.enclosingClass.thisType;
+ receiverType = interfaceTarget.enclosingClass.getThisType(
+ typeEnvironment.coreTypes,
+ interfaceTarget.enclosingLibrary.nonNullable);
}
return receiverType;
}
@@ -1377,7 +1379,8 @@
@override
Null visitProcedure(ir.Procedure node) {
- thisType = new ThisInterfaceType.from(node.enclosingClass?.thisType);
+ thisType = new ThisInterfaceType.from(node.enclosingClass?.getThisType(
+ typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable));
_currentVariables = {};
visitSignature(node.function);
visitNode(node.function.body);
@@ -1391,7 +1394,8 @@
@override
Null visitConstructor(ir.Constructor node) {
- thisType = new ThisInterfaceType.from(node.enclosingClass.thisType);
+ thisType = new ThisInterfaceType.from(node.enclosingClass.getThisType(
+ typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable));
_currentVariables = {};
visitSignature(node.function);
visitNodes(node.initializers);
@@ -1406,7 +1410,8 @@
@override
Null visitField(ir.Field node) {
- thisType = new ThisInterfaceType.from(node.enclosingClass?.thisType);
+ thisType = new ThisInterfaceType.from(node.enclosingClass?.getThisType(
+ typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable));
_currentVariables = {};
visitNode(node.initializer);
handleField(node);
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
index f8f4999..7ad2078 100644
--- a/pkg/compiler/lib/src/ir/static_type_base.dart
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -65,6 +65,8 @@
ir.TypeEnvironment get typeEnvironment => _typeEnvironment;
+ ir.StaticTypeContext get staticTypeContext;
+
ThisInterfaceType get thisType;
@override
@@ -131,17 +133,20 @@
@override
ir.DartType visitListLiteral(ir.ListLiteral node) {
- return typeEnvironment.literalListType(node.typeArgument);
+ return typeEnvironment.literalListType(
+ node.typeArgument, ir.Nullability.legacy);
}
@override
ir.DartType visitSetLiteral(ir.SetLiteral node) {
- return typeEnvironment.literalSetType(node.typeArgument);
+ return typeEnvironment.literalSetType(
+ node.typeArgument, ir.Nullability.legacy);
}
@override
ir.DartType visitMapLiteral(ir.MapLiteral node) {
- return typeEnvironment.literalMapType(node.keyType, node.valueType);
+ return typeEnvironment.literalMapType(
+ node.keyType, node.valueType, ir.Nullability.legacy);
}
@override
@@ -225,12 +230,13 @@
@override
ir.DartType visitLoadLibrary(ir.LoadLibrary node) {
- return typeEnvironment.futureType(const ir.DynamicType());
+ return typeEnvironment.futureType(
+ const ir.DynamicType(), ir.Nullability.legacy);
}
@override
ir.DartType visitConstantExpression(ir.ConstantExpression node) {
// TODO(johnniwinther): Include interface exactness where applicable.
- return node.getStaticType(typeEnvironment);
+ return node.getStaticType(staticTypeContext);
}
}
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index ffd71e5..22374f1 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -258,11 +258,11 @@
ConstantExpression visitTypeLiteral(ir.TypeLiteral node) {
String name;
DartType type = elementMap.getDartType(node.type);
- if (type.isDynamic) {
+ if (type is DynamicType) {
name = 'dynamic';
} else if (type is InterfaceType) {
name = type.element.name;
- } else if (type.isTypedef) {
+ } else if (type is TypedefType) {
// TODO(johnniwinther): Compute a name for the type literal? It is only
// used in error messages in the old SSA builder.
name = '?';
@@ -499,6 +499,8 @@
ConstructedConstantExpression superConstructorInvocation;
List<AssertConstantExpression> assertions = <AssertConstantExpression>[];
+ List<ir.DartType> parametersAsArguments = ir.getAsTypeArguments(
+ node.enclosingClass.typeParameters, node.enclosingLibrary);
for (ir.Initializer initializer in node.initializers) {
if (initializer is ir.FieldInitializer) {
registerField(initializer.field, visit(initializer.value));
@@ -509,9 +511,7 @@
initializer.arguments.types);
} else if (initializer is ir.RedirectingInitializer) {
superConstructorInvocation = _computeConstructorInvocation(
- initializer.target,
- initializer.arguments,
- node.enclosingClass.thisType.typeArguments);
+ initializer.target, initializer.arguments, parametersAsArguments);
} else if (initializer is ir.AssertInitializer) {
ConstantExpression condition = visit(initializer.statement.condition);
ConstantExpression message = initializer.statement.message != null
@@ -664,6 +664,7 @@
@override
DartType visitBottomType(ir.BottomType node) {
+ // TODO(fishythefish): Change `Null` to `Never` for NNBD.
return elementMap.commonElements.nullType;
}
}
diff --git a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
index c577600..46b78b2 100644
--- a/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
+++ b/pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart
@@ -58,7 +58,7 @@
@override
void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
- assert(node.typeExpression.isTypeVariable);
+ assert(node.typeExpression is TypeVariableType);
codegen.use(node.typeRepresentation);
arguments.add(codegen.pop());
}
@@ -73,7 +73,7 @@
@override
void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
- assert(node.typeExpression.isFunctionType);
+ assert(node.typeExpression is FunctionType);
codegen.use(node.typeRepresentation);
arguments.add(codegen.pop());
}
@@ -88,7 +88,7 @@
@override
void generateAdditionalArguments(SsaCodeGenerator codegen, ModularNamer namer,
HTypeConversion node, List<jsAst.Expression> arguments) {
- assert(node.typeExpression.isFutureOr);
+ assert(node.typeExpression is FutureOrType);
codegen.use(node.typeRepresentation);
arguments.add(codegen.pop());
}
@@ -203,23 +203,23 @@
String getCheckedModeHelperNameInternal(
DartType type, CommonElements commonElements,
{bool typeCast, bool nativeCheckOnly}) {
- assert(!type.isTypedef);
+ assert(type is! TypedefType);
- if (type.isTypeVariable) {
+ if (type is TypeVariableType) {
return typeCast
? 'subtypeOfRuntimeTypeCast'
: 'assertSubtypeOfRuntimeType';
}
- if (type.isFunctionType) {
+ if (type is FunctionType) {
return typeCast ? 'functionTypeCast' : 'functionTypeCheck';
}
- if (type.isFutureOr) {
+ if (type is FutureOrType) {
return typeCast ? 'futureOrCast' : 'futureOrCheck';
}
- assert(type.isInterfaceType,
+ assert(type is InterfaceType,
failedAt(NO_LOCATION_SPANNABLE, "Unexpected type: $type"));
InterfaceType interfaceType = type;
ClassEntity element = interfaceType.element;
@@ -284,7 +284,7 @@
return nativeCheck ? 'listSuperNative$suffix' : 'listSuper$suffix';
}
- if (type.isInterfaceType && !type.treatAsRaw) {
+ if (type is InterfaceType && !type.treatAsRaw) {
return typeCast ? 'subtypeCast' : 'assertSubtype';
}
diff --git a/pkg/compiler/lib/src/js_backend/codegen_listener.dart b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
index f7d02de..f4ae36c 100644
--- a/pkg/compiler/lib/src/js_backend/codegen_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
@@ -174,7 +174,7 @@
// If the type is a web component, we need to ensure the constructors are
// available to 'upgrade' the native object.
TypeConstantValue type = constant;
- if (type.representedType.isInterfaceType) {
+ if (type.representedType is InterfaceType) {
InterfaceType representedType = type.representedType;
_customElementsAnalysis.registerTypeConstant(representedType.element);
}
diff --git a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
index 16be5f2..2a547ec 100644
--- a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
@@ -102,13 +102,13 @@
}
void registerTypeLiteral(DartType type) {
- if (type.isInterfaceType) {
+ if (type is InterfaceType) {
// TODO(sra): If we had a flow query from the type literal expression to
// the Type argument of the metadata lookup, we could tell if this type
// literal is really a demand for the metadata.
InterfaceType interfaceType = type;
join.selectedClasses.add(interfaceType.element);
- } else if (type.isTypeVariable) {
+ } else if (type is TypeVariableType) {
// This is a type parameter of a parameterized class.
// TODO(sra): Is there a way to determine which types are bound to the
// parameter?
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index aa2c328..766013e 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
import '../common.dart';
import '../constants/values.dart';
@@ -56,7 +57,8 @@
FieldEntity fieldElement = _elementMap.getField(field);
ir.Expression expression = field.initializer;
- ConstantValue value = _elementMap.getConstantValue(expression,
+ ConstantValue value = _elementMap.getConstantValue(
+ _elementMap.getStaticTypeContext(fieldElement), expression,
requireConstant: false, implicitNull: true);
if (value != null && value.isConstant) {
fieldData[fieldElement] = new AllocatorData(value);
@@ -65,6 +67,8 @@
for (ir.Constructor constructor in classNode.constructors) {
KConstructor constructorElement = _elementMap.getConstructor(constructor);
+ ir.StaticTypeContext staticTypeContext =
+ _elementMap.getStaticTypeContext(constructorElement);
constructors.add(constructorElement);
for (ir.Initializer initializer in constructor.initializers) {
if (initializer is ir.FieldInitializer) {
@@ -79,7 +83,8 @@
Initializer initializerValue = const Initializer.complex();
ir.Expression value = initializer.value;
- ConstantValue constantValue = _elementMap.getConstantValue(value,
+ ConstantValue constantValue = _elementMap.getConstantValue(
+ staticTypeContext, value,
requireConstant: false, implicitNull: true);
if (constantValue != null && constantValue.isConstant) {
initializerValue = new Initializer.direct(constantValue);
@@ -90,9 +95,8 @@
if (position != -1) {
if (position >= constructor.function.requiredParameterCount) {
constantValue = _elementMap.getConstantValue(
- parameter.initializer,
- requireConstant: false,
- implicitNull: true);
+ staticTypeContext, parameter.initializer,
+ requireConstant: false, implicitNull: true);
if (constantValue != null && constantValue.isConstant) {
initializerValue =
new Initializer.positional(position, constantValue);
@@ -103,9 +107,8 @@
constructor.function.namedParameters.indexOf(parameter);
if (position != -1) {
constantValue = _elementMap.getConstantValue(
- parameter.initializer,
- requireConstant: false,
- implicitNull: true);
+ staticTypeContext, parameter.initializer,
+ requireConstant: false, implicitNull: true);
if (constantValue != null && constantValue.isConstant) {
initializerValue =
new Initializer.named(parameter.name, constantValue);
@@ -123,7 +126,8 @@
void registerStaticField(KField field, InitializerComplexity complexity) {
ir.Field node = _elementMap.getMemberNode(field);
ir.Expression expression = node.initializer;
- ConstantValue value = _elementMap.getConstantValue(expression,
+ ConstantValue value = _elementMap.getConstantValue(
+ _elementMap.getStaticTypeContext(field), expression,
requireConstant: node.isConst, implicitNull: true);
if (value != null && !value.isConstant) {
value = null;
diff --git a/pkg/compiler/lib/src/js_backend/frequency_assignment.dart b/pkg/compiler/lib/src/js_backend/frequency_assignment.dart
new file mode 100644
index 0000000..b19015e
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/frequency_assignment.dart
@@ -0,0 +1,216 @@
+// Copyright (c) 2019, 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.
+
+import 'dart:collection' show SplayTreeMap;
+
+/// Assigns names from [nameSequence] to items using a naive algorithm.
+///
+/// Items are assigned the next available name in decreasing frequency
+/// order. This allocation order is unstable in that small changes in the input
+/// cause large changes in the output. To see this, consider a typical
+/// distribution that has a 'tail' where large numbers of items occur two or
+/// three times. If the small change causes one of the items that occurs twice
+/// to occur four times, of then all the items that occur three times will be
+/// assigned names that are 'shifted down' in the allocation order, as will many
+/// of the items that occur twice.
+///
+/// See [semistableFrequencyAssignment] for meaning of parameters.
+void naiveFrequencyAssignment(
+ int items,
+ Iterable<String> nameSequence,
+ int Function(int) hashOf,
+ int Function(int) countOf,
+ void Function(int, String) assign) {
+ Iterator<String> nameIterator = nameSequence.iterator..moveNext();
+
+ for (int item = 0; item < items; item++) {
+ assign(item, nameIterator.current);
+ nameIterator.moveNext();
+ }
+}
+
+/// Assigns names from [nameSequence] to items, trying to avoid the unstable
+/// allocation of [naiveFrequencyAssignment] by assigning items to their
+/// hashing-based 'preferred' slots if possible.
+///
+/// - [items]: number of items to be assigned names. Items are numbered from
+/// zero. Items must be sorted in order of decreasing [countOf].
+///
+/// - [nameSequence]: Potentially unbounded sequence of valid names in
+/// increasing size.
+///
+/// - [hashOf]: Function returning a stable hash code for item `i`.
+///
+/// - [countOf]: Function returning the frequency or number of occurences of
+/// item `i`.
+///
+/// - [assign]: Function to register the assignment of a name to item `i`.
+void semistableFrequencyAssignment(
+ int items,
+ Iterable<String> nameSequence,
+ int Function(int) hashOf,
+ int Function(int) countOf,
+ void Function(int, String) assign) {
+ // Overallocate 3x the number of names so that the last pool is large enough
+ // to substantially reduce collisions. Round up to the next power of two so
+ // that slightly changing the number of items does not usually change the size
+ // of the largest pool.
+ int maxIndex = 1 << (items * 3).bitLength;
+ List<String> names = nameSequence.take(maxIndex).toList(growable: false);
+ List<_Pool> pools = _Pool.makePools(names);
+
+ // First cohort with unassigned items.
+ _Cohort firstCohort = _Cohort.makeCohorts(items, countOf);
+
+ for (var pool in pools) {
+ // Completely allocate smaller pools before allocating larger
+ // pools. Completely allocate each cohort in turn.
+
+ // TODO(sra): If the next several cohorts all fit in the current pool, the
+ // allocation will not change the bytes saved by minification. Consider
+ // allocating the preferred slot from several cohorts before allocating a
+ // non-preferred slot. This should increase the number of items allocated to
+ // their preferred slot.
+ firstCohort = firstCohort?.skipEmpty();
+ for (var startCohort = firstCohort;
+ startCohort != null;
+ startCohort = startCohort.next) {
+ if (pool.remaining == 0) break;
+
+ // Pass 1: assign members of cohort their preferred slot if available.
+ List<int> assigned = [];
+ for (var item in startCohort.unassigned) {
+ if (pool.remaining == 0) break;
+ int hash = hashOf(item);
+ int slot = hash % pool.size;
+ if (pool.slotIsAvailable(slot)) {
+ assign(item, pool.allocate(slot));
+ assigned.add(item);
+ }
+ }
+ startCohort.unassigned.removeAll(assigned);
+ // Pass 2: assign members of cohort their second 'rehash' slot if
+ // available, or the next available slot.
+ assigned.clear();
+ for (var item in startCohort.unassigned) {
+ if (pool.remaining == 0) break;
+ int hash = hashOf(item);
+ int rehashSlot = (5 * hash + 7) % pool.size;
+ int slot = pool.firstAvailableSlotFrom(rehashSlot);
+ assign(item, pool.allocate(slot));
+ assigned.add(item);
+ }
+ startCohort.unassigned.removeAll(assigned);
+ }
+ }
+
+ // Perform naive assignment of any items left unassigned above (should be
+ // none).
+ for (var pool in pools) {
+ while (pool.remaining > 0) {
+ firstCohort = firstCohort?.skipEmpty();
+ if (firstCohort == null) break;
+
+ var item = firstCohort.unassigned.first;
+ String name = pool.allocate(pool.firstAvailableSlot());
+ assign(item, name);
+ firstCohort.unassigned.remove(item);
+ }
+ }
+}
+
+/// A [_Pool] is a set of identifiers of the same length from which names are
+/// allocated.
+class _Pool {
+ final List<String /*?*/ > _names = [];
+
+ // Keep the unused (available) slots in an ordered set for efficiently finding
+ // the next available slot (i.e. linear rehash). We are concerned about
+ // efficiency because the smaller pools are completely allocated, making
+ // worst-case linear rehashing quadratic. Using an ordered map brings this
+ // down to O(N log N).
+ //
+ // We would prefer an ordered Set, but SplayTreeSet does not have methods to
+ // find keys adjacent to a query key.
+ final SplayTreeMap<int, bool> _availableSlots = SplayTreeMap();
+
+ static List<_Pool> makePools(Iterable<String> names) {
+ List<_Pool> pools = [];
+ for (var name in names) {
+ int length = name.length;
+ while (pools.length < length) pools.add(_Pool());
+ _Pool pool = pools[length - 1];
+ pool._availableSlots[pool._names.length] = true;
+ pool._names.add(name);
+ }
+ return pools;
+ }
+
+ int get size => _names.length;
+ int get remaining => _availableSlots.length;
+
+ bool slotIsAvailable(int slot) => _names[slot] != null;
+
+ int firstAvailableSlot() => _availableSlots.keys.first;
+
+ /// Returns [start] if slot [start] is free, otherwise returns the next
+ /// available slot.
+ int firstAvailableSlotFrom(int start) =>
+ _availableSlots.firstKeyAfter(start - 1) ??
+ _availableSlots.firstKeyAfter(-1) ??
+ (throw StateError('No entries left in pool'));
+
+ String allocate(int slot) {
+ String name = _names[slot];
+ assert(name != null);
+ _names[slot] = null;
+ _availableSlots.remove(slot);
+ return name;
+ }
+
+ @override
+ String toString() => '_Pool(${_names.length}, ${_availableSlots.length})';
+}
+
+/// A [_Cohort] is a set of entities which occur with the same frequency. The
+/// entities are identified by integers.
+class _Cohort {
+ _Cohort next; // Next cohort in decreasing frequency.
+ final int count; // This is the cohort of items occuring [count] times.
+ Set<int> unassigned = Set();
+
+ _Cohort(this.count);
+
+ _Cohort skipEmpty() {
+ _Cohort cohort = this;
+ while (cohort != null && cohort.remaining == 0) cohort = cohort.next;
+ return cohort;
+ }
+
+ int get remaining => unassigned.length;
+
+ static _Cohort makeCohorts(int items, int Function(int) countOf) {
+ // Build _Cohorts.
+ _Cohort first, current;
+ int lastCount = -1;
+ for (int item = 0; item < items; item++) {
+ int count = countOf(item);
+ if (count != lastCount) {
+ lastCount = count;
+ _Cohort next = _Cohort(count);
+ if (current == null) {
+ first = next;
+ } else {
+ current.next = next;
+ }
+ current = next;
+ }
+ current.unassigned.add(item);
+ }
+ return first;
+ }
+
+ @override
+ String toString() => '_Cohort($count, $remaining)';
+}
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index 7c2177a..3e0b432 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -185,7 +185,7 @@
break;
case TypeUseKind.TYPE_LITERAL:
_customElementsResolutionAnalysis.registerTypeLiteral(type);
- if (type.isTypeVariable) {
+ if (type is TypeVariableType) {
TypeVariableType typeVariable = type;
Entity typeDeclaration = typeVariable.element.typeDeclaration;
if (typeDeclaration is ClassEntity) {
@@ -332,9 +332,11 @@
type = _elementEnvironment.getUnaliasedType(type);
registerImpact(_impacts.typeCheck);
- if (!type.treatAsRaw || type.containsTypeVariables || type.isFunctionType) {
+ if (!type.treatAsRaw ||
+ type.containsTypeVariables ||
+ type is FunctionType) {
registerImpact(_impacts.genericTypeCheck);
- if (type.isTypeVariable) {
+ if (type is TypeVariableType) {
registerImpact(_impacts.typeVariableTypeCheck);
}
}
@@ -353,7 +355,6 @@
class CodegenImpactTransformer {
final JClosedWorld _closedWorld;
final ElementEnvironment _elementEnvironment;
- final CommonElements _commonElements;
final BackendImpacts _impacts;
final NativeData _nativeData;
final BackendUsage _backendUsage;
@@ -367,7 +368,6 @@
CodegenImpactTransformer(
this._closedWorld,
this._elementEnvironment,
- this._commonElements,
this._impacts,
this._nativeData,
this._backendUsage,
@@ -379,8 +379,8 @@
this._nativeEmitter);
void onIsCheckForCodegen(DartType type, TransformedWorldImpact transformed) {
- if (type.isDynamic) return;
- if (type.isVoid) return;
+ if (type is DynamicType) return;
+ if (type is VoidType) return;
type = type.unaliased;
_impacts.typeCheck.registerImpact(transformed, _elementEnvironment);
diff --git a/pkg/compiler/lib/src/js_backend/interceptor_data.dart b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
index db85765..867c379 100644
--- a/pkg/compiler/lib/src/js_backend/interceptor_data.dart
+++ b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
@@ -278,7 +278,7 @@
// is mixed-in or in an implements clause.
if (!type.treatAsRaw) return false;
- if (type.isFutureOr) return false;
+ if (type is FutureOrType) return false;
InterfaceType interfaceType = type;
ClassEntity classElement = interfaceType.element;
if (isInterceptedClass(classElement)) return false;
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index fd7df4d..aaabd51 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -1513,7 +1513,7 @@
@override
jsAst.Name operatorIsType(DartType type) {
- if (type.isFunctionType) {
+ if (type is FunctionType) {
// TODO(erikcorry): Reduce from $isx to ix when we are minifying.
return new CompoundName([
new StringBackedName(fixedNames.operatorIsPrefix),
@@ -1617,7 +1617,7 @@
}
String getTypeRepresentationForTypeConstant(DartType type) {
- if (type.isDynamic) return "dynamic";
+ if (type is DynamicType) return "dynamic";
if (type is TypedefType) {
return uniqueNameForTypeConstantElement(
type.element.library, type.element);
@@ -2178,11 +2178,11 @@
}
bool _isSimpleFunctionType(FunctionType type) {
- if (!type.returnType.isDynamic) return false;
+ if (type.returnType is! DynamicType) return false;
if (!type.optionalParameterTypes.isEmpty) return false;
if (!type.namedParameterTypes.isEmpty) return false;
for (DartType parameter in type.parameterTypes) {
- if (!parameter.isDynamic) return false;
+ if (parameter is! DynamicType) return false;
}
return true;
}
diff --git a/pkg/compiler/lib/src/js_backend/resolution_listener.dart b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
index c781753..9d16126 100644
--- a/pkg/compiler/lib/src/js_backend/resolution_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
@@ -270,7 +270,7 @@
..addAll(functionType.optionalParameterTypes)
..addAll(functionType.namedParameterTypes);
for (var type in allParameterTypes) {
- if (type.isFunctionType || type.isTypedef) {
+ if (type is FunctionType || type is TypedefType) {
var closureConverter = _commonElements.closureConverter;
worldImpact.registerStaticUse(
new StaticUse.implicitInvoke(closureConverter));
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index b486e74..319ab0c 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -1023,6 +1023,22 @@
}
@override
+ jsAst.Expression visitLegacyType(LegacyType type, ModularEmitter emitter) {
+ throw UnsupportedError('Legacy RTI does not support legacy types');
+ }
+
+ @override
+ jsAst.Expression visitNullableType(
+ NullableType type, ModularEmitter emitter) {
+ throw UnsupportedError('Legacy RTI does not support nullable types');
+ }
+
+ @override
+ jsAst.Expression visitNeverType(NeverType type, ModularEmitter emitter) {
+ throw UnsupportedError('Legacy RTI does not support the Never type');
+ }
+
+ @override
jsAst.Expression visitFunctionTypeVariable(
FunctionTypeVariable type, ModularEmitter emitter) {
int position = functionTypeVariables.indexOf(type);
@@ -1290,81 +1306,53 @@
}
}
-class ArgumentCollector extends DartTypeVisitor<dynamic, bool> {
+class ArgumentCollector extends DartTypeVisitor<void, void> {
final Set<ClassEntity> classes = new Set<ClassEntity>();
void addClass(ClassEntity cls) {
classes.add(cls);
}
- collect(DartType type, {bool isTypeArgument: false}) {
- visit(type, isTypeArgument);
+ void collect(DartType type) {
+ visit(type, null);
}
/// Collect all types in the list as if they were arguments of an
/// InterfaceType.
- collectAll(List<DartType> types, {bool isTypeArgument: false}) {
- for (DartType type in types) {
- visit(type, true);
- }
+ void collectAll(List<DartType> types) => types.forEach(collect);
+
+ @override
+ void visitLegacyType(LegacyType type, _) {
+ collect(type.baseType);
}
@override
- visitTypedefType(TypedefType type, bool isTypeArgument) {
- collect(type.unaliased, isTypeArgument: isTypeArgument);
+ void visitNullableType(NullableType type, _) {
+ collect(type.baseType);
}
@override
- visitInterfaceType(InterfaceType type, bool isTypeArgument) {
- if (isTypeArgument) addClass(type.element);
- collectAll(type.typeArguments, isTypeArgument: true);
+ void visitFutureOrType(FutureOrType type, _) {
+ collect(type.typeArgument);
}
@override
- visitFunctionType(FunctionType type, _) {
- collect(type.returnType, isTypeArgument: true);
- collectAll(type.parameterTypes, isTypeArgument: true);
- collectAll(type.optionalParameterTypes, isTypeArgument: true);
- collectAll(type.namedParameterTypes, isTypeArgument: true);
- }
-}
-
-class FunctionArgumentCollector extends DartTypeVisitor<dynamic, bool> {
- final Set<ClassEntity> classes = new Set<ClassEntity>();
-
- FunctionArgumentCollector();
-
- collect(DartType type, {bool inFunctionType: false}) {
- visit(type, inFunctionType);
- }
-
- collectAll(Iterable<DartType> types, {bool inFunctionType: false}) {
- for (DartType type in types) {
- visit(type, inFunctionType);
- }
+ void visitTypedefType(TypedefType type, _) {
+ collect(type.unaliased);
}
@override
- visitTypedefType(TypedefType type, bool inFunctionType) {
- collect(type.unaliased, inFunctionType: inFunctionType);
+ void visitInterfaceType(InterfaceType type, _) {
+ addClass(type.element);
+ collectAll(type.typeArguments);
}
@override
- visitInterfaceType(InterfaceType type, bool inFunctionType) {
- if (inFunctionType) {
- classes.add(type.element);
- }
- collectAll(type.typeArguments, inFunctionType: inFunctionType);
- }
-
- @override
- visitFunctionType(FunctionType type, _) {
- collect(type.returnType, inFunctionType: true);
- collectAll(type.parameterTypes, inFunctionType: true);
- collectAll(type.optionalParameterTypes, inFunctionType: true);
- collectAll(type.namedParameterTypes, inFunctionType: true);
- collectAll(type.typeVariables.map((type) => type.bound),
- inFunctionType: true);
+ void visitFunctionType(FunctionType type, _) {
+ collect(type.returnType);
+ collectAll(type.parameterTypes);
+ collectAll(type.optionalParameterTypes);
+ collectAll(type.namedParameterTypes);
}
}
@@ -1387,7 +1375,8 @@
TypeVisitor({this.onClass, this.onTypeVariable, this.onFunctionType});
- visitType(DartType type, TypeVisitorState state) => type.accept(this, state);
+ void visitType(DartType type, TypeVisitorState state) =>
+ type.accept(this, state);
TypeVisitorState covariantArgument(TypeVisitorState state) {
switch (state) {
@@ -1417,13 +1406,25 @@
throw new UnsupportedError("Unexpected TypeVisitorState $state");
}
- visitTypes(List<DartType> types, TypeVisitorState state) {
+ void visitTypes(List<DartType> types, TypeVisitorState state) {
for (DartType type in types) {
visitType(type, state);
}
}
@override
+ void visitLegacyType(LegacyType type, TypeVisitorState state) =>
+ visitType(type.baseType, state);
+
+ @override
+ void visitNullableType(NullableType type, TypeVisitorState state) =>
+ visitType(type.baseType, state);
+
+ @override
+ void visitFutureOrType(FutureOrType type, TypeVisitorState state) =>
+ visitType(type.typeArgument, state);
+
+ @override
void visitTypeVariableType(TypeVariableType type, TypeVisitorState state) {
if (onTypeVariable != null) {
onTypeVariable(type.element, state: state);
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
index 92a3b0a..53f2004 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_new.dart
@@ -226,6 +226,23 @@
void visit(DartType type, _) => type.accept(this, _);
@override
+ void visitLegacyType(LegacyType type, _) {
+ visit(type.baseType, _);
+ _emitCode(Recipe.wrapStar);
+ }
+
+ @override
+ void visitNullableType(NullableType type, _) {
+ visit(type.baseType, _);
+ _emitCode(Recipe.wrapQuestion);
+ }
+
+ @override
+ void visitNeverType(NeverType type, _) {
+ _emitExtensionOp(Recipe.pushNeverExtension);
+ }
+
+ @override
void visitTypeVariableType(TypeVariableType type, _) {
TypeEnvironmentStructure environment = _environment;
if (environment is SingletonTypeEnvironmentStructure) {
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
index 9c9fd78..a303026 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -1055,7 +1055,7 @@
void processChecks(Set<DartType> checks) {
checks.forEach((DartType type) {
- if (type.isInterfaceType) {
+ if (type is InterfaceType) {
InterfaceType itf = type;
if (!itf.treatAsRaw) {
potentiallyNeedTypeArguments(itf.element);
@@ -1067,7 +1067,7 @@
Entity typeDeclaration = typeVariable.element.typeDeclaration;
potentiallyNeedTypeArguments(typeDeclaration);
});
- if (type.isFunctionType) {
+ if (type is FunctionType) {
checkClosures(potentialSubtypeOf: type);
}
if (type is FutureOrType) {
@@ -1100,8 +1100,8 @@
void checkFunction(Entity function, FunctionType type) {
for (FunctionTypeVariable typeVariable in type.typeVariables) {
DartType bound = typeVariable.bound;
- if (!bound.isDynamic &&
- !bound.isVoid &&
+ if (bound is! DynamicType &&
+ bound is! VoidType &&
bound != closedWorld.commonElements.objectType) {
potentiallyNeedTypeArguments(function);
break;
diff --git a/pkg/compiler/lib/src/js_backend/type_reference.dart b/pkg/compiler/lib/src/js_backend/type_reference.dart
index 068fe60..e6be8f9 100644
--- a/pkg/compiler/lib/src/js_backend/type_reference.dart
+++ b/pkg/compiler/lib/src/js_backend/type_reference.dart
@@ -76,8 +76,16 @@
FullTypeEnvironmentRecipe;
import '../serialization/serialization.dart';
import '../util/util.dart' show Hashing;
+import 'frequency_assignment.dart';
import 'runtime_types_new.dart' show RecipeEncoder;
+/// Run the minifier for 'type$' property names even in non-minified mode,
+/// making a name from minified name and the readable name. Usage:
+///
+/// DART_VM_OPTIONS='-DDebugMinifyTypesHolder=true' dart2js ...
+///
+const _debugMinify = bool.fromEnvironment('DebugMinifyTypesHolder');
+
/// A [TypeReference] is a deferred JavaScript expression that refers to the
/// runtime representation of a ground type or ground type environment. The
/// deferred expression is filled in by the TypeReferenceFinalizer which is
@@ -386,7 +394,7 @@
referencesInTable.add(referenceSet);
}
- if (!_minify) {
+ if (!_minify && !_debugMinify) {
// For unminified code, use the characteristic names as property names.
// TODO(sra): Some of these names are long. We could truncate the names
// after the unique prefix.
@@ -410,15 +418,20 @@
referenceSet.hash = _hashCharacteristicString(referenceSet.name);
}
- Iterator<String> names = minifiedNameSequence().iterator..moveNext();
-
- // TODO(sra): It is highly unstable to allocate names in frequency
- // order. Use a more stable frequency based allocation by assigning
- // 'preferred' names.
- for (_ReferenceSet referenceSet in referencesByFrequency) {
- referenceSet.propertyName = names.current;
- names.moveNext();
+ int hashOf(int index) => referencesByFrequency[index].hash;
+ int countOf(int index) => referencesByFrequency[index].count;
+ void assign(int index, String name) {
+ if (_minify) {
+ referencesByFrequency[index].propertyName = name;
+ } else {
+ var refSet = referencesByFrequency[index];
+ refSet.propertyName = name + '_' + refSet.name;
+ }
}
+
+ //naiveFrequencyAssignment(
+ semistableFrequencyAssignment(referencesByFrequency.length,
+ minifiedNameSequence(), hashOf, countOf, assign);
}
static int _hashCharacteristicString(String s) {
@@ -607,6 +620,23 @@
}
@override
+ void visitLegacyType(covariant LegacyType type, _) {
+ _add('legacy');
+ _visit(type.baseType, type);
+ }
+
+ @override
+ void visitNullableType(covariant NullableType type, _) {
+ _add('nullable');
+ _visit(type.baseType, type);
+ }
+
+ @override
+ void visitNeverType(covariant NeverType type, _) {
+ _add('Never');
+ }
+
+ @override
void visitVoidType(covariant VoidType type, _) {
_add('void');
}
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index f1200d2..7648503 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -212,21 +212,29 @@
}
@override
- int visitVoidType(covariant VoidType type, _) => 6;
- @override
- int visitTypeVariableType(covariant TypeVariableType type, _) => 3;
- @override
int visitFunctionType(covariant FunctionType type, _) => 0;
@override
int visitInterfaceType(covariant InterfaceType type, _) => 1;
@override
int visitTypedefType(covariant TypedefType type, _) => 2;
@override
+ int visitTypeVariableType(covariant TypeVariableType type, _) => 3;
+ @override
+ int visitNeverType(covariant NeverType type, _) => 4;
+ @override
int visitDynamicType(covariant DynamicType type, _) => 5;
@override
+ int visitVoidType(covariant VoidType type, _) => 6;
+ @override
int visitAnyType(covariant AnyType type, _) => 7;
@override
int visitErasedType(covariant ErasedType type, _) => 8;
+ @override
+ int visitLegacyType(covariant LegacyType type, _) => 9;
+ @override
+ int visitNullableType(covariant NullableType type, _) => 10;
+ @override
+ int visitFutureOrType(covariant FutureOrType type, _) => 11;
}
class _DartTypeOrdering extends DartTypeVisitor<int, DartType> {
@@ -246,6 +254,25 @@
}
@override
+ int visitLegacyType(covariant LegacyType type, covariant LegacyType other) =>
+ compare(type.baseType, other.baseType);
+
+ @override
+ int visitNullableType(
+ covariant NullableType type, covariant NullableType other) =>
+ visit(type.baseType, other.baseType);
+
+ @override
+ int visitFutureOrType(
+ covariant FutureOrType type, covariant FutureOrType other) =>
+ visit(type.typeArgument, other.typeArgument);
+
+ @override
+ int visitNeverType(covariant NeverType type, covariant NeverType other) {
+ throw UnsupportedError('Unreachable');
+ }
+
+ @override
int visitVoidType(covariant VoidType type, covariant VoidType other) {
throw new UnsupportedError('Unreachable');
}
diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
index 7be3f0d..c520f5c 100644
--- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
@@ -268,7 +268,7 @@
for (jsAst.Parameter stubParameter in stubParameters) {
if (stubParameter.name == name) {
type = type.unaliased;
- if (type.isFunctionType) {
+ if (type is FunctionType) {
closureConverter ??= _emitterTask.emitter
.staticFunctionAccess(_commonElements.closureConverter);
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index 7b49849f..3105010 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -9,13 +9,10 @@
///
/// The code for the containing (used) methods must exist in the `universe`.
class Collector {
- final CompilerOptions _options;
final JCommonElements _commonElements;
final JElementEnvironment _elementEnvironment;
final OutputUnitData _outputUnitData;
final CodegenWorld _codegenWorld;
- // TODO(floitsch): the code-emitter task should not need a namer.
- final Namer _namer;
final Emitter _emitter;
final NativeData _nativeData;
final InterceptorData _interceptorData;
@@ -47,12 +44,10 @@
final List<ClassEntity> nativeClassesAndSubclasses = <ClassEntity>[];
Collector(
- this._options,
this._commonElements,
this._elementEnvironment,
this._outputUnitData,
this._codegenWorld,
- this._namer,
this._emitter,
this._nativeData,
this._interceptorData,
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
index 83a7d37..f753208 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/field_visitor.dart
@@ -24,7 +24,6 @@
bool needsGetter, bool needsSetter, bool needsCheckedSetter);
class FieldVisitor {
- final CompilerOptions _options;
final JElementEnvironment _elementEnvironment;
final JCommonElements _commonElements;
final CodegenWorld _codegenWorld;
@@ -32,7 +31,7 @@
final Namer _namer;
final JClosedWorld _closedWorld;
- FieldVisitor(this._options, this._elementEnvironment, this._commonElements,
+ FieldVisitor(this._elementEnvironment, this._commonElements,
this._codegenWorld, this._nativeData, this._namer, this._closedWorld);
/// Invokes [f] for each of the fields of [element].
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index cfd16dc..ebb4796 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -137,12 +137,10 @@
this._rtiNeededClasses,
this._mainFunction)
: this.collector = new Collector(
- _options,
_commonElements,
_elementEnvironment,
_outputUnitData,
_codegenWorld,
- _namer,
_task.emitter,
_nativeData,
_interceptorData,
@@ -1173,7 +1171,7 @@
fieldData.isElided));
}
- FieldVisitor visitor = new FieldVisitor(_options, _elementEnvironment,
+ FieldVisitor visitor = new FieldVisitor(_elementEnvironment,
_commonElements, _codegenWorld, _nativeData, _namer, _closedWorld);
visitor.visitFields(visitField,
visitStatics: visitStatics, library: library, cls: cls);
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index fcc0a7e..7365429 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -240,7 +240,7 @@
return new jsAst.VariableUse(_getVariableName(variable.element.name));
}
- if (substitution.arguments.every((DartType type) => type.isDynamic)) {
+ if (substitution.arguments.every((DartType type) => type is DynamicType)) {
return emitter.generateFunctionThatReturnsNull();
} else {
jsAst.Expression value =
@@ -323,6 +323,17 @@
}
@override
+ bool visitLegacyType(LegacyType type, OutputUnit argument) =>
+ visit(type.baseType, argument);
+
+ @override
+ bool visitNullableType(NullableType type, OutputUnit argument) =>
+ visit(type.baseType, argument);
+
+ @override
+ bool visitNeverType(NeverType type, OutputUnit argument) => true;
+
+ @override
bool visitFutureOrType(FutureOrType type, OutputUnit argument) {
if (_outputUnitData.outputUnitForClass(_commonElements.functionClass) !=
argument) {
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 61bb3c7..df0534f 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -1160,7 +1160,8 @@
ir.TreeNode sourceNode = definition.node;
ir.DartType type;
if (sourceNode is ir.Class) {
- type = sourceNode.thisType;
+ type = sourceNode.getThisType(
+ elementMap.coreTypes, sourceNode.enclosingLibrary.nonNullable);
} else if (sourceNode is ir.VariableDeclaration) {
type = sourceNode.type;
} else if (sourceNode is ir.Field) {
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 333b359..dad0b52 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -1202,6 +1202,7 @@
return data.imports[node];
}
+ @override
ir.CoreTypes get coreTypes =>
_coreTypes ??= ir.CoreTypes(programEnv.mainComponent);
@@ -1211,17 +1212,22 @@
ir.ClassHierarchy get classHierarchy =>
_classHierarchy ??= ir.ClassHierarchy(programEnv.mainComponent);
+ ir.StaticTypeContext getStaticTypeContext(ir.Member node) {
+ // TODO(johnniwinther): Cache the static type context.
+ return new ir.StaticTypeContext(node, typeEnvironment);
+ }
+
@override
StaticTypeProvider getStaticTypeProvider(MemberEntity member) {
MemberDefinition memberDefinition = members.getData(member).definition;
StaticTypeCache cachedStaticTypes;
- ir.InterfaceType thisType;
+ ir.StaticTypeContext staticTypeContext;
switch (memberDefinition.kind) {
case MemberKind.regular:
case MemberKind.constructor:
case MemberKind.constructorBody:
ir.Member node = memberDefinition.node;
- thisType = node.enclosingClass?.thisType;
+ staticTypeContext = getStaticTypeContext(node);
cachedStaticTypes = members.getData(member).staticTypes;
break;
case MemberKind.closureCall:
@@ -1229,7 +1235,7 @@
while (node != null) {
if (node is ir.Member) {
ir.Member member = node;
- thisType = member.enclosingClass?.thisType;
+ staticTypeContext = getStaticTypeContext(member);
cachedStaticTypes = members.getData(getMember(member)).staticTypes;
break;
}
@@ -1240,12 +1246,26 @@
case MemberKind.signature:
case MemberKind.generatorBody:
cachedStaticTypes = const StaticTypeCache();
+ ir.TreeNode node = memberDefinition.node;
+ while (node != null) {
+ if (node is ir.Member) {
+ ir.Member member = node;
+ staticTypeContext = getStaticTypeContext(member);
+ break;
+ } else if (node is ir.Library) {
+ // Closure field may use class nodes or type parameter nodes as
+ // the definition node.
+ staticTypeContext =
+ new ir.StaticTypeContext.forAnnotations(node, typeEnvironment);
+ }
+ node = node.parent;
+ }
break;
}
-
assert(cachedStaticTypes != null, "No static types cached for $member.");
- return new CachedStaticType(typeEnvironment, cachedStaticTypes,
- new ThisInterfaceType.from(thisType));
+ assert(staticTypeContext != null, "No static types context for $member.");
+ return new CachedStaticType(staticTypeContext, cachedStaticTypes,
+ new ThisInterfaceType.from(staticTypeContext.thisType));
}
@override
@@ -2784,9 +2804,7 @@
class ClosedEntityWriter extends EntityWriter {
final int _earlyMemberIndexLimit;
- final JsKernelToElementMap _elementMap;
-
- ClosedEntityWriter(this._elementMap, this._earlyMemberIndexLimit);
+ ClosedEntityWriter(this._earlyMemberIndexLimit);
@override
void writeMemberToDataSink(DataSink sink, IndexedMember value) {
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 339c61f..822be8c 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -312,7 +312,6 @@
_codegenImpactTransformer = new CodegenImpactTransformer(
closedWorld,
closedWorld.elementEnvironment,
- closedWorld.commonElements,
impacts,
closedWorld.nativeData,
closedWorld.backendUsage,
@@ -413,7 +412,7 @@
EntityWriter forEachCodegenMember(void Function(MemberEntity member) f) {
int earlyMemberIndexLimit = _elementMap.prepareForCodegenSerialization();
ClosedEntityWriter entityWriter =
- new ClosedEntityWriter(_elementMap, earlyMemberIndexLimit);
+ new ClosedEntityWriter(earlyMemberIndexLimit);
for (int memberIndex = 0;
memberIndex < _elementMap.members.length;
memberIndex++) {
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index fd739cc..6308055 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -760,6 +760,18 @@
}
@override
+ DartType visitLegacyType(LegacyType type, _EntityConverter converter) =>
+ LegacyType(visit(type.baseType, converter));
+
+ @override
+ DartType visitNullableType(NullableType type, _EntityConverter converter) =>
+ NullableType(visit(type.baseType, converter));
+
+ @override
+ DartType visitNeverType(NeverType type, _EntityConverter converter) =>
+ NeverType();
+
+ @override
DartType visitDynamicType(DynamicType type, _EntityConverter converter) {
return DynamicType();
}
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index 48f1dcb..02c3047 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -53,6 +53,11 @@
@override
bool get enableNoSuchMethodForwarders => true;
+ // TODO(johnniwinther): Change this to `false` when late field lowering is
+ // ready.
+ @override
+ bool get supportsLateFields => true;
+
@override
List<String> get extraRequiredLibraries => _requiredLibraries[name];
diff --git a/pkg/compiler/lib/src/kernel/deferred_load.dart b/pkg/compiler/lib/src/kernel/deferred_load.dart
index 87a90be..09c383c 100644
--- a/pkg/compiler/lib/src/kernel/deferred_load.dart
+++ b/pkg/compiler/lib/src/kernel/deferred_load.dart
@@ -5,6 +5,7 @@
library kernel.deferred_load_data;
import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
import '../common_elements.dart';
import '../compiler.dart' show Compiler;
@@ -83,7 +84,8 @@
// Fetch the internal node in order to skip annotations on the member.
// TODO(sigmund): replace this pattern when the kernel-ast provides a better
// way to skip annotations (issue 31565).
- var visitor = new ConstantCollector(_elementMap, dependencies);
+ var visitor = new ConstantCollector(
+ _elementMap, _elementMap.getStaticTypeContext(element), dependencies);
if (node is ir.Field) {
node.initializer?.accept(visitor);
return;
@@ -119,14 +121,15 @@
class ConstantCollector extends ir.RecursiveVisitor {
final KernelToElementMap elementMap;
final Dependencies dependencies;
+ final ir.StaticTypeContext staticTypeContext;
- ConstantCollector(this.elementMap, this.dependencies);
+ ConstantCollector(this.elementMap, this.staticTypeContext, this.dependencies);
CommonElements get commonElements => elementMap.commonElements;
void add(ir.Expression node, {bool required: true}) {
- ConstantValue constant =
- elementMap.getConstantValue(node, requireConstant: required);
+ ConstantValue constant = elementMap
+ .getConstantValue(staticTypeContext, node, requireConstant: required);
if (constant != null) {
dependencies.addConstant(
constant, elementMap.getImport(getDeferredImport(node)));
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index f0a3770..a9ef438 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -112,7 +112,8 @@
js.Name getNameForJsGetName(ConstantValue constant, Namer namer);
/// Computes the [ConstantValue] for the constant [expression].
- ConstantValue getConstantValue(ir.Expression expression,
+ ConstantValue getConstantValue(
+ ir.StaticTypeContext staticTypeContext, ir.Expression expression,
{bool requireConstant: true, bool implicitNull: false});
/// Return the [ImportEntity] corresponding to [node].
@@ -178,6 +179,8 @@
/// Returns the defining node for [member].
ir.Member getMemberNode(covariant MemberEntity member);
+
+ ir.StaticTypeContext getStaticTypeContext(MemberEntity member);
}
/// Kinds of foreign functions.
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index cb01960..c8e869a 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -800,6 +800,12 @@
ir.ClassHierarchy get classHierarchy =>
_classHierarchy ??= ir.ClassHierarchy(env.mainComponent);
+ @override
+ ir.StaticTypeContext getStaticTypeContext(MemberEntity member) {
+ // TODO(johnniwinther): Cache the static type context.
+ return new ir.StaticTypeContext(getMemberNode(member), typeEnvironment);
+ }
+
Dart2jsConstantEvaluator get constantEvaluator {
return _constantEvaluator ??= new Dart2jsConstantEvaluator(typeEnvironment,
(ir.LocatedMessage message, List<ir.LocatedMessage> context) {
@@ -1065,13 +1071,14 @@
}
@override
- ConstantValue getConstantValue(ir.Expression node,
+ ConstantValue getConstantValue(
+ ir.StaticTypeContext staticTypeContext, ir.Expression node,
{bool requireConstant: true,
bool implicitNull: false,
bool checkCasts: true}) {
if (node is ir.ConstantExpression) {
- ir.Constant constant =
- constantEvaluator.evaluate(node, requireConstant: requireConstant);
+ ir.Constant constant = constantEvaluator.evaluate(staticTypeContext, node,
+ requireConstant: requireConstant);
if (constant == null) {
if (requireConstant) {
throw new UnsupportedError(
@@ -1111,13 +1118,15 @@
}
/// Converts [annotations] into a list of [ConstantValue]s.
- List<ConstantValue> getMetadata(List<ir.Expression> annotations) {
+ List<ConstantValue> getMetadata(
+ ir.StaticTypeContext staticTypeContext, List<ir.Expression> annotations) {
if (annotations.isEmpty) return const <ConstantValue>[];
List<ConstantValue> metadata = <ConstantValue>[];
annotations.forEach((ir.Expression node) {
// We skip the implicit cast checks for metadata to avoid circular
// dependencies in the js-interop class registration.
- metadata.add(getConstantValue(node, checkCasts: false));
+ metadata
+ .add(getConstantValue(staticTypeContext, node, checkCasts: false));
});
return metadata;
}
@@ -1417,7 +1426,14 @@
ImpactData impactData = impactBuilderData.impactData;
memberData.staticTypes = impactBuilderData.cachedStaticTypes;
KernelImpactConverter converter = new KernelImpactConverter(
- this, member, reporter, options, _constantValuefier);
+ this,
+ member,
+ reporter,
+ options,
+ _constantValuefier,
+ // TODO(johnniwinther): Pull the static type context from the cached
+ // static types.
+ new ir.StaticTypeContext(node, typeEnvironment));
return converter.convert(impactData);
} else {
KernelImpactBuilder builder = new KernelImpactBuilder(
@@ -1425,6 +1441,7 @@
member,
reporter,
options,
+ new ir.StaticTypeContext(node, typeEnvironment),
variableScopeModel,
annotations,
_constantValuefier);
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 077aa0a..6496281 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -10,6 +10,7 @@
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/clone.dart';
import 'package:kernel/type_algebra.dart';
+import 'package:kernel/type_environment.dart' as ir;
import 'package:collection/collection.dart' show mergeSort; // a stable sort.
import '../common.dart';
@@ -203,7 +204,10 @@
KLibraryData(this.library);
Iterable<ConstantValue> getMetadata(KernelToElementMapImpl elementMap) {
- return _metadata ??= elementMap.getMetadata(library.annotations);
+ return _metadata ??= elementMap.getMetadata(
+ new ir.StaticTypeContext.forAnnotations(
+ library, elementMap.typeEnvironment),
+ library.annotations);
}
Iterable<ImportEntity> getImports(KernelToElementMapImpl elementMap) {
@@ -667,7 +671,10 @@
@override
Iterable<ConstantValue> getMetadata(
covariant KernelToElementMapImpl elementMap) {
- return _metadata ??= elementMap.getMetadata(node.annotations);
+ return _metadata ??= elementMap.getMetadata(
+ new ir.StaticTypeContext.forAnnotations(
+ node.enclosingLibrary, elementMap.typeEnvironment),
+ node.annotations);
}
@override
@@ -705,7 +712,9 @@
@override
Iterable<ConstantValue> getMetadata(
covariant KernelToElementMapImpl elementMap) {
- return _metadata ??= elementMap.getMetadata(node.annotations);
+ return _metadata ??= elementMap.getMetadata(
+ new ir.StaticTypeContext(node, elementMap.typeEnvironment),
+ node.annotations);
}
@override
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index 4e4571e..ac71d58 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -55,12 +55,12 @@
this.currentMember,
this.reporter,
this._options,
+ ir.StaticTypeContext staticTypeContext,
VariableScopeModel variableScopeModel,
this._annotations,
this._constantValuefier)
: this.impactBuilder = new ResolutionWorldImpactBuilder(currentMember),
- super(elementMap.typeEnvironment, elementMap.classHierarchy,
- variableScopeModel);
+ super(staticTypeContext, elementMap.classHierarchy, variableScopeModel);
@override
CommonElements get commonElements => elementMap.commonElements;
@@ -91,9 +91,11 @@
final MemberEntity currentMember;
@override
final ConstantValuefier _constantValuefier;
+ @override
+ final ir.StaticTypeContext staticTypeContext;
KernelImpactConverter(this.elementMap, this.currentMember, this.reporter,
- this._options, this._constantValuefier)
+ this._options, this._constantValuefier, this.staticTypeContext)
: this.impactBuilder = new ResolutionWorldImpactBuilder(currentMember);
@override
@@ -125,6 +127,7 @@
CommonElements get commonElements;
NativeBasicData get _nativeBasicData;
ConstantValuefier get _constantValuefier;
+ ir.StaticTypeContext get staticTypeContext;
Object _computeReceiverConstraint(
ir.DartType receiverType, ClassRelation relation) {
@@ -142,7 +145,7 @@
@override
void registerParameterCheck(ir.DartType irType) {
DartType type = elementMap.getDartType(irType);
- if (!type.isDynamic) {
+ if (type is! DynamicType) {
impactBuilder.registerTypeUse(new TypeUse.parameterCheck(type));
}
}
@@ -355,8 +358,8 @@
assert(node.isConst);
ConstructorEntity constructor = elementMap.getConstructor(node.target);
if (commonElements.isSymbolConstructor(constructor)) {
- ConstantValue value =
- elementMap.getConstantValue(node.arguments.positional.first);
+ ConstantValue value = elementMap.getConstantValue(
+ staticTypeContext, node.arguments.positional.first);
if (!value.isString) {
// TODO(het): Get the actual span for the Symbol constructor argument
reporter.reportErrorMessage(
@@ -856,7 +859,8 @@
for (ir.SwitchCase switchCase in node.cases) {
for (ir.Expression expression in switchCase.expressions) {
- ConstantValue value = elementMap.getConstantValue(expression);
+ ConstantValue value =
+ elementMap.getConstantValue(staticTypeContext, expression);
DartType type = value.getType(elementMap.commonElements);
if (firstCaseType == null) {
firstCase = expression;
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index 80ea69f..642120d 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -5,6 +5,7 @@
library dart2js.kernel.frontend_strategy;
import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
import '../common.dart';
import '../common/backend_api.dart';
@@ -457,8 +458,10 @@
// depend on metadata, so these parts of the impact data need to be
// computed during conversion to [ResolutionImpact].
impactBuilderData = _compilerTask.measureSubtask('worldImpact', () {
- ImpactBuilder builder = new ImpactBuilder(_elementMap.typeEnvironment,
- _elementMap.classHierarchy, scopeModel.variableScopeModel,
+ ImpactBuilder builder = new ImpactBuilder(
+ new ir.StaticTypeContext(node, _elementMap.typeEnvironment),
+ _elementMap.classHierarchy,
+ scopeModel.variableScopeModel,
useAsserts: _elementMap.options.enableUserAssertions,
inferEffectivelyFinalVariableTypes:
!annotations.contains(PragmaAnnotation.disableFinal));
diff --git a/pkg/compiler/lib/src/kernel/no_such_method_resolver.dart b/pkg/compiler/lib/src/kernel/no_such_method_resolver.dart
index c57d9e1..32f6721 100644
--- a/pkg/compiler/lib/src/kernel/no_such_method_resolver.dart
+++ b/pkg/compiler/lib/src/kernel/no_such_method_resolver.dart
@@ -9,8 +9,6 @@
KernelNoSuchMethodResolver(this.elementMap);
- ElementEnvironment get _elementEnvironment => elementMap.elementEnvironment;
-
CommonElements get _commonElements => elementMap.commonElements;
@override
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index b97e294..0e2aa4b 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -815,7 +815,7 @@
}
if (!trustJSInteropTypeAnnotations ||
- type.isDynamic ||
+ type is DynamicType ||
type == commonElements.objectType) {
// By saying that only JS-interop types can be created, we prevent
// pulling in every other native type (e.g. all of dart:html) when a
@@ -882,7 +882,7 @@
_behavior.typesReturned.add(!isJsInterop || trustJSInteropTypeAnnotations
? returnType
: commonElements.dynamicType);
- if (!type.returnType.isVoid) {
+ if (type.returnType is! VoidType) {
// Declared types are nullable.
_behavior.typesReturned.add(commonElements.nullType);
}
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 766bfa0..e08baad 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -132,7 +132,7 @@
InterfaceType specType = _elementEnvironment.getRawType(type.element);
return _dartTypes.isSubtype(nativeType, specType);
}));
- } else if (type.isDynamic) {
+ } else if (type is DynamicType) {
matchingClasses.addAll(_unusedClasses);
} else {
assert(type is VoidType, '$type was ${type.runtimeType}');
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index c98787d..51cd928 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -187,6 +187,12 @@
switch (kind) {
case DartTypeKind.none:
return null;
+ case DartTypeKind.legacyType:
+ return LegacyType(_readDartType(functionTypeVariables));
+ case DartTypeKind.nullableType:
+ return NullableType(_readDartType(functionTypeVariables));
+ case DartTypeKind.neverType:
+ return NeverType();
case DartTypeKind.voidType:
return VoidType();
case DartTypeKind.typeVariable:
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 13b0a7f..8d73694 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -89,6 +89,9 @@
/// Enum used for identifying [DartType] subclasses in serialization.
enum DartTypeKind {
none,
+ legacyType,
+ nullableType,
+ neverType,
voidType,
typeVariable,
functionTypeVariable,
@@ -122,6 +125,26 @@
}
@override
+ void visitLegacyType(covariant LegacyType type,
+ List<FunctionTypeVariable> functionTypeVariables) {
+ _sink.writeEnum(DartTypeKind.legacyType);
+ _sink._writeDartType(type.baseType, functionTypeVariables);
+ }
+
+ @override
+ void visitNullableType(covariant NullableType type,
+ List<FunctionTypeVariable> functionTypeVariables) {
+ _sink.writeEnum(DartTypeKind.nullableType);
+ _sink._writeDartType(type.baseType, functionTypeVariables);
+ }
+
+ @override
+ void visitNeverType(covariant NeverType type,
+ List<FunctionTypeVariable> functionTypeVariables) {
+ _sink.writeEnum(DartTypeKind.neverType);
+ }
+
+ @override
void visitVoidType(covariant VoidType type,
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.voidType);
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 0688ba9..b696a67 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -1488,8 +1488,8 @@
_elementMap);
HInstruction newParameter = localsHandler.directLocals[local];
DartType bound = _getDartTypeIfValid(typeParameter.bound);
- if (!bound.isDynamic &&
- !bound.isVoid &&
+ if (bound is! DynamicType &&
+ bound is! VoidType &&
bound != _commonElements.objectType) {
if (options.experimentNewRti) {
_checkTypeBound(newParameter, bound, local.name);
@@ -5525,7 +5525,7 @@
/// Returns `true` if the checking of [type] is performed directly on the
/// object and not on an interceptor.
bool _hasDirectCheckFor(DartType type) {
- if (!type.isInterfaceType) return false;
+ if (type is! InterfaceType) return false;
InterfaceType interfaceType = type;
ClassEntity element = interfaceType.element;
return element == _commonElements.stringClass ||
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index ee72ee8..856e4fc 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -390,10 +390,10 @@
new SsaInstructionSelection(_options, _closedWorld, _interceptorData));
runPhase(new SsaTypeKnownRemover());
runPhase(new SsaTrustedCheckRemover(_options));
- runPhase(new SsaAssignmentChaining(_options, _closedWorld));
+ runPhase(new SsaAssignmentChaining(_closedWorld));
runPhase(new SsaInstructionMerger(_abstractValueDomain, generateAtUseSite));
runPhase(new SsaConditionMerger(generateAtUseSite, controlFlowOperators));
- runPhase(new SsaShareRegionConstants(_options));
+ runPhase(new SsaShareRegionConstants());
SsaLiveIntervalBuilder intervalBuilder =
new SsaLiveIntervalBuilder(generateAtUseSite, controlFlowOperators);
@@ -2891,7 +2891,7 @@
void checkType(HInstruction input, HInstruction interceptor, DartType type,
SourceInformation sourceInformation,
{bool negative: false}) {
- if (type.isInterfaceType) {
+ if (type is InterfaceType) {
InterfaceType interfaceType = type;
ClassEntity element = interfaceType.element;
if (element == _commonElements.jsArrayClass) {
@@ -3102,7 +3102,7 @@
_commonElements.isListSupertype(element)) {
handleListOrSupertypeCheck(input, interceptor, type, sourceInformation,
negative: negative);
- } else if (type.isFunctionType) {
+ } else if (type is FunctionType) {
checkType(input, interceptor, type, sourceInformation,
negative: negative);
} else if ((input.isPrimitive(_abstractValueDomain).isPotentiallyTrue &&
@@ -3133,10 +3133,10 @@
void visitTypeConversion(HTypeConversion node) {
assert(node.isTypeCheck || node.isCastCheck);
DartType type = node.typeExpression;
- assert(!type.isTypedef);
- assert(!type.isDynamic);
- assert(!type.isVoid);
- if (type.isFunctionType) {
+ assert(type is! TypedefType);
+ assert(type is! DynamicType);
+ assert(type is! VoidType);
+ if (type is FunctionType) {
// TODO(5022): We currently generate $isFunction checks for
// function types.
_registry
@@ -3546,7 +3546,7 @@
TypeRecipe typeExpression = node.typeExpression;
if (envStructure is FullTypeEnvironmentStructure &&
typeExpression is TypeExpressionRecipe) {
- if (typeExpression.type.isTypeVariable) {
+ if (typeExpression.type is TypeVariableType) {
TypeVariableType type = typeExpression.type;
int index = indexTypeVariable(
_closedWorld, _rtiSubstitutions, envStructure, type);
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index a3c4af4..b984e4b 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -443,10 +443,8 @@
/// b.y = a.x = v;
class SsaAssignmentChaining extends HBaseVisitor with CodegenPhase {
final JClosedWorld _closedWorld;
- final CompilerOptions _options;
- //HGraph graph;
- SsaAssignmentChaining(this._options, this._closedWorld);
+ SsaAssignmentChaining(this._closedWorld);
AbstractValueDomain get _abstractValueDomain =>
_closedWorld.abstractValueDomain;
@@ -1114,9 +1112,7 @@
/// name would be shorter than repeated references. These are caches for 'this'
/// and constant values.
class SsaShareRegionConstants extends HBaseVisitor with CodegenPhase {
- final CompilerOptions _options;
-
- SsaShareRegionConstants(this._options);
+ SsaShareRegionConstants();
@override
visitGraph(HGraph graph) {
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 90297a2..edbcb67 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -1404,16 +1404,16 @@
// Only the builder knows how to create [HTypeConversion]
// instructions with generics. It has the generic type context
// available.
- assert(!type.isTypeVariable);
- assert(type.treatAsRaw || type.isFunctionType);
- if (type.isDynamic) return this;
- if (type.isVoid) return this;
+ assert(type is! TypeVariableType);
+ assert(type.treatAsRaw || type is FunctionType);
+ if (type is DynamicType) return this;
+ if (type is VoidType) return this;
if (type == closedWorld.commonElements.objectType) return this;
- if (type.isFunctionType || type.isFutureOr) {
+ if (type is FunctionType || type is FutureOrType) {
return new HTypeConversion(type, kind,
closedWorld.abstractValueDomain.dynamicType, this, sourceInformation);
}
- assert(type.isInterfaceType);
+ assert(type is InterfaceType);
if (kind == HTypeConversion.TYPE_CHECK && !type.treatAsRaw) {
throw 'creating compound check to $type (this = ${this})';
} else {
@@ -3427,7 +3427,7 @@
// TODO(sigmund): re-add `&& typeExpression.treatAsRaw` or something
// equivalent (which started failing once we allowed typeExpressions that
// contain type parameters matching the original bounds of the type).
- assert((typeExpression.isFunctionType || typeExpression.isInterfaceType),
+ assert((typeExpression is FunctionType || typeExpression is InterfaceType),
"Unexpected raw is-test type: $typeExpression");
return new HIs.internal(typeExpression, [expression, interceptor],
RAW_CHECK, type, sourceInformation);
@@ -3554,7 +3554,7 @@
HInstruction input, SourceInformation sourceInformation)
: checkedType = type,
super(<HInstruction>[input], type) {
- assert(typeExpression == null || !typeExpression.isTypedef);
+ assert(typeExpression == null || typeExpression is! TypedefType);
this.sourceElement = input.sourceElement;
this.sourceInformation = sourceInformation;
}
@@ -3563,13 +3563,13 @@
AbstractValue type, HInstruction input, HInstruction typeRepresentation)
: checkedType = type,
super(<HInstruction>[input, typeRepresentation], type) {
- assert(!typeExpression.isTypedef);
+ assert(typeExpression is! TypedefType);
sourceElement = input.sourceElement;
}
bool get hasTypeRepresentation {
return typeExpression != null &&
- typeExpression.isInterfaceType &&
+ typeExpression is InterfaceType &&
inputs.length > 1;
}
@@ -3615,10 +3615,10 @@
AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
DartType type = typeExpression;
if (type != null) {
- if (type.isTypeVariable) {
+ if (type is TypeVariableType) {
return false;
}
- if (type.isFutureOr) {
+ if (type is FutureOrType) {
// `null` always passes type conversion.
if (checkedInput.isNull(abstractValueDomain).isDefinitelyTrue) {
return true;
@@ -3633,7 +3633,7 @@
}
return false;
}
- if (type.isFunctionType) {
+ if (type is FunctionType) {
// `null` always passes type conversion.
if (checkedInput.isNull(abstractValueDomain).isDefinitelyTrue) {
return true;
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 2f69165..8c27840 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -852,7 +852,7 @@
if (!canInline) return;
if (inputPosition >= inputs.length) return;
HInstruction input = inputs[inputPosition++];
- if (parameterType.unaliased.isFunctionType) {
+ if (parameterType.unaliased is FunctionType) {
// Must call the target since it contains a function conversion.
canInline = false;
return;
@@ -1093,11 +1093,11 @@
if (!node.isRawCheck) {
return node;
- } else if (type.isTypedef) {
+ } else if (type is TypedefType) {
return node;
- } else if (type.isFunctionType) {
+ } else if (type is FunctionType) {
return node;
- } else if (type.isFutureOr) {
+ } else if (type is FutureOrType) {
return node;
}
@@ -1174,7 +1174,7 @@
rep.kind == TypeInfoExpressionKind.COMPLETE &&
rep.inputs.isEmpty) {
DartType type = rep.dartType;
- if (type.isInterfaceType && type.treatAsRaw) {
+ if (type is InterfaceType && type.treatAsRaw) {
return node.checkedInput.convertType(_closedWorld, type, node.kind)
..sourceInformation = node.sourceInformation;
}
@@ -1427,9 +1427,9 @@
}
if (!fieldType.treatAsRaw ||
- fieldType.isTypeVariable ||
- fieldType.unaliased.isFunctionType ||
- fieldType.unaliased.isFutureOr) {
+ fieldType is TypeVariableType ||
+ fieldType.unaliased is FunctionType ||
+ fieldType.unaliased is FutureOrType) {
// We cannot generate the correct type representation here, so don't
// inline this access.
// TODO(sra): If the input is such that we don't need a type check, we
@@ -3155,9 +3155,9 @@
DartType type = instruction.typeExpression;
if (!instruction.isRawCheck) {
return;
- } else if (type.isTypedef) {
+ } else if (type is TypedefType) {
return;
- } else if (type.isFutureOr) {
+ } else if (type is FutureOrType) {
return;
}
InterfaceType interfaceType = type;
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index 0b77dbd..06429cf 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -53,8 +53,8 @@
if (type == null) return null;
type = builder.localsHandler.substInContext(type);
type = type.unaliased;
- if (type.isDynamic) return null;
- if (!type.isInterfaceType) return null;
+ if (type is DynamicType) return null;
+ if (type is! InterfaceType) return null;
if (type == _closedWorld.commonElements.objectType) return null;
// The type element is either a class or the void element.
ClassEntity element = (type as InterfaceType).element;
@@ -229,10 +229,10 @@
HInstruction buildTypeArgumentRepresentations(
DartType type, MemberEntity sourceElement,
[SourceInformation sourceInformation]) {
- assert(!type.isTypeVariable);
+ assert(type is! TypeVariableType);
// Compute the representation of the type arguments, including access
// to the runtime type information for type variables as instructions.
- assert(type.isInterfaceType);
+ assert(type is InterfaceType);
InterfaceType interface = type;
List<HInstruction> inputs = <HInstruction>[];
for (DartType argument in interface.typeArguments) {
@@ -261,7 +261,7 @@
return builder.graph.addConstantNull(_closedWorld);
}
- if (argument.isTypeVariable) {
+ if (argument is TypeVariableType) {
return addTypeVariableReference(argument, sourceElement,
sourceInformation: sourceInformation);
}
@@ -433,7 +433,7 @@
if (type == null) return original;
type = type.unaliased;
- if (type.isInterfaceType && !type.treatAsRaw) {
+ if (type is InterfaceType && !type.treatAsRaw) {
InterfaceType interfaceType = type;
AbstractValue subtype =
_abstractValueDomain.createNullableSubtype(interfaceType.element);
@@ -443,14 +443,14 @@
return new HTypeConversion.withTypeRepresentation(
type, kind, subtype, original, representations)
..sourceInformation = sourceInformation;
- } else if (type.isTypeVariable) {
+ } else if (type is TypeVariableType) {
AbstractValue subtype = original.instructionType;
HInstruction typeVariable =
addTypeVariableReference(type, builder.sourceElement);
return new HTypeConversion.withTypeRepresentation(
type, kind, subtype, original, typeVariable)
..sourceInformation = sourceInformation;
- } else if (type.isFunctionType || type.isFutureOr) {
+ } else if (type is FunctionType || type is FutureOrType) {
HInstruction reifiedType =
analyzeTypeArgument(type, builder.sourceElement);
// TypeMasks don't encode function types or FutureOr types.
@@ -473,8 +473,8 @@
if (type == null) return original;
type = type.unaliased;
- if (type.isDynamic) return original;
- if (type.isVoid) return original;
+ if (type is DynamicType) return original;
+ if (type is VoidType) return original;
if (type == _closedWorld.commonElements.objectType) return original;
HInstruction reifiedType = analyzeTypeArgumentNewRti(
diff --git a/pkg/compiler/lib/src/ssa/types.dart b/pkg/compiler/lib/src/ssa/types.dart
index 1795329..201fca6 100644
--- a/pkg/compiler/lib/src/ssa/types.dart
+++ b/pkg/compiler/lib/src/ssa/types.dart
@@ -4,6 +4,7 @@
import '../common_elements.dart' show CommonElements;
import '../elements/entities.dart';
+import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../inferrer/types.dart';
import '../native/behavior.dart';
@@ -49,9 +50,9 @@
if (type == SpecialType.JsObject) {
return abstractValueDomain
.createNonNullExact(commonElements.objectClass);
- } else if (type.isVoid) {
+ } else if (type is VoidType) {
return abstractValueDomain.nullType;
- } else if (type.isDynamic) {
+ } else if (type is DynamicType) {
return abstractValueDomain.dynamicType;
} else if (type == commonElements.nullType) {
return abstractValueDomain.nullType;
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index 64e22df..59b416e 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -808,20 +808,6 @@
_invokedSetters.forEach(f);
}
- bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
- MemberEntity member, JClosedWorld world) {
- if (selectors == null) return false;
- for (Selector selector in selectors.keys) {
- if (selector.appliesUnnamed(member)) {
- SelectorConstraints masks = selectors[selector];
- if (masks.canHit(member, selector.memberName, world)) {
- return true;
- }
- }
- }
- return false;
- }
-
@override
bool hasInvokedGetter(MemberEntity member) {
MemberUsage memberUsage = _liveMemberUsage[member];
diff --git a/pkg/dart2native/bin/dart2native.dart b/pkg/dart2native/bin/dart2native.dart
index 121aad1..826290e1 100644
--- a/pkg/dart2native/bin/dart2native.dart
+++ b/pkg/dart2native/bin/dart2native.dart
@@ -21,6 +21,8 @@
path.join(binDir, 'utils', 'gen_snapshot${executableSuffix}');
final String platformDill =
path.join(sdkDir, 'lib', '_internal', 'vm_platform_strong.dill');
+final String productPlatformDill =
+ path.join(sdkDir, 'lib', '_internal', 'vm_platform_strong_product.dill');
Future<void> generateNative(
Kind kind,
@@ -40,8 +42,21 @@
if (verbose) {
print('Generating AOT kernel dill.');
}
- final kernelResult = await generateAotKernel(dart, genKernel, platformDill,
- sourceFile, kernelFile, packages, defines);
+
+ // Prefer to use the product platform file, if available. Fall back to the
+ // normal one (this happens if `out/<build-dir>/dart-sdk` is used).
+ //
+ // Background information: For the `dart-sdk` we distribute we build release
+ // and product mode configurations. Then we have an extra bundling step
+ // which will add product-mode
+ // gen_snapshot/dartaotruntime/vm_platform_strong_product.dill to the
+ // release SDK (see tools/bots/dart_sdk.py:CopyAotBinaries)
+ final String platformFileToUse = File(productPlatformDill).existsSync()
+ ? productPlatformDill
+ : platformDill;
+
+ final kernelResult = await generateAotKernel(dart, genKernel,
+ platformFileToUse, sourceFile, kernelFile, packages, defines);
if (kernelResult.exitCode != 0) {
stderr.writeln(kernelResult.stdout);
stderr.writeln(kernelResult.stderr);
diff --git a/pkg/dartfix/CHANGELOG.md b/pkg/dartfix/CHANGELOG.md
index 3a8048b..de84535 100644
--- a/pkg/dartfix/CHANGELOG.md
+++ b/pkg/dartfix/CHANGELOG.md
@@ -1,3 +1,6 @@
+# 0.1.6
+* Improve experimental non-nullable migration support.
+
# 0.1.5
* Add command line options for selecting/excluding fixes to apply (`--fix`,
`--excludeFix`, and `--required`). Call with `--help` for more details.
diff --git a/pkg/dartfix/README.md b/pkg/dartfix/README.md
index 43ed757..245ac92 100644
--- a/pkg/dartfix/README.md
+++ b/pkg/dartfix/README.md
@@ -72,7 +72,7 @@
and star the fixes you want.
If no issue exists for the fix, [create a GitHub issue.][new issue]
-[dartfix]: https://pub.dartlang.org/packages/dartfix
+[dartfix]: https://pub.dev/packages/dartfix
[dartfmt]: https://www.dartlang.org/tools/dartfmt
[added in Dart in 2.1]: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#210---2018-11-15
[features added to Dart in 2.1]: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#210---2018-11-15
diff --git a/pkg/dartfix/pubspec.yaml b/pkg/dartfix/pubspec.yaml
index b895769..1ad071e 100644
--- a/pkg/dartfix/pubspec.yaml
+++ b/pkg/dartfix/pubspec.yaml
@@ -1,5 +1,5 @@
name: dartfix
-version: 0.1.5
+version: 0.1.6
author: Dart Team <misc@dartlang.org>
description:
A tool for migrating Dart source to newer versions of the Dart SDK
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 75ce561..d698b73 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -21,7 +21,7 @@
show DartObject, DartObjectImpl;
import 'package:analyzer/src/generated/resolver.dart'
show TypeProvider, NamespaceBuilder;
-import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
+import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/task/strong/ast_properties.dart';
import 'package:path/path.dart' as p;
@@ -74,7 +74,7 @@
final SummaryDataStore summaryData;
final CompilerOptions options;
- final Dart2TypeSystem rules;
+ final TypeSystemImpl rules;
/// Errors that were produced during compilation, if any.
final ErrorCollector errors;
@@ -196,7 +196,12 @@
CodeGenerator(LinkedAnalysisDriver driver, this.types, this.summaryData,
this.options, this._extensionTypes, this.errors)
- : rules = Dart2TypeSystem(types),
+ : rules = TypeSystemImpl(
+ implicitCasts: true,
+ isNonNullableByDefault: false,
+ strictInference: false,
+ typeProvider: types,
+ ),
declaredVariables = driver.declaredVariables,
_asyncStreamIterator = getLegacyRawClassType(
driver.getClass('dart:async', 'StreamIterator')),
@@ -4879,7 +4884,7 @@
variable ??= js_ast.TemporaryId(name);
var idElement =
- TemporaryVariableElement.forNode(id, variable, _currentElement);
+ TemporaryVariableElement(name, -1, variable, _currentElement);
id.staticElement = idElement;
id.staticType = type;
setIsDynamicInvoke(id, dynamicInvoke ?? type.isDynamic);
@@ -6687,9 +6692,9 @@
class TemporaryVariableElement extends LocalVariableElementImpl {
final js_ast.Expression jsVariable;
- TemporaryVariableElement.forNode(
- Identifier name, this.jsVariable, Element enclosingElement)
- : super.forNode(name) {
+ TemporaryVariableElement(
+ String name, int offset, this.jsVariable, Element enclosingElement)
+ : super(name, offset) {
this.enclosingElement = enclosingElement;
}
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index ee256ec..c1f9a92 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -14,7 +14,7 @@
import 'package:analyzer/src/generated/constant.dart'
show DartObject, DartObjectImpl;
import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
+import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
import 'type_utilities.dart';
@@ -48,7 +48,7 @@
/// `element.type`, but unfortunately typedef elements do not return a
/// meaningful type, so we need to work around that.
DartType instantiateElementTypeToBounds(
- Dart2TypeSystem rules, TypeDefiningElement element) {
+ TypeSystemImpl rules, TypeDefiningElement element) {
if (element is TypeParameterizedElement) {
if (element is ClassElement) {
var typeArguments = rules.instantiateTypeFormalsToBounds2(element);
diff --git a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
index c24e5f5..aa62632 100644
--- a/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/js_typerep.dart
@@ -5,14 +5,14 @@
import 'package:analyzer/dart/element/element.dart' show ClassElement;
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
+import 'package:analyzer/src/generated/type_system.dart' show TypeSystemImpl;
import '../compiler/js_typerep.dart';
import 'driver.dart';
import 'type_utilities.dart';
class JSTypeRep extends SharedJSTypeRep<DartType> {
- final Dart2TypeSystem rules;
+ final TypeSystemImpl rules;
final TypeProvider types;
final ClassElement _jsBool;
diff --git a/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart b/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
index 3f4cd73..d639be6 100644
--- a/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/module_compiler.dart
@@ -314,23 +314,9 @@
String mapPath = jsPath + '.map';
var code = getCode(
format, p.toUri(jsPath).toString(), p.toUri(mapPath).toString());
- var c = code.code;
- if (format == ModuleFormat.amdConcat ||
- format == ModuleFormat.legacyConcat) {
- // In single-out-file mode we wrap each module in an eval statement to
- // leverage sourceURL to improve the debugging experience when source maps
- // are not enabled.
- //
- // Note: We replace all `/` with `.` so that we don't break relative urls
- // to sources in the original sourcemap. The name of this file is bogus
- // anyways, so it has very little effect on things.
- c += '\n//# sourceURL=${name.replaceAll("/", ".")}.js\n';
- c = 'eval(${json.encode(c)});\n';
- }
-
var file = File(jsPath);
if (!file.parent.existsSync()) file.parent.createSync(recursive: true);
- file.writeAsStringSync(c);
+ file.writeAsStringSync(code.code);
// TODO(jacobr): it is a bit strange we are writing the source map to a file
// even when options.inlineSourceMap is true. To be consistent perhaps we
diff --git a/pkg/dev_compiler/lib/src/compiler/module_builder.dart b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
index ec1ea4a..8ac6e20 100644
--- a/pkg/dev_compiler/lib/src/compiler/module_builder.dart
+++ b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:args/args.dart' show ArgParser, ArgResults;
-import 'package:args/command_runner.dart' show UsageException;
import 'package:path/path.dart' as p;
import '../js_ast/js_ast.dart';
@@ -20,14 +19,8 @@
/// Asynchronous Module Definition (AMD, used in browsers).
amd,
- /// Dart Dev Compiler's legacy format (deprecated).
- legacy,
-
- /// Like [amd] but can be concatenated into a single file.
- amdConcat,
-
- /// Like [legacy] but can be concatenated into a single file.
- legacyConcat
+ /// Dart Dev Compiler's own format.
+ ddc,
}
/// Parses a string into a [ModuleFormat].
@@ -35,35 +28,15 @@
'es6': ModuleFormat.es6,
'common': ModuleFormat.common,
'amd': ModuleFormat.amd,
+ 'ddc': ModuleFormat.ddc,
// Deprecated:
'node': ModuleFormat.common,
- 'legacy': ModuleFormat.legacy
+ 'legacy': ModuleFormat.ddc
}[s];
/// Parse the module format option added by [addModuleFormatOptions].
List<ModuleFormat> parseModuleFormatOption(ArgResults args) {
- var formats =
- (args['modules'] as List<String>).map(parseModuleFormat).toList();
-
- if (args['single-out-file'] as bool) {
- for (int i = 0; i < formats.length; i++) {
- var format = formats[i];
- switch (formats[i]) {
- case ModuleFormat.amd:
- formats[i] = ModuleFormat.amdConcat;
- break;
- case ModuleFormat.legacy:
- formats[i] = ModuleFormat.legacyConcat;
- break;
- default:
- throw UsageException(
- 'Format $format cannot be combined with '
- 'single-out-file. Only amd and legacy modes are supported.',
- '');
- }
- }
- }
- return formats;
+ return (args['modules'] as List<String>).map(parseModuleFormat).toList();
}
/// Adds an option to the [argParser] for choosing the module format, optionally
@@ -74,7 +47,8 @@
'es6',
'common',
'amd',
- 'legacy', // deprecated
+ 'ddc',
+ 'legacy', // renamed to ddc
'node', // renamed to commonjs
'all' // to emit all flavors for the SDK
], allowedHelp: {
@@ -84,12 +58,6 @@
}, defaultsTo: [
'amd'
]);
-
- argParser.addFlag('single-out-file',
- help: 'emit modules that can be concatenated into one file.\n'
- 'Only compatible with legacy and amd module formats.',
- defaultsTo: false,
- hide: hide);
}
/// Transforms an ES6 [module] into a given module [format].
@@ -102,16 +70,12 @@
/// [ExportDeclaration]s.
Program transformModuleFormat(ModuleFormat format, Program module) {
switch (format) {
- case ModuleFormat.legacy:
- case ModuleFormat.legacyConcat:
- // Legacy format always generates output compatible with single file mode.
- return LegacyModuleBuilder().build(module);
+ case ModuleFormat.ddc:
+ return DdcModuleBuilder().build(module);
case ModuleFormat.common:
return CommonJSModuleBuilder().build(module);
case ModuleFormat.amd:
return AmdModuleBuilder().build(module);
- case ModuleFormat.amdConcat:
- return AmdModuleBuilder(singleOutFile: true).build(module);
case ModuleFormat.es6:
default:
return module;
@@ -161,9 +125,9 @@
}
}
-/// Generates modules for with our legacy `dart_library.js` loading mechanism.
+/// Generates modules for with our DDC `dart_library.js` loading mechanism.
// TODO(jmesserly): remove this and replace with something that interoperates.
-class LegacyModuleBuilder extends _ModuleBuilder {
+class DdcModuleBuilder extends _ModuleBuilder {
Program build(Program module) {
// Collect imports/exports/statements.
visitProgram(module);
@@ -180,7 +144,8 @@
TemporaryId(pathToJSIdentifier(import.from.valueWithoutQuotes));
parameters.add(moduleVar);
for (var importName in import.namedImports) {
- assert(!importName.isStar); // import * not supported in legacy modules.
+ assert(!importName
+ .isStar); // import * not supported in ddc format modules.
var asName = importName.asName ?? importName.name;
var fromName = importName.name.name;
// Load non-SDK modules on demand (i.e., deferred).
@@ -204,7 +169,7 @@
// TODO(jmesserly): make these immutable in JS?
for (var export in exports) {
var names = export.exportedNames;
- assert(names != null); // export * not supported in legacy modules.
+ assert(names != null); // export * not supported in ddc modules.
for (var name in names) {
var alias = name.asName ?? name.name;
statements.add(
@@ -280,9 +245,7 @@
/// Generates AMD modules (used in browsers with RequireJS).
class AmdModuleBuilder extends _ModuleBuilder {
- final bool singleOutFile;
-
- AmdModuleBuilder({this.singleOutFile = false});
+ AmdModuleBuilder();
Program build(Program module) {
var importStatements = <Statement>[];
@@ -326,16 +289,9 @@
}
// TODO(vsm): Consider using an immediately invoked named function pattern
- // (see legacy code above).
- var block = singleOutFile
- ? js.statement("define(#, #, function(#) { 'use strict'; #; });", [
- js.string(module.name, "'"),
- ArrayInitializer(dependencies),
- fnParams,
- statements
- ])
- : js.statement("define(#, function(#) { 'use strict'; #; });",
- [ArrayInitializer(dependencies), fnParams, statements]);
+ // (see ddc module code above).
+ var block = js.statement("define(#, function(#) { 'use strict'; #; });",
+ [ArrayInitializer(dependencies), fnParams, statements]);
return Program([block]);
}
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_command.dart b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
index 09374d2..3d4f240 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_command.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
@@ -349,7 +349,14 @@
var scheme = uri.scheme;
if (scheme == 'dart' || scheme == 'package' || scheme == multiRootScheme) {
if (scheme == multiRootScheme) {
- var multiRootPath = "${multiRootOutputPath ?? ''}${uri.path}";
+ // TODO(sigmund): extract all source-map normalization outside ddc. This
+ // custom logic is BUILD specific and could be shared with other tools
+ // like dart2js.
+ var shortPath = uri.path
+ .replaceAll("/sdk/", "/dart-sdk/")
+ .replaceAll("/sdk_nnbd/", "/dart-sdk/");
+ var multiRootPath = "${multiRootOutputPath ?? ''}$shortPath";
+ multiRootPath = multiRootPath;
multiRootPath = p.url.relative(multiRootPath, from: sourceMapDir);
return multiRootPath;
}
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 4fa082c..478f3b3 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -10,6 +10,7 @@
import 'package:build_integration/file_system/multi_root.dart';
import 'package:cli_util/cli_util.dart' show getSdkPath;
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
+import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/kernel.dart' hide MapEntry;
import 'package:kernel/target/targets.dart';
import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
@@ -430,6 +431,77 @@
return CompilerResult(0, kernelState: compilerState);
}
+// A simplified entrypoint similar to `_compile` that only supports building the
+// sdk. Note that some changes in `_compile_` might need to be copied here as
+// well.
+// TODO(sigmund): refactor the underlying pieces to reduce the code duplication.
+Future<CompilerResult> compileSdkFromDill(List<String> args) async {
+ var argParser = ArgParser(allowTrailingOptions: true)
+ ..addMultiOption('out', abbr: 'o', help: 'Output file (required).')
+ ..addOption('multi-root-scheme', defaultsTo: 'org-dartlang-sdk')
+ ..addOption('multi-root-output-path',
+ help: 'Path to set multi-root files relative to when generating'
+ ' source-maps.',
+ hide: true);
+ SharedCompilerOptions.addArguments(argParser);
+
+ ArgResults argResults;
+ try {
+ argResults = argParser.parse(filterUnknownArguments(args, argParser));
+ } on FormatException catch (error) {
+ print(error);
+ print(_usageMessage(argParser));
+ return CompilerResult(64);
+ }
+
+ var outPaths = argResults['out'] as List<String>;
+ var moduleFormats = parseModuleFormatOption(argResults);
+ if (outPaths.isEmpty) {
+ print('Please specify the output file location. For example:\n'
+ ' -o PATH/TO/OUTPUT_FILE.js');
+ return CompilerResult(64);
+ } else if (outPaths.length != moduleFormats.length) {
+ print('Number of output files (${outPaths.length}) must match '
+ 'number of module formats (${moduleFormats.length}).');
+ return CompilerResult(64);
+ }
+
+ var component = loadComponentFromBinary(argResults.rest[0]);
+ var hierarchy = ClassHierarchy(component);
+ var multiRootScheme = argResults['multi-root-scheme'] as String;
+ var multiRootOutputPath = argResults['multi-root-output-path'] as String;
+ var options = SharedCompilerOptions.fromArguments(argResults);
+
+ var compiler = ProgramCompiler(component, hierarchy, options);
+ var jsModule = compiler.emitModule(component, const [], const [], const {});
+ var outFiles = <Future>[];
+
+ // Also the old Analyzer backend had some code to make debugging better when
+ // --single-out-file is used, but that option does not appear to be used by
+ // any of our build systems.
+ for (var i = 0; i < outPaths.length; ++i) {
+ var output = outPaths[i];
+ var moduleFormat = moduleFormats[i];
+ var file = File(output);
+ await file.parent.create(recursive: true);
+ var jsCode = jsProgramToCode(jsModule, moduleFormat,
+ buildSourceMap: options.sourceMap,
+ inlineSourceMap: options.inlineSourceMap,
+ jsUrl: p.toUri(output).toString(),
+ mapUrl: p.toUri(output + '.map').toString(),
+ bazelMapping: options.bazelMapping,
+ customScheme: multiRootScheme,
+ multiRootOutputPath: multiRootOutputPath);
+
+ outFiles.add(file.writeAsString(jsCode.code));
+ if (jsCode.sourceMap != null) {
+ outFiles.add(
+ File(output + '.map').writeAsString(json.encode(jsCode.sourceMap)));
+ }
+ }
+ return CompilerResult(0);
+}
+
/// The output of compiling a JavaScript module in a particular format.
/// This was copied from module_compiler.dart class "JSModuleCode".
class JSCode {
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 939ee1b..369ec38 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -6,7 +6,6 @@
import 'dart:convert';
import 'dart:math' show max, min;
-import 'package:front_end/src/api_unstable/ddc.dart' show TypeSchemaEnvironment;
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart' hide MapEntry;
@@ -112,6 +111,8 @@
final TypeEnvironment _types;
+ final StatefulStaticTypeContext _staticTypeContext;
+
final ClassHierarchy _hierarchy;
/// Information about virtual and overridden fields/getters/setters in the
@@ -219,12 +220,22 @@
SharedCompilerOptions options,
{CoreTypes coreTypes}) {
coreTypes ??= CoreTypes(component);
- var types = TypeSchemaEnvironment(coreTypes, hierarchy);
+ var types = TypeEnvironment(coreTypes, hierarchy);
var constants = DevCompilerConstants();
var nativeTypes = NativeTypeSet(coreTypes, constants);
var jsTypeRep = JSTypeRep(types, hierarchy);
- return ProgramCompiler._(coreTypes, coreTypes.index, nativeTypes, constants,
- types, hierarchy, jsTypeRep, NullableInference(jsTypeRep), options);
+ var staticTypeContext = StatefulStaticTypeContext.stacked(types);
+ return ProgramCompiler._(
+ coreTypes,
+ coreTypes.index,
+ nativeTypes,
+ constants,
+ types,
+ hierarchy,
+ jsTypeRep,
+ NullableInference(jsTypeRep, staticTypeContext),
+ staticTypeContext,
+ options);
}
ProgramCompiler._(
@@ -236,6 +247,7 @@
this._hierarchy,
this._typeRep,
this._nullableInference,
+ this._staticTypeContext,
this._options)
: _jsArrayClass = sdk.getClass('dart:_interceptors', 'JSArray'),
_asyncStreamIteratorClass =
@@ -405,6 +417,7 @@
// See _emitClass.
assert(_currentLibrary == null);
_currentLibrary = library;
+ _staticTypeContext.enterLibrary(_currentLibrary);
if (isSdkInternalRuntime(library)) {
// `dart:_runtime` uses a different order for bootstrapping.
@@ -427,6 +440,7 @@
_emitTopLevelFields(library.fields);
}
+ _staticTypeContext.leaveLibrary(_currentLibrary);
_currentLibrary = null;
}
@@ -472,7 +486,6 @@
var savedLibrary = _currentLibrary;
var savedUri = _currentUri;
_currentClass = c;
- _types.thisType = c.thisType;
_currentLibrary = c.enclosingLibrary;
_currentUri = c.fileUri;
@@ -484,7 +497,6 @@
}
_currentClass = savedClass;
- _types.thisType = savedClass?.thisType;
_currentLibrary = savedLibrary;
_currentUri = savedUri;
}
@@ -763,7 +775,8 @@
}
getBaseClass(int count) {
- var base = emitDeferredType(c.thisType);
+ var base = emitDeferredType(
+ c.getThisType(_coreTypes, c.enclosingLibrary.nonNullable));
while (--count >= 0) {
base = js.call('#.__proto__', [base]);
}
@@ -1345,8 +1358,10 @@
!f.namedParameters.any(isCovariantParameter)) {
result = f.thisFunctionType;
} else {
- reifyParameter(VariableDeclaration p) =>
- isCovariantParameter(p) ? _coreTypes.objectClass.thisType : p.type;
+ reifyParameter(VariableDeclaration p) => isCovariantParameter(p)
+ ? _coreTypes.objectClass.getThisType(
+ _coreTypes, _coreTypes.objectClass.enclosingLibrary.nonNullable)
+ : p.type;
reifyNamedParameter(VariableDeclaration p) =>
NamedType(p.name, reifyParameter(p));
@@ -1374,6 +1389,7 @@
Constructor node, List<Field> fields, js_ast.Expression className) {
var savedUri = _currentUri;
_currentUri = node.fileUri ?? savedUri;
+ _staticTypeContext.enterMember(node);
var params = _emitParameters(node.function);
var body = _withCurrentFunction(
node.function,
@@ -1382,6 +1398,7 @@
var end = _nodeEnd(node.fileEndOffset);
_currentUri = savedUri;
+ _staticTypeContext.leaveMember(node);
end ??= _nodeEnd(node.enclosingClass.fileEndOffset);
return js_ast.Fun(params, js_ast.Block(body))..sourceInformation = end;
@@ -1530,7 +1547,9 @@
(init == null || _constants.isConstant(init))) {
continue;
}
+ _staticTypeContext.enterMember(f);
emitFieldInit(f, init, f);
+ _staticTypeContext.leaveMember(f);
}
// Run constructor field initializers such as `: foo = bar.baz`
@@ -1650,6 +1669,7 @@
var savedUri = _currentUri;
for (var m in c.procedures) {
+ _staticTypeContext.enterMember(m);
// For the Dart SDK, we use the member URI because it may be different
// from the class (because of patch files). User code does not need this.
//
@@ -1662,9 +1682,11 @@
// TODO(jmesserly): is there any other kind of forwarding stub?
jsMethods.addAll(_emitCovarianceCheckStub(m));
} else if (m.isFactory) {
- // Skip redirecting factories (they've already been resolved).
- if (redirectingFactories?.contains(m) ?? false) continue;
- jsMethods.add(_emitFactoryConstructor(m));
+ if (redirectingFactories?.contains(m) ?? false) {
+ // Skip redirecting factories (they've already been resolved).
+ } else {
+ jsMethods.add(_emitFactoryConstructor(m));
+ }
} else if (m.isAccessor) {
jsMethods.add(_emitMethodDeclaration(m));
jsMethods.add(_emitSuperAccessorWrapper(m, getters, setters));
@@ -1675,6 +1697,7 @@
} else {
jsMethods.add(_emitMethodDeclaration(m));
}
+ _staticTypeContext.leaveMember(m);
}
_currentUri = savedUri;
@@ -2027,11 +2050,12 @@
// Helper functions to test if a constructor invocation is internal and
// should be eagerly evaluated.
var isInternalConstructor = (ConstructorInvocation node) {
- var type = node.getStaticType(_types) as InterfaceType;
+ var type = node.getStaticType(_staticTypeContext) as InterfaceType;
var library = type.classNode.enclosingLibrary;
return isSdkInternalRuntime(library);
};
for (var field in fields) {
+ _staticTypeContext.enterMember(field);
var init = field.initializer;
if (init == null ||
init is BasicLiteral ||
@@ -2040,7 +2064,7 @@
if (init is ConstructorInvocation) {
// This is an eagerly executed constructor invocation. We need to
// ensure the class is emitted before this statement.
- var type = init.getStaticType(_types) as InterfaceType;
+ var type = init.getStaticType(_staticTypeContext) as InterfaceType;
_emitClass(type.classNode);
}
_currentUri = field.fileUri;
@@ -2051,6 +2075,7 @@
} else {
lazyFields.add(field);
}
+ _staticTypeContext.leaveMember(field);
}
_currentUri = savedUri;
@@ -2071,6 +2096,7 @@
for (var field in fields) {
_currentUri = field.fileUri;
+ _staticTypeContext.enterMember(field);
var access = emitFieldName(field);
accessors.add(js_ast.Method(access, _emitStaticFieldInitializer(field),
isGetter: true)
@@ -2085,6 +2111,7 @@
access, js.call('function(_) {}') as js_ast.Fun,
isSetter: true));
}
+ _staticTypeContext.leaveMember(field);
}
_currentUri = _currentLibrary.fileUri;
@@ -2422,6 +2449,7 @@
js_ast.Method _emitLibraryAccessor(Procedure node) {
var savedUri = _currentUri;
+ _staticTypeContext.enterMember(node);
_currentUri = node.fileUri;
var name = node.name.name;
@@ -2431,11 +2459,13 @@
..sourceInformation = _nodeEnd(node.fileEndOffset);
_currentUri = savedUri;
+ _staticTypeContext.leaveMember(node);
return result;
}
js_ast.Statement _emitLibraryFunction(Procedure p) {
var savedUri = _currentUri;
+ _staticTypeContext.enterMember(p);
_currentUri = p.fileUri;
var body = <js_ast.Statement>[];
@@ -2461,6 +2491,7 @@
}
_currentUri = savedUri;
+ _staticTypeContext.leaveMember(p);
return js_ast.Statement.from(body);
}
@@ -3163,7 +3194,8 @@
}
if (node is AsExpression && node.isTypeError) {
- assert(node.getStaticType(_types) == _types.coreTypes.boolLegacyRawType);
+ assert(node.getStaticType(_staticTypeContext) ==
+ _types.coreTypes.boolLegacyRawType);
return runtimeCall('dtest(#)', [_visitExpression(node.operand)]);
}
@@ -3290,7 +3322,7 @@
js_ast.Statement visitAssertStatement(AssertStatement node) {
if (!_options.enableAsserts) return js_ast.EmptyStatement();
var condition = node.condition;
- var conditionType = condition.getStaticType(_types);
+ var conditionType = condition.getStaticType(_staticTypeContext);
var jsCondition = _visitExpression(condition);
var boolType = _coreTypes.boolLegacyRawType;
@@ -3943,7 +3975,7 @@
// encoded as a different node, or possibly eliminated?
// (Regardless, we'll still need to handle the callable JS interop classes.)
if (memberName == 'call' &&
- _isDirectCallable(receiver.getStaticType(_types))) {
+ _isDirectCallable(receiver.getStaticType(_staticTypeContext))) {
// Tearoff of `call` on a function type is a no-op;
return _visitExpression(receiver);
}
@@ -4068,7 +4100,7 @@
target.hasGetter &&
_isDynamicOrFunction(target.getterType);
if (name == 'call') {
- var receiverType = receiver.getStaticType(_types);
+ var receiverType = receiver.getStaticType(_staticTypeContext);
if (isCallingDynamicField || _isDynamicOrFunction(receiverType)) {
return _emitDynamicInvoke(jsReceiver, null, args, arguments);
} else if (_isDirectCallable(receiverType)) {
@@ -4332,7 +4364,7 @@
if (target != null) {
var targetClass = target.enclosingClass;
var leftType = _coreTypes.legacyRawType(targetClass);
- var rightType = right.getStaticType(_types);
+ var rightType = right.getStaticType(_staticTypeContext);
if (_typeRep.binaryOperationIsPrimitive(leftType, rightType) ||
leftType == _types.coreTypes.stringLegacyRawType && op == '+') {
@@ -4432,7 +4464,7 @@
var targetClass = target?.enclosingClass;
var leftType = targetClass != null
? _coreTypes.legacyRawType(targetClass)
- : left.getStaticType(_types);
+ : left.getStaticType(_staticTypeContext);
// Conceptually `x == y` in Dart is defined as:
//
@@ -4731,15 +4763,16 @@
}
bool _isNull(Expression expr) =>
- expr is NullLiteral || expr.getStaticType(_types) == _coreTypes.nullType;
+ expr is NullLiteral ||
+ expr.getStaticType(_staticTypeContext) == _coreTypes.nullType;
bool _doubleEqIsIdentity(Expression left, Expression right) {
// If we statically know LHS or RHS is null we can use ==.
if (_isNull(left) || _isNull(right)) return true;
// If the representation of the two types will not induce conversion in
// JS then we can use == .
- return !_typeRep.equalityMayConvert(
- left.getStaticType(_types), right.getStaticType(_types));
+ return !_typeRep.equalityMayConvert(left.getStaticType(_staticTypeContext),
+ right.getStaticType(_staticTypeContext));
}
bool _tripleEqIsIdentity(Expression left, Expression right) {
@@ -4943,11 +4976,11 @@
if (jsExpr is js_ast.LiteralString && jsExpr.valueWithoutQuotes.isEmpty) {
continue;
}
- parts.add(
- e.getStaticType(_types) == _types.coreTypes.stringLegacyRawType &&
- !isNullable(e)
- ? jsExpr
- : runtimeCall('str(#)', [jsExpr]));
+ parts.add(e.getStaticType(_staticTypeContext) ==
+ _types.coreTypes.stringLegacyRawType &&
+ !isNullable(e)
+ ? jsExpr
+ : runtimeCall('str(#)', [jsExpr]));
}
if (parts.isEmpty) return js.string('');
return js_ast.Expression.binary(parts, '+');
@@ -5005,7 +5038,7 @@
Expression fromExpr = node.operand;
var to = node.type;
var jsFrom = _visitExpression(fromExpr);
- var from = fromExpr.getStaticType(_types);
+ var from = fromExpr.getStaticType(_staticTypeContext);
// If the check was put here by static analysis to ensure soundness, we
// can't skip it. For example, one could implement covariant generic caller
@@ -5146,8 +5179,8 @@
// TODO(markzipan): remove const check when we use front-end const eval
if (!node.isConst) {
- var mapType =
- _emitMapImplType(node.getStaticType(_types) as InterfaceType);
+ var mapType = _emitMapImplType(
+ node.getStaticType(_staticTypeContext) as InterfaceType);
if (node.entries.isEmpty) {
return js.call('new #.new()', [mapType]);
}
@@ -5170,7 +5203,8 @@
js_ast.Expression visitFunctionExpression(FunctionExpression node) {
var fn = _emitArrowFunction(node);
if (!_reifyFunctionType(node.function)) return fn;
- return _emitFunctionTagged(fn, node.getStaticType(_types) as FunctionType);
+ return _emitFunctionTagged(
+ fn, node.getStaticType(_staticTypeContext) as FunctionType);
}
js_ast.ArrowFun _emitArrowFunction(FunctionExpression node) {
@@ -5251,7 +5285,7 @@
js_ast.Expression genFn = js_ast.Fun([], jsBlock, isGenerator: true);
if (usesThisOrSuper(genFn)) genFn = js.call('#.bind(this)', genFn);
var asyncLibrary = emitLibraryName(_coreTypes.asyncLibrary);
- var returnType = _emitType(node.getStaticType(_types));
+ var returnType = _emitType(node.getStaticType(_staticTypeContext));
var asyncCall =
js.call('#.async(#, #)', [asyncLibrary, returnType, genFn]);
return js_ast.Yield(asyncCall);
@@ -5450,7 +5484,8 @@
return js_ast.Property(symbol, constant);
}
- var type = visitInterfaceType(node.getType(_types) as InterfaceType);
+ var type =
+ visitInterfaceType(node.getType(_staticTypeContext) as InterfaceType);
var prototype = js.call("#.prototype", [type]);
var properties = [
js_ast.Property(propertyName("__proto__"), prototype),
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index c49ba46..f549783 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -14,7 +14,7 @@
/// This class can also analyze the nullability of local variables, if
/// [enterFunction] and [exitFunction] are used.
class NullableInference extends ExpressionVisitor<bool> {
- final TypeEnvironment types;
+ final StaticTypeContext _staticTypeContext;
final JSTypeRep jsTypeRep;
final CoreTypes coreTypes;
@@ -38,19 +38,22 @@
final _variableInference = _NullableVariableInference();
- NullableInference(this.jsTypeRep)
- : types = jsTypeRep.types,
- coreTypes = jsTypeRep.coreTypes {
+ NullableInference(this.jsTypeRep, this._staticTypeContext)
+ : coreTypes = jsTypeRep.coreTypes {
_variableInference._nullInference = this;
}
/// Call when entering a function to enable [isNullable] to recognize local
/// variables that cannot be null.
- void enterFunction(FunctionNode fn) => _variableInference.enterFunction(fn);
+ void enterFunction(FunctionNode fn) {
+ _variableInference.enterFunction(fn);
+ }
/// Call when exiting a function to clear out the information recorded by
/// [enterFunction].
- void exitFunction(FunctionNode fn) => _variableInference.exitFunction(fn);
+ void exitFunction(FunctionNode fn) {
+ _variableInference.exitFunction(fn);
+ }
/// Returns true if [expr] can be null.
bool isNullable(Expression expr) => expr != null ? expr.accept(this) : false;
@@ -119,7 +122,8 @@
if (target == null) return true; // dynamic call
if (target.name.name == 'toString' &&
receiver != null &&
- receiver.getStaticType(types) == coreTypes.stringLegacyRawType) {
+ receiver.getStaticType(_staticTypeContext) ==
+ coreTypes.stringLegacyRawType) {
// TODO(jmesserly): `class String` in dart:core does not explicitly
// declare `toString`, which results in a target of `Object.toString` even
// when the reciever type is known to be `String`. So we work around it.
@@ -164,7 +168,9 @@
@override
visitStaticInvocation(StaticInvocation node) {
var target = node.target;
- if (target == types.coreTypes.identicalProcedure) return false;
+ if (target == coreTypes.identicalProcedure) {
+ return false;
+ }
if (isInlineJS(target)) {
var args = node.arguments.positional;
var first = args.isNotEmpty ? args.first : null;
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 960e92a..7cd1fc0 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -23,6 +23,11 @@
@override
bool get enableSuperMixins => true;
+ // TODO(johnniwinther): Change this to `false` when late field lowering is
+ // ready.
+ @override
+ bool get supportsLateFields => true;
+
@override
String get name => 'dartdevc';
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index c7f7e28..4a49356 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -8,6 +8,7 @@
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/type_environment.dart';
import 'package:kernel/target/targets.dart';
import 'package:test/test.dart';
@@ -527,16 +528,21 @@
class _TestRecursiveVisitor extends RecursiveVisitor<void> {
final Set<Library> librariesFromDill;
int _functionNesting = 0;
+ TypeEnvironment _typeEnvironment;
+ StatefulStaticTypeContext _staticTypeContext;
_TestRecursiveVisitor(this.librariesFromDill);
@override
visitComponent(Component node) {
var hierarchy = ClassHierarchy(node);
- inference ??= NullableInference(JSTypeRep(
+ var jsTypeRep = JSTypeRep(
fe.TypeSchemaEnvironment(CoreTypes(node), hierarchy),
hierarchy,
- ));
+ );
+ _typeEnvironment = jsTypeRep.types;
+ _staticTypeContext = StatefulStaticTypeContext.stacked(_typeEnvironment);
+ inference ??= NullableInference(jsTypeRep, _staticTypeContext);
if (useAnnotations) {
inference.allowNotNullDeclarations = useAnnotations;
@@ -547,18 +553,43 @@
@override
visitLibrary(Library node) {
+ _staticTypeContext.enterLibrary(node);
if (librariesFromDill.contains(node) ||
node.importUri.scheme == 'package' &&
node.importUri.pathSegments[0] == 'meta') {
return;
}
super.visitLibrary(node);
+ _staticTypeContext.leaveLibrary(node);
+ }
+
+ @override
+ visitField(Field node) {
+ _staticTypeContext.enterMember(node);
+ super.visitField(node);
+ _staticTypeContext.leaveMember(node);
+ }
+
+ @override
+ visitConstructor(Constructor node) {
+ _staticTypeContext.enterMember(node);
+ super.visitConstructor(node);
+ _staticTypeContext.leaveMember(node);
+ }
+
+ @override
+ visitProcedure(Procedure node) {
+ _staticTypeContext.enterMember(node);
+ super.visitProcedure(node);
+ _staticTypeContext.leaveMember(node);
}
@override
visitFunctionNode(FunctionNode node) {
_functionNesting++;
- if (_functionNesting == 1) inference.enterFunction(node);
+ if (_functionNesting == 1) {
+ inference.enterFunction(node);
+ }
super.visitFunctionNode(node);
if (_functionNesting == 1) inference.exitFunction(node);
_functionNesting--;
diff --git a/pkg/dev_compiler/test/sdk_source_map_test.dart b/pkg/dev_compiler/test/sdk_source_map_test.dart
index f4028f5..da0683f 100644
--- a/pkg/dev_compiler/test/sdk_source_map_test.dart
+++ b/pkg/dev_compiler/test/sdk_source_map_test.dart
@@ -27,6 +27,6 @@
Expect.equals(p.extension(url), '.dart');
Expect.isFalse(p.isAbsolute(url));
var fullPath = p.canonicalize(p.join(sdkJsMapDir, url));
- Expect.isTrue(await File(fullPath).exists());
+ Expect.isTrue(await File(fullPath).exists(), "Missing file: $fullPath");
}
}
diff --git a/pkg/dev_compiler/test/sourcemap/README.md b/pkg/dev_compiler/test/sourcemap/README.md
index a855144..65c5ef3 100644
--- a/pkg/dev_compiler/test/sourcemap/README.md
+++ b/pkg/dev_compiler/test/sourcemap/README.md
@@ -7,7 +7,7 @@
Running the tests likely requires the compilation of the correct targets. DDK currently also
requires `ddc_sdk.dill` inside
-`{sdkroot}/{out,xcodebuild}/ReleaseX64/gen/utils/dartdevc/kernel/ddc_sdk.dill`.
+`{sdkroot}/{out,xcodebuild}/ReleaseX64/ddc_sdk.dill`.
Except for that, running them should simply be a matter of executing the `*_suite.dart` files.
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
index cec6887..3246bd5 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
@@ -56,7 +56,7 @@
File sdkJsFile = findInOutDir("gen/utils/dartdevc/js/es6/dart_sdk.js");
var jsSdkPath = sdkJsFile.uri;
- File ddcSdkSummary = findInOutDir("gen/utils/dartdevc/kernel/ddc_sdk.dill");
+ File ddcSdkSummary = findInOutDir("ddc_sdk.dill");
List<String> args = <String>[
"--packages=${sdkRoot.uri.resolve(".packages").toFilePath()}",
diff --git a/pkg/dev_compiler/tool/check_nnbd_sdk.dart b/pkg/dev_compiler/tool/check_nnbd_sdk.dart
new file mode 100644
index 0000000..8d36bb9
--- /dev/null
+++ b/pkg/dev_compiler/tool/check_nnbd_sdk.dart
@@ -0,0 +1,77 @@
+#!/usr/bin/env dart
+// Copyright (c) 2019, 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.
+
+/// Command-line tool that runs dartanalyzer on a sdk under the perspective of
+/// one tool.
+// TODO(sigmund): generalize this to support other tools, not just ddc.
+
+import 'dart:io';
+import 'package:args/args.dart';
+import 'package:front_end/src/fasta/resolve_input_uri.dart';
+
+import 'patch_sdk.dart' as patch;
+
+void main(List<String> argv) {
+ var args = _parser.parse(argv);
+ String baseDir = args['out'] as String;
+ if (baseDir == null) {
+ var tmp = Directory.systemTemp.createTempSync('check_sdk-');
+ baseDir = tmp.path;
+ }
+ var baseUri = resolveInputUri(baseDir.endsWith('/') ? baseDir : '$baseDir/');
+ var sdkDir = baseUri.resolve('sdk/').toFilePath();
+ print('Generating a patched sdk at ${baseUri.path}');
+
+ Uri librariesJson = args['libraries'] != null
+ ? resolveInputUri(args['libraries'] as String)
+ : Platform.script.resolve('../../../sdk_nnbd/lib/libraries.json');
+ patch.main([
+ '--libraries',
+ librariesJson.toFilePath(),
+ '--target',
+ args['target'] as String,
+ '--out',
+ sdkDir,
+ '--merge-parts',
+ '--nnbd',
+ ]);
+
+ var emptyProgramUri = baseUri.resolve('empty_program.dart');
+ File.fromUri(emptyProgramUri).writeAsStringSync('main() {}');
+
+ print('Running dartanalyzer');
+ var dart = Uri.base.resolve(Platform.resolvedExecutable);
+ var analyzerSnapshot = Uri.base
+ .resolve(Platform.resolvedExecutable)
+ .resolve('snapshots/dartanalyzer.dart.snapshot');
+ var result = Process.runSync(dart.toFilePath(), [
+ analyzerSnapshot.toFilePath(),
+ '--dart-sdk=${sdkDir}',
+ '--format',
+ 'machine',
+ '--sdk-warnings',
+ '--no-hints',
+ emptyProgramUri.toFilePath()
+ ]);
+
+ stdout.write(result.stdout);
+ String errors = result.stderr as String;
+ var count = errors.trim().split('\n').length;
+ print('$count analyzer errors. Errors emitted to ${baseUri.path}errors.txt');
+ File.fromUri(baseUri.resolve('errors.txt')).writeAsStringSync(errors);
+}
+
+final _parser = ArgParser()
+ ..addOption('libraries',
+ help: 'Path to the nnbd libraries.json (defaults to the one under '
+ 'sdk_nnbd/lib/libraries.json.')
+ ..addOption('out',
+ help: 'Path to an output folder (defaults to a new tmp folder).')
+ ..addOption('target',
+ help: 'The target tool. '
+ 'This name matches one of the possible targets in libraries.json '
+ 'and it is used to pick which patch files will be applied.',
+ allowed: ['dartdevc', 'dart2js', 'dart2js_server', 'vm', 'flutter'],
+ defaultsTo: 'dartdevc');
diff --git a/pkg/dev_compiler/tool/compile_dartdevc_sdk.dart b/pkg/dev_compiler/tool/compile_dartdevc_sdk.dart
new file mode 100644
index 0000000..097a40a
--- /dev/null
+++ b/pkg/dev_compiler/tool/compile_dartdevc_sdk.dart
@@ -0,0 +1,15 @@
+#!/usr/bin/env dart
+// Copyright (c) 2019, 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.
+
+/// Tool that consumes the .dill file of an entire dart-sdk and produces the
+/// corresponding Javascript module.
+
+import 'dart:io';
+import 'package:dev_compiler/src/kernel/command.dart';
+
+main(List<String> args) async {
+ var result = await compileSdkFromDill(args);
+ exitCode = result.exitCode;
+}
diff --git a/pkg/dev_compiler/tool/ddc b/pkg/dev_compiler/tool/ddc
index 4fff33d..cfe8879 100755
--- a/pkg/dev_compiler/tool/ddc
+++ b/pkg/dev_compiler/tool/ddc
@@ -51,7 +51,8 @@
fi
fi
-GEN_DIR="$OUT_DIR"/"$DART_CONFIGURATION"/gen/utils/dartdevc
+ROOT_OUT_DIR="$OUT_DIR"/"$DART_CONFIGURATION"
+GEN_DIR="$ROOT_OUT_DIR"/gen/utils/dartdevc
KERNEL=false
if [ "$1" = "-k" ]; then
@@ -64,7 +65,7 @@
if [ "$KERNEL" = true ]; then
- if [ ! -e $GEN_DIR/kernel/ddc_sdk.dill ]; then
+ if [ ! -e $ROOT_OUT_DIR/ddc_sdk.dill ]; then
echo "DDC SDK must be built first, please run:"
echo " pushd $SDKDIR"
echo " ./tools/build.py -m release dartdevc_kernel_sdk"
@@ -74,7 +75,7 @@
NODE_PATH=$GEN_DIR/kernel/common:$LIBROOT:$NODE_PATH
$SDK_DIR/sdk/bin/dartdevc --kernel --modules=node \
- --dart-sdk-summary=$GEN_DIR/ddc_sdk.sum \
+ --dart-sdk-summary=$ROOT_OUT_DIR/ddc_sdk.dill \
-o $LIBROOT/$BASENAME.js $*
else
diff --git a/pkg/dev_compiler/tool/kernel_sdk.dart b/pkg/dev_compiler/tool/kernel_sdk.dart
index 81eb813..6c337e6 100755
--- a/pkg/dev_compiler/tool/kernel_sdk.dart
+++ b/pkg/dev_compiler/tool/kernel_sdk.dart
@@ -100,7 +100,7 @@
'amd': ModuleFormat.amd,
'common': ModuleFormat.common,
'es6': ModuleFormat.es6,
- 'legacy': ModuleFormat.legacy,
+ 'legacy': ModuleFormat.ddc,
};
for (var name in moduleFormats.keys) {
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index d36bd4a..110685b 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -12,6 +12,7 @@
controlFlowCollections,
extensionMethods,
nonNullable,
+ nonfunctionTypeAliases,
setLiterals,
spreadCollections,
tripleShift,
@@ -28,6 +29,8 @@
return ExperimentalFlag.extensionMethods;
case "non-nullable":
return ExperimentalFlag.nonNullable;
+ case "nonfunction-type-aliases":
+ return ExperimentalFlag.nonfunctionTypeAliases;
case "set-literals":
return ExperimentalFlag.setLiterals;
case "spread-collections":
@@ -45,6 +48,7 @@
ExperimentalFlag.controlFlowCollections: true,
ExperimentalFlag.extensionMethods: true,
ExperimentalFlag.nonNullable: false,
+ ExperimentalFlag.nonfunctionTypeAliases: false,
ExperimentalFlag.setLiterals: true,
ExperimentalFlag.spreadCollections: true,
ExperimentalFlag.tripleShift: false,
@@ -56,6 +60,7 @@
ExperimentalFlag.controlFlowCollections: true,
ExperimentalFlag.extensionMethods: false,
ExperimentalFlag.nonNullable: false,
+ ExperimentalFlag.nonfunctionTypeAliases: false,
ExperimentalFlag.setLiterals: true,
ExperimentalFlag.spreadCollections: true,
ExperimentalFlag.tripleShift: false,
diff --git a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
index ebb705a..8de9131 100644
--- a/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/kernel_generator.dart
@@ -109,6 +109,11 @@
/// The generated component, if it was requested.
Component get component;
+ Component get sdkComponent;
+
+ /// The components loaded from dill (excluding the sdk).
+ List<Component> get loadedComponents;
+
/// Dependencies traversed by the compiler. Used only for generating
/// dependency .GN files in the dart-sdk build system.
/// Note this might be removed when we switch to compute dependencies without
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 98f0245..8c3c529 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -15,6 +15,7 @@
Expression,
Field,
FunctionNode,
+ FunctionType,
InterfaceType,
InvalidType,
ListLiteral,
@@ -33,9 +34,8 @@
TypeParameterType,
VariableDeclaration,
Variance,
- VoidType;
-
-import 'package:kernel/ast.dart' show FunctionType, TypeParameterType;
+ VoidType,
+ getAsTypeArguments;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -49,6 +49,7 @@
computeVariance,
findTypeArgumentIssues,
getGenericTypeName;
+
import 'package:kernel/text/text_serialization_verifier.dart';
import 'package:kernel/type_algebra.dart' show Substitution, substitute;
@@ -383,6 +384,11 @@
@override
bool isNullClass = false;
+ InterfaceType _legacyRawType;
+ InterfaceType _nullableRawType;
+ InterfaceType _nonNullableRawType;
+ InterfaceType _thisType;
+
ClassBuilderImpl(
List<MetadataBuilder> metadata,
int modifiers,
@@ -604,33 +610,29 @@
return declaration;
}
- InterfaceType _legacyRawType;
- InterfaceType _nullableRawType;
- InterfaceType _nonNullableRawType;
-
@override
ClassBuilder get origin => actualOrigin ?? this;
@override
- InterfaceType get thisType => cls.thisType;
+ InterfaceType get thisType {
+ return _thisType ??= new InterfaceType(cls, library.nonNullable,
+ getAsTypeArguments(cls.typeParameters, library.library));
+ }
@override
InterfaceType get legacyRawType {
- // TODO(dmitryas): Use computeBound instead of DynamicType here?
return _legacyRawType ??= new InterfaceType(cls, Nullability.legacy,
new List<DartType>.filled(typeVariablesCount, const DynamicType()));
}
@override
InterfaceType get nullableRawType {
- // TODO(dmitryas): Use computeBound instead of DynamicType here?
return _nullableRawType ??= new InterfaceType(cls, Nullability.nullable,
new List<DartType>.filled(typeVariablesCount, const DynamicType()));
}
@override
InterfaceType get nonNullableRawType {
- // TODO(dmitryas): Use computeBound instead of DynamicType here?
return _nonNullableRawType ??= new InterfaceType(
cls,
Nullability.nonNullable,
@@ -804,7 +806,7 @@
List<TypeArgumentIssue> issues = findTypeArgumentIssues(
new InterfaceType(
- supertype.classNode, Nullability.legacy, supertype.typeArguments),
+ supertype.classNode, library.nonNullable, supertype.typeArguments),
typeEnvironment,
allowSuperBounded: false);
if (issues != null) {
@@ -1160,7 +1162,7 @@
target.loader.coreTypes,
new ThisExpression(),
prefix + procedure.name.name,
- new Arguments.forwarded(procedure.function),
+ new Arguments.forwarded(procedure.function, library.library),
procedure.fileOffset,
/*isSuper=*/ false);
Expression result = new MethodInvocation(new ThisExpression(),
@@ -1382,8 +1384,7 @@
Substitution interfaceSubstitution = Substitution.empty;
if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
interfaceSubstitution = Substitution.fromInterfaceType(types.hierarchy
- .getKernelTypeAsInstanceOf(
- cls.thisType, interfaceMember.enclosingClass));
+ .getKernelTypeAsInstanceOf(thisType, interfaceMember.enclosingClass));
}
if (declaredFunction?.typeParameters?.length !=
interfaceFunction?.typeParameters?.length) {
@@ -1408,8 +1409,9 @@
<TypeParameter, DartType>{};
for (int i = 0; i < declaredFunction.typeParameters.length; ++i) {
substitutionMap[interfaceFunction.typeParameters[i]] =
- new TypeParameterType(
- declaredFunction.typeParameters[i], Nullability.legacy);
+ new TypeParameterType.forAlphaRenaming(
+ interfaceFunction.typeParameters[i],
+ declaredFunction.typeParameters[i]);
}
Substitution substitution = Substitution.fromMap(substitutionMap);
for (int i = 0; i < declaredFunction.typeParameters.length; ++i) {
@@ -1454,8 +1456,7 @@
Substitution declaredSubstitution = Substitution.empty;
if (declaredMember.enclosingClass.typeParameters.isNotEmpty) {
declaredSubstitution = Substitution.fromInterfaceType(types.hierarchy
- .getKernelTypeAsInstanceOf(
- cls.thisType, declaredMember.enclosingClass));
+ .getKernelTypeAsInstanceOf(thisType, declaredMember.enclosingClass));
}
return declaredSubstitution;
}
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index 8c730f3..dfb0012 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -226,11 +226,12 @@
List<DartType> typeParameterTypes = new List<DartType>();
for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
TypeParameter typeParameter = enclosingClass.typeParameters[i];
- typeParameterTypes
- .add(new TypeParameterType(typeParameter, Nullability.legacy));
+ typeParameterTypes.add(
+ new TypeParameterType.withDefaultNullabilityForLibrary(
+ typeParameter, library.library));
}
functionNode.returnType = new InterfaceType(
- enclosingClass, Nullability.legacy, typeParameterTypes);
+ enclosingClass, library.nonNullable, typeParameterTypes);
return functionNode;
}
@@ -334,13 +335,14 @@
// stage, there is no easy way to make body building stage skip initializer
// parsing, so we simply clear parsed initializers and rebuild them
// again.
+ // For when doing an experimental incremental compilation they are also
+ // potentially done more than once (because it rebuilds the bodies of an old
+ // compile), and so we also clear them.
// Note: this method clears both initializers from the target Kernel node
// and internal state associated with parsing initializers.
- if (_constructor.isConst) {
- _constructor.initializers.length = 0;
- redirectingInitializer = null;
- superInitializer = null;
- hasMovedSuperInitializer = false;
- }
+ _constructor.initializers.length = 0;
+ redirectingInitializer = null;
+ superInitializer = null;
+ hasMovedSuperInitializer = false;
}
}
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
index 2a17bdcb..2d01cccc 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -128,9 +128,9 @@
/// String toString() => _name;
/// }
- members["index"] = new FieldBuilderImpl(null, intType, "index",
+ members["index"] = new SourceFieldBuilder(null, intType, "index",
finalMask | hasInitializerMask, parent, charOffset, charOffset);
- members["_name"] = new FieldBuilderImpl(null, stringType, "_name",
+ members["_name"] = new SourceFieldBuilder(null, stringType, "_name",
finalMask | hasInitializerMask, parent, charOffset, charOffset);
ConstructorBuilder constructorBuilder = new ConstructorBuilderImpl(
null,
@@ -150,7 +150,7 @@
charOffset,
charEndOffset);
constructors[""] = constructorBuilder;
- FieldBuilder valuesBuilder = new FieldBuilderImpl(
+ FieldBuilder valuesBuilder = new SourceFieldBuilder(
null,
listType,
"values",
@@ -209,7 +209,7 @@
name.length,
parent.fileUri);
}
- FieldBuilder fieldBuilder = new FieldBuilderImpl(
+ FieldBuilder fieldBuilder = new SourceFieldBuilder(
metadata,
selfType,
name,
@@ -273,10 +273,12 @@
coreLibrary.scope, charOffset, fileUri, libraryBuilder);
listType.resolveIn(coreLibrary.scope, charOffset, fileUri, libraryBuilder);
- FieldBuilderImpl indexFieldBuilder = firstMemberNamed("index");
- Field indexField = indexFieldBuilder.build(libraryBuilder);
- FieldBuilderImpl nameFieldBuilder = firstMemberNamed("_name");
- Field nameField = nameFieldBuilder.build(libraryBuilder);
+ SourceFieldBuilder indexFieldBuilder = firstMemberNamed("index");
+ indexFieldBuilder.build(libraryBuilder);
+ Field indexField = indexFieldBuilder.field;
+ SourceFieldBuilder nameFieldBuilder = firstMemberNamed("_name");
+ nameFieldBuilder.build(libraryBuilder);
+ Field nameField = nameFieldBuilder.field;
ProcedureBuilder toStringBuilder = firstMemberNamed("toString");
toStringBuilder.body = new ReturnStatement(
new DirectPropertyGet(new ThisExpression(), nameField));
@@ -286,16 +288,17 @@
if (enumConstantInfo != null) {
Builder declaration = firstMemberNamed(enumConstantInfo.name);
if (declaration.isField) {
- FieldBuilderImpl field = declaration;
- values.add(new StaticGet(field.build(libraryBuilder)));
+ SourceFieldBuilder fieldBuilder = declaration;
+ fieldBuilder.build(libraryBuilder);
+ values.add(new StaticGet(fieldBuilder.field));
}
}
}
}
- FieldBuilderImpl valuesBuilder = firstMemberNamed("values");
+ SourceFieldBuilder valuesBuilder = firstMemberNamed("values");
valuesBuilder.build(libraryBuilder);
- valuesBuilder.initializer = new ListLiteral(values,
- typeArgument: rawType(library.nonNullable), isConst: true);
+ valuesBuilder.buildBody(new ListLiteral(values,
+ typeArgument: rawType(library.nonNullable), isConst: true));
ConstructorBuilderImpl constructorBuilder = constructorScopeBuilder[""];
Constructor constructor = constructorBuilder.build(libraryBuilder);
constructor.initializers.insert(
@@ -339,8 +342,8 @@
new IntLiteral(index++),
new StringLiteral("$name.$constant")
]);
- field.initializer =
- new ConstructorInvocation(constructor, arguments, isConst: true);
+ field.buildBody(
+ new ConstructorInvocation(constructor, arguments, isConst: true));
}
}
}
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 941904a..341fe25 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -16,8 +16,9 @@
templateCantInferTypeDueToCircularity;
import '../kernel/body_builder.dart' show BodyBuilder;
-
+import '../kernel/class_hierarchy_builder.dart' show ClassMember;
import '../kernel/kernel_builder.dart' show ImplicitFieldType;
+import '../kernel/late_lowering.dart' as late_lowering;
import '../modifier.dart' show covariantMask, hasInitializerMask, lateMask;
@@ -37,7 +38,6 @@
import '../type_inference/type_schema.dart' show UnknownType;
-import 'builder.dart';
import 'class_builder.dart';
import 'extension_builder.dart';
import 'library_builder.dart';
@@ -62,22 +62,39 @@
bool get hasInitializer;
- void set initializer(Expression value);
+ /// Whether the body of this field has been built.
+ ///
+ /// Constant fields have their initializer built in the outline so we avoid
+ /// building them twice as part of the non-outline build.
+ bool get hasBodyBeenBuilt;
+
+ /// Builds the body of this field using [initializer] as the initializer
+ /// expression.
+ void buildBody(Expression initializer);
+
+ /// Builds the field initializers for each field used to encode this field
+ /// using the [fileOffset] for the created nodes and [value] as the initial
+ /// field value.
+ List<Initializer> buildInitializer(int fileOffset, Expression value,
+ {bool isSynthetic});
bool get isEligibleForInference;
DartType get builtType;
+
+ DartType inferType();
+
+ DartType fieldType;
}
-class FieldBuilderImpl extends MemberBuilderImpl implements FieldBuilder {
+class SourceFieldBuilder extends MemberBuilderImpl implements FieldBuilder {
@override
final String name;
@override
final int modifiers;
- @override
- final Field field;
+ FieldEncoding _fieldEncoding;
@override
final List<MetadataBuilder> metadata;
@@ -90,14 +107,38 @@
bool hadTypesInferred = false;
- FieldBuilderImpl(this.metadata, this.type, this.name, this.modifiers,
- Builder compilationUnit, int charOffset, int charEndOffset)
- : field = new Field(null, fileUri: compilationUnit?.fileUri)
- ..fileOffset = charOffset
- ..fileEndOffset = charEndOffset,
- super(compilationUnit, charOffset);
+ bool hasBodyBeenBuilt = false;
- Member get member => field;
+ SourceFieldBuilder(this.metadata, this.type, this.name, this.modifiers,
+ SourceLibraryBuilder libraryBuilder, int charOffset, int charEndOffset)
+ : super(libraryBuilder, charOffset) {
+ Uri fileUri = libraryBuilder?.fileUri;
+ if (isLate &&
+ !libraryBuilder.loader.target.backendTarget.supportsLateFields) {
+ if (hasInitializer) {
+ if (isFinal) {
+ _fieldEncoding = new LateFinalFieldWithInitializerEncoding(
+ name, fileUri, charOffset, charEndOffset);
+ } else {
+ _fieldEncoding = new LateFieldWithInitializerEncoding(
+ name, fileUri, charOffset, charEndOffset);
+ }
+ } else {
+ if (isFinal) {
+ _fieldEncoding = new LateFinalFieldWithoutInitializerEncoding(
+ name, fileUri, charOffset, charEndOffset);
+ } else {
+ _fieldEncoding = new LateFieldWithoutInitializerEncoding(
+ name, fileUri, charOffset, charEndOffset);
+ }
+ }
+ } else {
+ _fieldEncoding =
+ new RegularFieldEncoding(fileUri, charOffset, charEndOffset);
+ }
+ }
+
+ Member get member => _fieldEncoding.field;
String get debugName => "FieldBuilder";
@@ -112,12 +153,26 @@
@override
bool get hasInitializer => (modifiers & hasInitializerMask) != 0;
- void set initializer(Expression value) {
- if (!hasInitializer && value is! NullLiteral && !isConst && !isFinal) {
+ @override
+ void buildBody(Expression initializer) {
+ assert(!hasBodyBeenBuilt);
+ hasBodyBeenBuilt = true;
+ if (!hasInitializer &&
+ initializer != null &&
+ initializer is! NullLiteral &&
+ !isConst &&
+ !isFinal) {
internalProblem(
messageInternalProblemAlreadyInitialized, charOffset, fileUri);
}
- field.initializer = value..parent = field;
+ _fieldEncoding.createBodies(initializer);
+ }
+
+ @override
+ List<Initializer> buildInitializer(int fileOffset, Expression value,
+ {bool isSynthetic}) {
+ return _fieldEncoding.createInitializer(fileOffset, value,
+ isSynthetic: isSynthetic);
}
bool get isEligibleForInference {
@@ -137,81 +192,38 @@
}
@override
- Member get readTarget => field;
+ Field get field => _fieldEncoding.field;
@override
- Member get writeTarget => isAssignable ? field : null;
+ Member get readTarget => _fieldEncoding.readTarget;
@override
- Member get invokeTarget => field;
+ Member get writeTarget {
+ return isAssignable ? _fieldEncoding.writeTarget : null;
+ }
+
+ @override
+ Member get invokeTarget => readTarget;
@override
void buildMembers(
LibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
- Member member = build(library);
- f(
- member,
- isExtensionMember
- ? BuiltMemberKind.ExtensionField
- : BuiltMemberKind.Field);
+ build(library);
+ _fieldEncoding.registerMembers(library, this, f);
}
- Field build(SourceLibraryBuilder libraryBuilder) {
- field
- ..isCovariant = isCovariant
- ..isFinal = isFinal
- ..isConst = isConst
- ..isLate = isLate;
- if (isExtensionMember) {
- ExtensionBuilder extension = parent;
- field.name = new Name('${extension.name}|$name', libraryBuilder.library);
- field
- ..hasImplicitGetter = false
- ..hasImplicitSetter = false
- ..isStatic = true
- ..isExtensionMember = true;
- } else {
- // TODO(johnniwinther): How can the name already have been computed.
- field.name ??= new Name(name, libraryBuilder.library);
- bool isInstanceMember = !isStatic && !isTopLevel;
- field
- ..hasImplicitGetter = isInstanceMember
- ..hasImplicitSetter = isInstanceMember && !isConst && !isFinal
- ..isStatic = !isInstanceMember
- ..isExtensionMember = false;
- }
+ void build(SourceLibraryBuilder libraryBuilder) {
if (type != null) {
- field.type = type.build(libraryBuilder);
-
- if (!isFinal && !isConst) {
- IncludesTypeParametersNonCovariantly needsCheckVisitor;
- if (parent is ClassBuilder) {
- ClassBuilder enclosingClassBuilder = parent;
- Class enclosingClass = enclosingClassBuilder.cls;
- if (enclosingClass.typeParameters.isNotEmpty) {
- needsCheckVisitor = new IncludesTypeParametersNonCovariantly(
- enclosingClass.typeParameters,
- // We are checking the field type as if it is the type of the
- // parameter of the implicit setter and this is a contravariant
- // position.
- initialVariance: Variance.contravariant);
- }
- }
- if (needsCheckVisitor != null) {
- if (field.type.accept(needsCheckVisitor)) {
- field.isGenericCovariantImpl = true;
- }
- }
- }
+ fieldType = type.build(libraryBuilder);
}
- return field;
+ _fieldEncoding.build(libraryBuilder, this);
}
@override
void buildOutlineExpressions(LibraryBuilder library) {
ClassBuilder classBuilder = isClassMember ? parent : null;
MetadataBuilder.buildAnnotations(
- field, metadata, library, classBuilder, this);
+ _fieldEncoding.field, metadata, library, classBuilder, this);
// For modular compilation we need to include initializers of all const
// fields and all non-static final fields in classes with const constructors
@@ -228,31 +240,60 @@
library, classBuilder, this, scope, fileUri);
bodyBuilder.constantContext =
isConst ? ConstantContext.inferred : ConstantContext.required;
- initializer = bodyBuilder.typeInferrer?.inferFieldInitializer(bodyBuilder,
- field.type, bodyBuilder.parseFieldInitializer(constInitializerToken));
- if (library.loader is SourceLoader) {
+ Expression initializer = bodyBuilder.typeInferrer?.inferFieldInitializer(
+ bodyBuilder,
+ fieldType,
+ bodyBuilder.parseFieldInitializer(constInitializerToken));
+ if (library.loader is SourceLoader &&
+ (bodyBuilder.transformSetLiterals ||
+ bodyBuilder.transformCollections)) {
+ // Wrap the initializer in a temporary parent expression; the
+ // transformations need a parent relation.
+ Not wrapper = new Not(initializer);
SourceLoader loader = library.loader;
- loader.transformPostInference(field, bodyBuilder.transformSetLiterals,
- bodyBuilder.transformCollections);
+ loader.transformPostInference(wrapper, bodyBuilder.transformSetLiterals,
+ bodyBuilder.transformCollections, library.library);
+ initializer = wrapper.operand;
}
+ buildBody(initializer);
bodyBuilder.resolveRedirectingFactoryTargets();
}
constInitializerToken = null;
}
- @override
- void inferType() {
- SourceLibraryBuilder library = this.library;
- if (field.type is! ImplicitFieldType) {
- // We have already inferred a type.
- return;
+ DartType get fieldType => _fieldEncoding.type;
+
+ void set fieldType(DartType value) {
+ _fieldEncoding.type = value;
+ if (!isFinal && !isConst && parent is ClassBuilder) {
+ ClassBuilder enclosingClassBuilder = parent;
+ Class enclosingClass = enclosingClassBuilder.cls;
+ if (enclosingClass.typeParameters.isNotEmpty) {
+ IncludesTypeParametersNonCovariantly needsCheckVisitor =
+ new IncludesTypeParametersNonCovariantly(
+ enclosingClass.typeParameters,
+ // We are checking the field type as if it is the type of the
+ // parameter of the implicit setter and this is a contravariant
+ // position.
+ initialVariance: Variance.contravariant);
+ if (value.accept(needsCheckVisitor)) {
+ _fieldEncoding.setGenericCovariantImpl();
+ }
+ }
}
- ImplicitFieldType type = field.type;
- if (type.memberBuilder != this) {
+ }
+
+ @override
+ DartType inferType() {
+ SourceLibraryBuilder library = this.library;
+ if (fieldType is! ImplicitFieldType) {
+ // We have already inferred a type.
+ return fieldType;
+ }
+ ImplicitFieldType type = fieldType;
+ if (type.fieldBuilder != this) {
// The implicit type was inherited.
- FieldBuilder other = type.memberBuilder;
- other.inferCopiedType(field);
- return;
+ return fieldType = type.inferType();
}
if (type.isStarted) {
library.addProblem(
@@ -260,30 +301,34 @@
charOffset,
name.length,
fileUri);
- field.type = const InvalidType();
- return;
+ return fieldType = const InvalidType();
}
type.isStarted = true;
+ InterfaceType enclosingClassThisType = field.enclosingClass == null
+ ? null
+ : library.loader.typeInferenceEngine.coreTypes.thisInterfaceType(
+ field.enclosingClass, field.enclosingLibrary.nonNullable);
TypeInferrerImpl typeInferrer = library.loader.typeInferenceEngine
- .createTopLevelTypeInferrer(fileUri, field.enclosingClass?.thisType,
- library, dataForTesting?.inferenceData);
+ .createTopLevelTypeInferrer(fileUri, enclosingClassThisType, library,
+ dataForTesting?.inferenceData);
BodyBuilder bodyBuilder =
library.loader.createBodyBuilderForField(this, typeInferrer);
bodyBuilder.constantContext =
isConst ? ConstantContext.inferred : ConstantContext.none;
- initializer = bodyBuilder.parseFieldInitializer(type.initializerToken);
+ Expression initializer =
+ bodyBuilder.parseFieldInitializer(type.initializerToken);
type.initializerToken = null;
ExpressionInferenceResult result = typeInferrer.inferExpression(
- field.initializer, const UnknownType(), true,
+ initializer, const UnknownType(), true,
isVoidAllowed: true);
DartType inferredType =
typeInferrer.inferDeclarationType(result.inferredType);
- if (field.type is ImplicitFieldType) {
- // `field.type` may have changed if a circularity was detected when
+ if (fieldType is ImplicitFieldType) {
+ // `fieldType` may have changed if a circularity was detected when
// [inferredType] was computed.
- field.type = inferredType;
+ fieldType = inferredType;
IncludesTypeParametersNonCovariantly needsCheckVisitor;
if (parent is ClassBuilder) {
@@ -299,24 +344,543 @@
}
}
if (needsCheckVisitor != null) {
- if (field.type.accept(needsCheckVisitor)) {
+ if (fieldType.accept(needsCheckVisitor)) {
field.isGenericCovariantImpl = true;
}
}
}
-
- // The following is a hack. The outline should contain the compiled
- // initializers, however, as top-level inference is subtly different from
- // we need to compile the field initializer again when everything else is
- // compiled.
- field.initializer = null;
+ return fieldType;
}
- void inferCopiedType(Field other) {
- inferType();
- other.type = field.type;
- other.initializer = null;
+ DartType get builtType => fieldType;
+
+ @override
+ List<ClassMember> get localMembers => _fieldEncoding.getLocalMembers(this);
+
+ @override
+ List<ClassMember> get localSetters => _fieldEncoding.getLocalSetters(this);
+}
+
+/// Strategy pattern for creating different encodings of a declared field.
+///
+/// This is used to provide lowerings for late fields using synthesized getters
+/// and setters.
+abstract class FieldEncoding {
+ /// The type of the declared field.
+ DartType type;
+
+ /// Creates the bodies needed for the field encoding using [initializer] as
+ /// the declared initializer expression.
+ ///
+ /// This method is not called for fields in outlines unless their are constant
+ /// or part of a const constructor.
+ void createBodies(Expression initializer);
+
+ List<Initializer> createInitializer(int fileOffset, Expression value,
+ {bool isSynthetic});
+
+ /// Registers that the (implicit) setter associated with this field needs to
+ /// contain a runtime type check to deal with generic covariance.
+ void setGenericCovariantImpl();
+
+ /// Returns the field that holds the field value at runtime.
+ Field get field;
+
+ /// Returns the member used to read the field value.
+ Member get readTarget;
+
+ /// Returns the member used to write to the field.
+ Member get writeTarget;
+
+ /// Creates the members necessary for this field encoding.
+ ///
+ /// This method is called for both outline and full compilation so the created
+ /// members should be without body. The member bodies are created through
+ /// [createBodies].
+ void build(
+ SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder);
+
+ /// Calls [f] for each member needed for this field encoding.
+ void registerMembers(
+ SourceLibraryBuilder library,
+ SourceFieldBuilder fieldBuilder,
+ void Function(Member, BuiltMemberKind) f);
+
+ List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder);
+
+ List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder);
+}
+
+class RegularFieldEncoding implements FieldEncoding {
+ Field _field;
+
+ RegularFieldEncoding(Uri fileUri, int charOffset, int charEndOffset) {
+ _field = new Field(null, fileUri: fileUri)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset;
}
- DartType get builtType => field.type;
+ @override
+ DartType get type => _field.type;
+
+ @override
+ void set type(DartType value) {
+ _field.type = value;
+ }
+
+ @override
+ void createBodies(Expression initializer) {
+ if (initializer != null) {
+ _field.initializer = initializer..parent = _field;
+ }
+ }
+
+ @override
+ List<Initializer> createInitializer(int fileOffset, Expression value,
+ {bool isSynthetic}) {
+ return <Initializer>[
+ new FieldInitializer(_field, value)
+ ..fileOffset = fileOffset
+ ..isSynthetic = isSynthetic
+ ];
+ }
+
+ @override
+ void build(
+ SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
+ _field
+ ..isCovariant = fieldBuilder.isCovariant
+ ..isFinal = fieldBuilder.isFinal
+ ..isConst = fieldBuilder.isConst;
+ String fieldName;
+ if (fieldBuilder.isExtensionMember) {
+ ExtensionBuilder extension = fieldBuilder.parent;
+ fieldName = '${extension.name}|${fieldBuilder.name}';
+ _field
+ ..hasImplicitGetter = false
+ ..hasImplicitSetter = false
+ ..isStatic = true
+ ..isExtensionMember = true;
+ } else {
+ fieldName = fieldBuilder.name;
+ bool isInstanceMember =
+ !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
+ _field
+ ..hasImplicitGetter = isInstanceMember
+ ..hasImplicitSetter =
+ isInstanceMember && !fieldBuilder.isConst && !fieldBuilder.isFinal
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = false;
+ }
+ // TODO(johnniwinther): How can the name already have been computed?
+ _field.name ??= new Name(fieldName, libraryBuilder.library);
+ _field.isLate = fieldBuilder.isLate;
+ }
+
+ @override
+ void registerMembers(
+ SourceLibraryBuilder library,
+ SourceFieldBuilder fieldBuilder,
+ void Function(Member, BuiltMemberKind) f) {
+ f(
+ _field,
+ fieldBuilder.isExtensionMember
+ ? BuiltMemberKind.ExtensionField
+ : BuiltMemberKind.Field);
+ }
+
+ @override
+ void setGenericCovariantImpl() {
+ _field.isGenericCovariantImpl = true;
+ }
+
+ @override
+ Field get field => _field;
+
+ @override
+ Member get readTarget => _field;
+
+ @override
+ Member get writeTarget => _field;
+
+ @override
+ List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
+ <ClassMember>[fieldBuilder];
+
+ @override
+ List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
+ const <ClassMember>[];
+}
+
+abstract class AbstractLateFieldEncoding implements FieldEncoding {
+ final String name;
+ final int fileOffset;
+ DartType _type;
+ Field _field;
+ Field _lateIsSetField;
+ Procedure _lateGetter;
+ Procedure _lateSetter;
+
+ AbstractLateFieldEncoding(
+ this.name, Uri fileUri, int charOffset, int charEndOffset)
+ : fileOffset = charOffset {
+ _field = new Field(null, fileUri: fileUri)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset;
+ _lateIsSetField = new Field(null, fileUri: fileUri)
+ ..fileOffset = charOffset
+ ..fileEndOffset = charEndOffset;
+ _lateGetter = new Procedure(
+ null, ProcedureKind.Getter, new FunctionNode(null),
+ fileUri: fileUri)
+ ..fileOffset = charOffset;
+ _lateSetter = _createSetter(name, fileUri, charOffset);
+ }
+
+ @override
+ void createBodies(Expression initializer) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ _field.initializer = new NullLiteral()..parent = _field;
+ if (_type.isPotentiallyNullable) {
+ _lateIsSetField.initializer = new BoolLiteral(false)
+ ..parent = _lateIsSetField;
+ }
+ _lateGetter.function.body = _createGetterBody(name, initializer)
+ ..parent = _lateGetter.function;
+ if (_lateSetter != null) {
+ _lateSetter.function.body = _createSetterBody(
+ name, _lateSetter.function.positionalParameters.first)
+ ..parent = _lateSetter.function;
+ }
+ }
+
+ @override
+ List<Initializer> createInitializer(int fileOffset, Expression value,
+ {bool isSynthetic}) {
+ List<Initializer> initializers = <Initializer>[];
+ if (_lateIsSetField != null) {
+ initializers.add(new FieldInitializer(
+ _lateIsSetField, new BoolLiteral(true)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset
+ ..isSynthetic = isSynthetic);
+ }
+ initializers.add(new FieldInitializer(_field, value)
+ ..fileOffset = fileOffset
+ ..isSynthetic = isSynthetic);
+ return initializers;
+ }
+
+ Expression _createFieldGet(Field field) {
+ if (field.isStatic) {
+ return new StaticGet(field)..fileOffset = fileOffset;
+ } else {
+ return new PropertyGet(
+ new ThisExpression()..fileOffset = fileOffset, field.name, field)
+ ..fileOffset = fileOffset;
+ }
+ }
+
+ Expression _createFieldSet(Field field, Expression value) {
+ if (field.isStatic) {
+ return new StaticSet(field, value)..fileOffset = fileOffset;
+ } else {
+ return new PropertySet(new ThisExpression()..fileOffset = fileOffset,
+ field.name, value, field)
+ ..fileOffset = fileOffset;
+ }
+ }
+
+ Statement _createGetterBody(String name, Expression initializer);
+
+ Procedure _createSetter(String name, Uri fileUri, int charOffset) {
+ VariableDeclaration parameter = new VariableDeclaration(null);
+ return new Procedure(
+ null,
+ ProcedureKind.Setter,
+ new FunctionNode(null,
+ positionalParameters: [parameter], returnType: const VoidType()),
+ fileUri: fileUri)
+ ..fileOffset = charOffset;
+ }
+
+ Statement _createSetterBody(String name, VariableDeclaration parameter);
+
+ @override
+ DartType get type => _type;
+
+ @override
+ void set type(DartType value) {
+ assert(_type == null, "Type has already been computed for field $name.");
+ _type = value;
+ _field.type = value.withNullability(Nullability.nullable);
+ _lateGetter.function.returnType = value;
+ if (_lateSetter != null) {
+ _lateSetter.function.positionalParameters.single.type = value;
+ }
+ if (!_type.isPotentiallyNullable) {
+ // We only need the is-set field if the field is potentially nullable.
+ // Otherwise we use `null` to signal that the field is uninitialized.
+ _lateIsSetField = null;
+ }
+ }
+
+ @override
+ void setGenericCovariantImpl() {
+ // TODO(johnniwinther): Is this correct? Should the [_lateSetter] be
+ // annotated instead?
+ _field.isGenericCovariantImpl = true;
+ }
+
+ @override
+ Field get field => _field;
+
+ @override
+ Member get readTarget => _lateGetter;
+
+ @override
+ Member get writeTarget => _lateSetter;
+
+ @override
+ void build(
+ SourceLibraryBuilder libraryBuilder, SourceFieldBuilder fieldBuilder) {
+ _field..isCovariant = fieldBuilder.isCovariant;
+ String fieldName;
+ bool isInstanceMember;
+ bool isExtensionMember = fieldBuilder.isExtensionMember;
+ if (isExtensionMember) {
+ ExtensionBuilder extension = fieldBuilder.parent;
+ fieldName = '${extension.name}|${fieldBuilder.name}';
+ _field
+ ..hasImplicitGetter = false
+ ..hasImplicitSetter = false
+ ..isStatic = true
+ ..isExtensionMember = isExtensionMember;
+ isInstanceMember = false;
+ } else {
+ isInstanceMember = !fieldBuilder.isStatic && !fieldBuilder.isTopLevel;
+ fieldName = fieldBuilder.name;
+ _field
+ ..hasImplicitGetter = isInstanceMember
+ ..hasImplicitSetter = isInstanceMember
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = false;
+ }
+ _field.name ??= new Name('_#$fieldName', libraryBuilder.library);
+ if (_lateIsSetField != null) {
+ _lateIsSetField
+ ..name = new Name('_#$fieldName#isSet', libraryBuilder.library)
+ ..isStatic = !isInstanceMember
+ ..hasImplicitGetter = isInstanceMember
+ ..hasImplicitSetter = isInstanceMember
+ ..isStatic = _field.isStatic
+ ..isExtensionMember = isExtensionMember;
+ // TODO(johnniwinther): Provide access to a `bool` type here.
+ /*_lateIsSetField.type =
+ libraryBuilder.loader.coreTypes.boolNonNullableRawType;*/
+ }
+ _lateGetter
+ ..name = new Name(fieldName, libraryBuilder.library)
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember;
+ if (_lateSetter != null) {
+ _lateSetter
+ ..name = new Name(fieldName, libraryBuilder.library)
+ ..isStatic = !isInstanceMember
+ ..isExtensionMember = isExtensionMember;
+ }
+ }
+
+ @override
+ void registerMembers(
+ SourceLibraryBuilder library,
+ SourceFieldBuilder fieldBuilder,
+ void Function(Member, BuiltMemberKind) f) {
+ f(
+ _field,
+ fieldBuilder.isExtensionMember
+ ? BuiltMemberKind.ExtensionField
+ : BuiltMemberKind.Field);
+ if (_lateIsSetField != null) {
+ f(_lateIsSetField, BuiltMemberKind.LateIsSetField);
+ }
+ f(_lateGetter, BuiltMemberKind.LateGetter);
+ if (_lateSetter != null) {
+ f(_lateSetter, BuiltMemberKind.LateSetter);
+ }
+ }
+
+ @override
+ List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) {
+ List<ClassMember> list = <ClassMember>[
+ new _ClassMember(fieldBuilder, field),
+ new _ClassMember(fieldBuilder, _lateGetter)
+ ];
+ if (_lateIsSetField != null) {
+ list.add(new _ClassMember(fieldBuilder, _lateIsSetField));
+ }
+ return list;
+ }
+
+ @override
+ List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) {
+ return _lateSetter == null
+ ? const <ClassMember>[]
+ : <ClassMember>[new _ClassMember(fieldBuilder, _lateSetter)];
+ }
+}
+
+mixin NonFinalLate on AbstractLateFieldEncoding {
+ @override
+ Statement _createSetterBody(String name, VariableDeclaration parameter) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return late_lowering.createSetterBody(fileOffset, name, parameter, _type,
+ shouldReturnValue: false,
+ createVariableWrite: (Expression value) =>
+ _createFieldSet(_field, value),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField, value));
+ }
+}
+
+mixin LateWithInitializer on AbstractLateFieldEncoding {
+ @override
+ Statement _createGetterBody(String name, Expression initializer) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return late_lowering.createGetterWithInitializer(
+ fileOffset, name, _type, initializer,
+ createVariableRead: () => _createFieldGet(_field),
+ createVariableWrite: (Expression value) =>
+ _createFieldSet(_field, value),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField, value));
+ }
+
+ @override
+ void createBodies(Expression initializer) {
+ super.createBodies(initializer);
+ }
+}
+
+mixin LateWithoutInitializer on AbstractLateFieldEncoding {
+ @override
+ Statement _createGetterBody(String name, Expression initializer) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return late_lowering.createGetterBodyWithoutInitializer(
+ fileOffset, name, type, 'Field',
+ createVariableRead: () => _createFieldGet(_field),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField));
+ }
+}
+
+class LateFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
+ with NonFinalLate, LateWithoutInitializer {
+ LateFieldWithoutInitializerEncoding(
+ String name, Uri fileUri, int charOffset, int charEndOffset)
+ : super(name, fileUri, charOffset, charEndOffset);
+}
+
+class LateFieldWithInitializerEncoding extends AbstractLateFieldEncoding
+ with NonFinalLate, LateWithInitializer {
+ LateFieldWithInitializerEncoding(
+ String name, Uri fileUri, int charOffset, int charEndOffset)
+ : super(name, fileUri, charOffset, charEndOffset);
+}
+
+class LateFinalFieldWithoutInitializerEncoding extends AbstractLateFieldEncoding
+ with LateWithoutInitializer {
+ LateFinalFieldWithoutInitializerEncoding(
+ String name, Uri fileUri, int charOffset, int charEndOffset)
+ : super(name, fileUri, charOffset, charEndOffset);
+
+ @override
+ Statement _createSetterBody(String name, VariableDeclaration parameter) {
+ assert(_type != null, "Type has not been computed for field $name.");
+ return late_lowering.createSetterBodyFinal(
+ fileOffset, name, parameter, type, 'Field',
+ shouldReturnValue: false,
+ createVariableRead: () => _createFieldGet(_field),
+ createVariableWrite: (Expression value) =>
+ _createFieldSet(_field, value),
+ createIsSetRead: () => _createFieldGet(_lateIsSetField),
+ createIsSetWrite: (Expression value) =>
+ _createFieldSet(_lateIsSetField, value));
+ }
+}
+
+class LateFinalFieldWithInitializerEncoding extends AbstractLateFieldEncoding
+ with LateWithInitializer {
+ LateFinalFieldWithInitializerEncoding(
+ String name, Uri fileUri, int charOffset, int charEndOffset)
+ : super(name, fileUri, charOffset, charEndOffset);
+
+ @override
+ Procedure _createSetter(String name, Uri fileUri, int charOffset) => null;
+
+ @override
+ Statement _createSetterBody(String name, VariableDeclaration parameter) =>
+ null;
+}
+
+class _ClassMember implements ClassMember {
+ final SourceFieldBuilder fieldBuilder;
+
+ @override
+ final Member member;
+
+ _ClassMember(this.fieldBuilder, this.member);
+
+ @override
+ ClassBuilder get classBuilder => fieldBuilder.classBuilder;
+
+ @override
+ bool get isDuplicate => fieldBuilder.isDuplicate;
+
+ @override
+ bool get isStatic => fieldBuilder.isStatic;
+
+ @override
+ bool get isField => member is Field;
+
+ @override
+ bool get isAssignable {
+ Member field = member;
+ return field is Field && field.hasSetter;
+ }
+
+ @override
+ bool get isSetter {
+ Member procedure = member;
+ return procedure is Procedure && procedure.kind == ProcedureKind.Setter;
+ }
+
+ @override
+ bool get isGetter {
+ Member procedure = member;
+ return procedure is Procedure && procedure.kind == ProcedureKind.Getter;
+ }
+
+ @override
+ bool get isFinal {
+ Member field = member;
+ return field is Field && field.isFinal;
+ }
+
+ @override
+ bool get isConst {
+ Member field = member;
+ return field is Field && field.isConst;
+ }
+
+ @override
+ String get fullNameForErrors => fieldBuilder.fullNameForErrors;
+
+ @override
+ Uri get fileUri => fieldBuilder.fileUri;
+
+ @override
+ int get charOffset => fieldBuilder.charOffset;
+
+ @override
+ String toString() => '_ClassMember($fieldBuilder,$member)';
}
diff --git a/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
index 3bbc2f1..8d18032 100644
--- a/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
@@ -28,7 +28,7 @@
return buffer;
}
- DartType build(LibraryBuilder library) => type;
+ DartType build(LibraryBuilder library, [TypedefType origin]) => type;
Supertype buildSupertype(
LibraryBuilder library, int charOffset, Uri fileUri) {
diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
index b85d421..14cc3ac 100644
--- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
@@ -29,7 +29,7 @@
import '../kernel/body_builder.dart' show BodyBuilder;
-import '../kernel/kernel_shadow_ast.dart' show VariableDeclarationImpl;
+import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
import 'builder.dart';
import 'class_builder.dart';
@@ -67,6 +67,8 @@
/// [buildOutlineExpressions].
Token initializerToken;
+ bool initializerWasInferred = false;
+
FormalParameterBuilder(this.metadata, this.modifiers, this.type, this.name,
LibraryBuilder compilationUnit, int charOffset,
[Uri fileUri])
@@ -174,6 +176,7 @@
.createBodyBuilderForOutlineExpression(
library, classBuilder, this, scope, fileUri);
bodyBuilder.constantContext = ConstantContext.required;
+ assert(!initializerWasInferred);
Expression initializer =
bodyBuilder.parseFieldInitializer(initializerToken);
initializer = bodyBuilder.typeInferrer
@@ -181,9 +184,13 @@
variable.initializer = initializer..parent = variable;
if (library.loader is SourceLoader) {
SourceLoader loader = library.loader;
- loader.transformPostInference(variable,
- bodyBuilder.transformSetLiterals, bodyBuilder.transformCollections);
+ loader.transformPostInference(
+ variable,
+ bodyBuilder.transformSetLiterals,
+ bodyBuilder.transformCollections,
+ library.library);
}
+ initializerWasInferred = true;
bodyBuilder.resolveRedirectingFactoryTargets();
}
initializerToken = null;
diff --git a/pkg/front_end/lib/src/fasta/builder/function_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
index bd2d60d..15d3f43 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -11,10 +11,11 @@
import 'package:kernel/type_algebra.dart';
+import '../identifiers.dart';
import '../scope.dart';
-import '../kernel/kernel_shadow_ast.dart' show VariableDeclarationImpl;
-
+import '../kernel/class_hierarchy_builder.dart' show ClassMember;
+import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
import '../loader.dart' show Loader;
@@ -87,7 +88,7 @@
/// to support generic methods.
Scope computeTypeParameterScope(Scope parent);
- FormalParameterBuilder getFormal(String name);
+ FormalParameterBuilder getFormal(Identifier identifier);
String get nativeMethodName;
@@ -274,11 +275,16 @@
}
@override
- FormalParameterBuilder getFormal(String name) {
+ FormalParameterBuilder getFormal(Identifier identifier) {
if (formals != null) {
for (FormalParameterBuilder formal in formals) {
- if (formal.name == name) return formal;
+ if (formal.name == identifier.name &&
+ formal.charOffset == identifier.charOffset) {
+ return formal;
+ }
}
+ // If we have any formals we should find the one we're looking for.
+ assert(false, "$identifier not found in $formals");
}
return null;
}
@@ -531,4 +537,12 @@
messagePatchDeclarationOrigin.withLocation(fileUri, charOffset, noLength)
]);
}
+
+ @override
+ List<ClassMember> get localMembers =>
+ isSetter ? const <ClassMember>[] : <ClassMember>[this];
+
+ @override
+ List<ClassMember> get localSetters =>
+ isSetter ? <ClassMember>[this] : const <ClassMember>[];
}
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 6e0219e..5e5a6d0 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -55,9 +55,19 @@
void buildOutlineExpressions(LibraryBuilder library);
- void inferType();
+ /// Returns the [ClassMember]s for the non-setter members created for this
+ /// member builder.
+ ///
+ /// This is normally the member itself, if not a setter, but for instance for
+ /// lowered late fields this can be synthesized members.
+ List<ClassMember> get localMembers;
- void inferCopiedType(covariant Object other);
+ /// Returns the [ClassMember]s for the setters created for this member
+ /// builder.
+ ///
+ /// This is normally the member itself, if a setter, but for instance
+ /// lowered late fields this can be synthesized setters.
+ List<ClassMember> get localSetters;
}
abstract class MemberBuilderImpl extends ModifierBuilderImpl
@@ -132,14 +142,6 @@
String get fullNameForErrors => name;
@override
- void inferType() => unsupported("inferType", charOffset, fileUri);
-
- @override
- void inferCopiedType(covariant Object other) {
- unsupported("inferType", charOffset, fileUri);
- }
-
- @override
ClassBuilder get classBuilder => parent is ClassBuilder ? parent : null;
}
@@ -154,6 +156,9 @@
ExtensionSetter,
ExtensionOperator,
ExtensionTearOff,
+ LateIsSetField,
+ LateGetter,
+ LateSetter,
}
class MemberDataForTesting {
diff --git a/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart b/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
index a9a572d..4387c8e 100644
--- a/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
@@ -4,7 +4,7 @@
library fasta.mixin_application_builder;
-import 'package:kernel/ast.dart' show InterfaceType, Supertype;
+import 'package:kernel/ast.dart' show InterfaceType, Supertype, TypedefType;
import '../problems.dart' show unsupported;
@@ -43,7 +43,7 @@
}
@override
- InterfaceType build(LibraryBuilder library) {
+ InterfaceType build(LibraryBuilder library, [TypedefType origin]) {
int charOffset = -1; // TODO(ahe): Provide these.
Uri fileUri = null; // TODO(ahe): Provide these.
return unsupported("build", charOffset, fileUri);
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index a653514..8991ca3 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -6,7 +6,7 @@
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-import 'package:kernel/ast.dart' show DartType, Supertype;
+import 'package:kernel/ast.dart' show DartType, Supertype, TypedefType;
import '../fasta_codes.dart'
show
@@ -204,7 +204,8 @@
return null;
}
- DartType build(LibraryBuilder library) {
+ // TODO(johnniwinther): Store [origin] on the built type.
+ DartType build(LibraryBuilder library, [TypedefType origin]) {
assert(declaration != null, "Declaration has not been resolved on $this.");
return declaration.buildType(library, nullabilityBuilder, arguments);
}
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index 766bb6d..dc46cb5 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -321,7 +321,8 @@
TypeParameter newTypeParameter = new TypeParameter(typeParameter.name);
typeParameters.add(newTypeParameter);
typeArguments.add(substitutionMap[typeParameter] =
- new TypeParameterType(newTypeParameter, Nullability.legacy));
+ new TypeParameterType.forAlphaRenaming(
+ typeParameter, newTypeParameter));
}
List<TypeParameter> tearOffTypeParameters = <TypeParameter>[];
@@ -536,8 +537,9 @@
if (function.typeParameters != null) {
Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
for (int i = 0; i < function.typeParameters.length; i++) {
- substitution[function.typeParameters[i]] = new TypeParameterType(
- actualOrigin.function.typeParameters[i], Nullability.legacy);
+ substitution[function.typeParameters[i]] =
+ new TypeParameterType.withDefaultNullabilityForLibrary(
+ actualOrigin.function.typeParameters[i], library.library);
}
List<DartType> newTypeArguments =
new List<DartType>(typeArguments.length);
diff --git a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
index c284797..7b36c75 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
@@ -4,16 +4,19 @@
library fasta.function_type_alias_builder;
+import 'package:front_end/src/fasta/builder/fixed_type_builder.dart';
+import 'package:front_end/src/fasta/builder/named_type_builder.dart';
import 'package:kernel/ast.dart'
show
DartType,
DynamicType,
- FunctionType,
InvalidType,
Nullability,
TypeParameter,
Typedef,
- VariableDeclaration;
+ TypedefType,
+ VariableDeclaration,
+ getAsTypeArguments;
import 'package:kernel/type_algebra.dart'
show FreshTypeParameters, getFreshTypeParameters, substitute;
@@ -86,6 +89,8 @@
}
}
}
+ } else if (type is NamedTypeBuilder || type is FixedTypeBuilder) {
+ // No error, but also no additional setup work.
} else if (type != null) {
unhandled("${type.fullNameForErrors}", "build", charOffset, fileUri);
}
@@ -93,6 +98,38 @@
return typedef;
}
+ TypedefType thisTypedefType(Typedef typedef, LibraryBuilder clientLibrary) {
+ // At this point the bounds of `typedef.typeParameters` may not be assigned
+ // yet, so [getAsTypeArguments] may crash trying to compute the nullability
+ // of the created types from the bounds. To avoid that, we use "dynamic"
+ // for the bound of all boundless variables and add them to the list for
+ // being recomputed later, when the bounds are assigned.
+ List<DartType> bounds =
+ new List<DartType>.filled(typedef.typeParameters.length, null);
+ for (int i = 0; i < bounds.length; ++i) {
+ bounds[i] = typedef.typeParameters[i].bound;
+ if (bounds[i] == null) {
+ typedef.typeParameters[i].bound = const DynamicType();
+ }
+ }
+ List<DartType> asTypeArguments =
+ getAsTypeArguments(typedef.typeParameters, clientLibrary.library);
+ TypedefType result =
+ new TypedefType(typedef, clientLibrary.nonNullable, asTypeArguments);
+ for (int i = 0; i < bounds.length; ++i) {
+ if (bounds[i] == null) {
+ // If the bound is not assigned yet, put the corresponding
+ // type-parameter type into the list for the nullability re-computation.
+ // At this point, [parent] should be a [SourceLibraryBuilder] because
+ // otherwise it's a compiled library loaded from a dill file, and the
+ // bounds should have been assigned.
+ SourceLibraryBuilder parentLibrary = parent;
+ parentLibrary.pendingNullabilities.add(asTypeArguments[i]);
+ }
+ }
+ return result;
+ }
+
DartType buildThisType(LibraryBuilder library) {
if (thisType != null) {
if (identical(thisType, cyclicTypeAliasMarker)) {
@@ -107,8 +144,9 @@
// instance of InvalidType that isn't identical to `const InvalidType()`.
thisType = cyclicTypeAliasMarker;
TypeBuilder type = this.type;
- if (type is FunctionTypeBuilder) {
- FunctionType builtType = type?.build(library, typedef.thisType);
+ if (type != null) {
+ DartType builtType =
+ type.build(library, thisTypedefType(typedef, library));
if (builtType != null) {
if (typeVariables != null) {
for (TypeVariableBuilder tv in typeVariables) {
@@ -120,12 +158,8 @@
} else {
return thisType = const InvalidType();
}
- } else if (type == null) {
- return thisType = const InvalidType();
- } else {
- return unhandled(
- "${type.fullNameForErrors}", "buildThisType", charOffset, fileUri);
}
+ return thisType = const InvalidType();
}
/// [arguments] have already been built.
@@ -133,7 +167,7 @@
Nullability nullability, List<DartType> arguments) {
DartType thisType = buildThisType(library);
if (const DynamicType() == thisType) return thisType;
- FunctionType result = thisType.withNullability(nullability);
+ DartType result = thisType.withNullability(nullability);
if (typedef.typeParameters.isEmpty && arguments == null) return result;
Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{};
for (int i = 0; i < typedef.typeParameters.length; i++) {
diff --git a/pkg/front_end/lib/src/fasta/builder/type_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
index 7a8440e..f365eb2 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
@@ -4,7 +4,7 @@
library fasta.type_builder;
-import 'package:kernel/ast.dart' show DartType, Supertype;
+import 'package:kernel/ast.dart' show DartType, Supertype, TypedefType;
import '../scope.dart';
import 'library_builder.dart';
@@ -58,7 +58,7 @@
String get fullNameForErrors => "${printOn(new StringBuffer())}";
- DartType build(LibraryBuilder library);
+ DartType build(LibraryBuilder library, [TypedefType origin]);
Supertype buildSupertype(LibraryBuilder library, int charOffset, Uri fileUri);
diff --git a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
index 4e7da64..1e5c652 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
@@ -114,7 +114,6 @@
DartType buildTypesWithBuiltArguments(LibraryBuilder library,
Nullability nullability, List<DartType> arguments) {
- // TODO(dmitryas): Use [nullability].
if (arguments != null) {
int charOffset = -1; // TODO(ahe): Provide these.
Uri fileUri = null; // TODO(ahe): Provide these.
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
index d384778..a496c3f 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
@@ -11,6 +11,7 @@
import '../builder/member_builder.dart';
import '../builder/library_builder.dart';
+import '../kernel/class_hierarchy_builder.dart' show ClassMember;
import '../kernel/kernel_builder.dart'
show isRedirectingGenerativeConstructorImplementation;
@@ -127,6 +128,14 @@
LibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
throw new UnsupportedError('DillMemberBuilder.buildMembers');
}
+
+ @override
+ List<ClassMember> get localMembers =>
+ isSetter ? const <ClassMember>[] : <ClassMember>[this];
+
+ @override
+ List<ClassMember> get localSetters =>
+ isSetter ? <ClassMember>[this] : const <ClassMember>[];
}
int computeModifiers(Member member) {
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_target.dart b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
index b79b11a..9c3ff9a 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_target.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_target.dart
@@ -72,4 +72,8 @@
libraryBuilders[library.importUri] =
new DillLibraryBuilder(library, loader);
}
+
+ void releaseAncillaryResources() {
+ libraryBuilders.clear();
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
index d9a60cb..2cd6217 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
@@ -1282,46 +1282,6 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
- String name,
- DartType _type,
- DartType
- _type2)> templateIntersectionTypeAsTypeArgument = const Template<
- Message Function(String name, DartType _type, DartType _type2)>(
- messageTemplate:
- r"""Can't infer a type for '#name', it can be either '#type' or '#type2'.""",
- tipTemplate:
- r"""Try adding a type argument selecting one of the options.""",
- withArguments: _withArgumentsIntersectionTypeAsTypeArgument);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, DartType _type, DartType _type2)>
- codeIntersectionTypeAsTypeArgument =
- const Code<Message Function(String name, DartType _type, DartType _type2)>(
- "IntersectionTypeAsTypeArgument",
- templateIntersectionTypeAsTypeArgument,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsIntersectionTypeAsTypeArgument(
- String name, DartType _type, DartType _type2) {
- if (name.isEmpty) throw 'No name provided';
- name = demangleMixinApplicationName(name);
- TypeLabeler labeler = new TypeLabeler();
- List<Object> typeParts = labeler.labelType(_type);
- List<Object> type2Parts = labeler.labelType(_type2);
- String type = typeParts.join();
- String type2 = type2Parts.join();
- return new Message(codeIntersectionTypeAsTypeArgument,
- message:
- """Can't infer a type for '${name}', it can be either '${type}' or '${type2}'.""" +
- labeler.originMessages,
- tip: """Try adding a type argument selecting one of the options.""",
- arguments: {'name': name, 'type': _type, 'type2': _type2});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
- Message Function(
DartType _type,
DartType
_type2)> templateInvalidAssignment = const Template<
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index a184705..4ebcdbb 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -51,7 +51,9 @@
import '../api_prototype/memory_file_system.dart' show MemoryFileSystem;
import 'builder/builder.dart';
+
import 'builder/class_builder.dart';
+
import 'builder/library_builder.dart';
import 'builder_graph.dart' show BuilderGraph;
@@ -68,6 +70,8 @@
import 'util/error_reporter_file_copier.dart' show saveAsGzip;
+import 'util/textual_outline.dart' show textualOutline;
+
import 'fasta_codes.dart'
show
DiagnosticMessageFromJson,
@@ -80,7 +84,7 @@
import 'kernel/kernel_builder.dart' show ClassHierarchyBuilder;
-import 'kernel/kernel_shadow_ast.dart' show VariableDeclarationImpl;
+import 'kernel/internal_ast.dart' show VariableDeclarationImpl;
import 'kernel/kernel_target.dart' show KernelTarget;
@@ -120,6 +124,7 @@
new Map<Uri, List<DiagnosticMessageFromJson>>();
List<Component> modulesToLoad;
IncrementalSerializer incrementalSerializer;
+ bool useExperimentalInvalidation = false;
static final Uri debugExprUri =
new Uri(scheme: "org-dartlang-debug", path: "synthetic_debug_expression");
@@ -243,9 +248,107 @@
ClassHierarchy hierarchy = userCode?.loader?.hierarchy;
Set<LibraryBuilder> notReusedLibraries = new Set<LibraryBuilder>();
+ List<LibraryBuilder> directlyInvalidated = new List<LibraryBuilder>();
+ // TODO(jensj): Do something smarter than this.
+ List<bool> invalidatedBecauseOfPackageUpdate = new List<bool>();
List<LibraryBuilder> reusedLibraries = computeReusedLibraries(
invalidatedUris, uriTranslator,
- notReused: notReusedLibraries);
+ notReused: notReusedLibraries,
+ directlyInvalidated: directlyInvalidated,
+ invalidatedBecauseOfPackageUpdate: invalidatedBecauseOfPackageUpdate);
+
+ bool apiUnchanged = false;
+ List<SourceLibraryBuilder> rebuildBodies =
+ new List<SourceLibraryBuilder>();
+ Set<LibraryBuilder> originalNotReusedLibraries;
+ Set<Uri> missingSources = new Set<Uri>();
+ if (useExperimentalInvalidation &&
+ modulesToLoad == null &&
+ directlyInvalidated.isNotEmpty &&
+ invalidatedBecauseOfPackageUpdate.isEmpty) {
+ // Figure out if the file(s) have changed outline, or we can just
+ // rebuild the bodies. This (at least currently) only works for
+ // SourceLibraryBuilder.
+ apiUnchanged = true;
+ for (int i = 0; i < directlyInvalidated.length; i++) {
+ LibraryBuilder builder = directlyInvalidated[i];
+ if (builder is! SourceLibraryBuilder) {
+ apiUnchanged = false;
+ break;
+ }
+ List<int> previousSource =
+ CompilerContext.current.uriToSource[builder.fileUri].source;
+ if (previousSource == null || previousSource.isEmpty) {
+ apiUnchanged = false;
+ break;
+ }
+ String before = textualOutline(previousSource);
+ String now;
+ FileSystemEntity entity =
+ c.options.fileSystem.entityForUri(builder.fileUri);
+ if (await entity.exists()) {
+ now = textualOutline(await entity.readAsBytes());
+ }
+ if (before != now) {
+ apiUnchanged = false;
+ break;
+ }
+ // TODO(jensj): We should only do this when we're sure we're going to
+ // do it!
+ CompilerContext.current.uriToSource.remove(builder.fileUri);
+ missingSources.add(builder.fileUri);
+ LibraryBuilder partOfLibrary = builder.partOfLibrary;
+ if (partOfLibrary != null) {
+ if (partOfLibrary is! SourceLibraryBuilder) {
+ apiUnchanged = false;
+ break;
+ }
+ rebuildBodies.add(partOfLibrary);
+ } else {
+ rebuildBodies.add(builder);
+ }
+ }
+
+ if (apiUnchanged) {
+ // TODO(jensj): Check for mixins in a smarter and faster way.
+ for (LibraryBuilder builder in notReusedLibraries) {
+ if (missingSources.contains(builder.fileUri)) continue;
+ Library lib = builder.library;
+ for (Class c in lib.classes) {
+ if (!c.isAnonymousMixin && !c.isEliminatedMixin) continue;
+ for (Supertype supertype in c.implementedTypes) {
+ if (missingSources.contains(supertype.classNode.fileUri)) {
+ // This is probably a mixin from one of the libraries we want
+ // to rebuild only the body of.
+ apiUnchanged = false;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (apiUnchanged) {
+ originalNotReusedLibraries = new Set<LibraryBuilder>();
+ Set<Uri> seenUris = new Set<Uri>();
+ for (LibraryBuilder builder in notReusedLibraries) {
+ if (builder.isPart) continue;
+ if (builder.isPatch) continue;
+ if (!seenUris.add(builder.uri)) continue;
+ reusedLibraries.add(builder);
+ originalNotReusedLibraries.add(builder);
+ }
+ notReusedLibraries.clear();
+ for (int i = 0; i < rebuildBodies.length; i++) {
+ SourceLibraryBuilder builder = rebuildBodies[i];
+ builder.issueLexicalErrorsOnBodyBuild = true;
+ }
+ } else {
+ missingSources.clear();
+ rebuildBodies.clear();
+ }
+ }
+ recordRebuildBodiesCountForTesting(missingSources.length);
bool removedDillBuilders = false;
for (LibraryBuilder builder in notReusedLibraries) {
@@ -358,6 +461,18 @@
}
Component componentWithDill = await userCode.buildOutlines();
+ for (int i = 0; i < rebuildBodies.length; i++) {
+ SourceLibraryBuilder builder = rebuildBodies[i];
+ builder.loader = userCode.loader;
+ Library lib = builder.library;
+ lib.problemsAsJson = null;
+ // Remove component problems for libraries we don't reuse.
+ if (remainingComponentProblems.isNotEmpty) {
+ removeLibraryFromRemainingComponentProblems(lib, uriTranslator);
+ }
+ userCode.loader.libraries.add(lib);
+ }
+
// This is not the full component. It is the component consisting of all
// newly compiled libraries and all libraries loaded from .dill files or
// directly from components.
@@ -389,19 +504,35 @@
this.invalidatedUris.clear();
hasToCheckPackageUris = false;
userCodeOld?.loader?.releaseAncillaryResources();
- userCodeOld?.loader?.builders?.clear();
userCodeOld = null;
}
List<Library> compiledLibraries =
new List<Library>.from(userCode.loader.libraries);
+ Map<Uri, Source> uriToSource = componentWithDill?.uriToSource;
+ if (originalNotReusedLibraries != null) {
+ // Make sure "compiledLibraries" contains what it would have, had we not
+ // only re-done the bodies, but invalidated everything.
+ originalNotReusedLibraries.removeAll(rebuildBodies);
+ for (LibraryBuilder builder in originalNotReusedLibraries) {
+ compiledLibraries.add(builder.library);
+ }
+
+ // uriToSources are created in the outline stage which we skipped for
+ // some of the libraries.
+ for (Uri uri in missingSources) {
+ // TODO(jensj): KernelTargets "link" takes some "excludeSource"
+ // setting into account.
+ uriToSource[uri] = CompilerContext.current.uriToSource[uri];
+ }
+ }
+
Procedure mainMethod = componentWithDill == null
? data.userLoadedUriMain
: componentWithDill.mainMethod;
List<Library> outputLibraries;
Set<Library> allLibraries;
- Map<Uri, Source> uriToSource = componentWithDill?.uriToSource;
if (data.component != null || fullComponent) {
outputLibraries = computeTransitiveClosure(
compiledLibraries,
@@ -1011,7 +1142,9 @@
/// Internal method.
List<LibraryBuilder> computeReusedLibraries(
Set<Uri> invalidatedUris, UriTranslator uriTranslator,
- {Set<LibraryBuilder> notReused}) {
+ {Set<LibraryBuilder> notReused,
+ List<LibraryBuilder> directlyInvalidated,
+ List<bool> invalidatedBecauseOfPackageUpdate}) {
List<LibraryBuilder> result = <LibraryBuilder>[];
result.addAll(platformBuilders);
if (userCode == null && userBuilders == null) {
@@ -1042,6 +1175,7 @@
currentPackagesMap[packageName])) {
Uri newFileUri = uriTranslator.translate(importUri, false);
if (newFileUri != fileUri) {
+ invalidatedBecauseOfPackageUpdate?.add(true);
return true;
}
}
@@ -1091,6 +1225,11 @@
}
recordInvalidatedImportUrisForTesting(invalidatedImportUris);
+ if (directlyInvalidated != null) {
+ for (Uri uri in invalidatedImportUris) {
+ directlyInvalidated.add(builders[uri]);
+ }
+ }
BuilderGraph graph = new BuilderGraph(builders);
@@ -1169,6 +1308,9 @@
void recordInvalidatedImportUrisForTesting(List<Uri> uris) {}
/// Internal method.
+ void recordRebuildBodiesCountForTesting(int count) {}
+
+ /// Internal method.
void recordTemporaryFileForTesting(Uri uri) {}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 377f607..fd64898 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -140,7 +140,7 @@
import 'kernel_ast_api.dart';
-import 'kernel_shadow_ast.dart';
+import 'internal_ast.dart';
import 'kernel_builder.dart';
@@ -553,8 +553,8 @@
void inferAnnotations(TreeNode parent, List<Expression> annotations) {
if (annotations != null) {
typeInferrer?.inferMetadata(this, parent, annotations);
- libraryBuilder.loader.transformListPostInference(
- annotations, transformSetLiterals, transformCollections);
+ libraryBuilder.loader.transformListPostInference(annotations,
+ transformSetLiterals, transformCollections, libraryBuilder.library);
}
}
@@ -675,20 +675,33 @@
}
fields.add(fieldBuilder);
if (initializer != null) {
- if (fieldBuilder.next != null) {
+ if (fieldBuilder.isDuplicate) {
// Duplicate definition. The field might not be the correct one,
// so we skip inference of the initializer.
// Error reporting and recovery is handled elsewhere.
- } else if (fieldBuilder.field.initializer != null) {
+ } else if (fieldBuilder.hasBodyBeenBuilt) {
// The initializer was already compiled (e.g., if it appear in the
// outline, like constant field initializers) so we do not need to
// perform type inference or transformations.
} else {
- fieldBuilder.initializer = typeInferrer?.inferFieldInitializer(
+ initializer = typeInferrer?.inferFieldInitializer(
this, fieldBuilder.builtType, initializer);
- libraryBuilder.loader.transformPostInference(
- fieldBuilder.field, transformSetLiterals, transformCollections);
+
+ if (transformCollections || transformSetLiterals) {
+ // Wrap the initializer in a temporary parent expression; the
+ // transformations need a parent relation.
+ Not wrapper = new Not(initializer);
+ libraryBuilder.loader.transformPostInference(
+ wrapper,
+ transformSetLiterals,
+ transformCollections,
+ libraryBuilder.library);
+ initializer = wrapper.operand;
+ }
+ fieldBuilder.buildBody(initializer);
}
+ } else if (!fieldBuilder.hasBodyBeenBuilt) {
+ fieldBuilder.buildBody(null);
}
}
{
@@ -733,16 +746,18 @@
if (member.formals != null) {
for (FormalParameterBuilder formal in member.formals) {
if (formal.isInitializingFormal) {
- Initializer initializer;
+ List<Initializer> initializers;
if (member.isExternal) {
- initializer = buildInvalidInitializer(
- buildProblem(
- fasta.messageExternalConstructorWithFieldInitializers,
- formal.charOffset,
- formal.name.length),
- formal.charOffset);
+ initializers = <Initializer>[
+ buildInvalidInitializer(
+ buildProblem(
+ fasta.messageExternalConstructorWithFieldInitializers,
+ formal.charOffset,
+ formal.name.length),
+ formal.charOffset)
+ ];
} else {
- initializer = buildFieldInitializer(
+ initializers = buildFieldInitializer(
true,
formal.name,
formal.charOffset,
@@ -750,7 +765,9 @@
new VariableGet(formal.variable),
formalType: formal.variable.type);
}
- member.addInitializer(initializer, this);
+ for (Initializer initializer in initializers) {
+ member.addInitializer(initializer, this);
+ }
}
}
}
@@ -796,25 +813,33 @@
assert(!inInitializer);
final ModifierBuilder member = this.member;
Object node = pop();
- Initializer initializer;
+ List<Initializer> initializers;
if (node is Initializer) {
- initializer = node;
+ initializers = <Initializer>[node];
} else if (node is Generator) {
- initializer = node.buildFieldInitializer(initializedFields);
+ initializers = node.buildFieldInitializer(initializedFields);
} else if (node is ConstructorInvocation) {
- initializer = buildSuperInitializer(
- false, node.target, node.arguments, token.charOffset);
+ initializers = <Initializer>[
+ buildSuperInitializer(
+ false, node.target, node.arguments, token.charOffset)
+ ];
} else {
Expression value = toValue(node);
if (!forest.isThrow(node)) {
value =
wrapInProblem(value, fasta.messageExpectedAnInitializer, noLength);
}
- initializer = buildInvalidInitializer(node, token.charOffset);
+ initializers = <Initializer>[
+ buildInvalidInitializer(node, token.charOffset)
+ ];
}
- typeInferrer?.inferInitializer(this, initializer);
+ for (Initializer initializer in initializers) {
+ typeInferrer?.inferInitializer(this, initializer);
+ }
if (member is ConstructorBuilder && !member.isExternal) {
- member.addInitializer(initializer, this);
+ for (Initializer initializer in initializers) {
+ member.addInitializer(initializer, this);
+ }
} else {
addProblem(
fasta.templateInitializerOutsideConstructor
@@ -846,18 +871,24 @@
FormalParameterBuilder parameter = formals.parameters[i];
Expression initializer = parameter.variable.initializer;
if (parameter.isOptional || initializer != null) {
- if (parameter.isOptional) {
- initializer ??= forest.createNullLiteral(
- // TODO(ahe): Should store: originParameter.fileOffset
- // https://github.com/dart-lang/sdk/issues/32289
- noLocation);
+ if (!parameter.initializerWasInferred) {
+ parameter.initializerWasInferred = true;
+ if (parameter.isOptional) {
+ initializer ??= forest.createNullLiteral(
+ // TODO(ahe): Should store: originParameter.fileOffset
+ // https://github.com/dart-lang/sdk/issues/32289
+ noLocation);
+ }
+ VariableDeclaration originParameter = builder.getFormalParameter(i);
+ initializer = typeInferrer?.inferParameterInitializer(
+ this, initializer, originParameter.type);
+ originParameter.initializer = initializer..parent = originParameter;
+ libraryBuilder.loader.transformPostInference(
+ originParameter,
+ transformSetLiterals,
+ transformCollections,
+ libraryBuilder.library);
}
- VariableDeclaration originParameter = builder.getFormalParameter(i);
- initializer = typeInferrer?.inferParameterInitializer(
- this, initializer, originParameter.type);
- originParameter.initializer = initializer..parent = originParameter;
- libraryBuilder.loader.transformPostInference(
- originParameter, transformSetLiterals, transformCollections);
VariableDeclaration extensionTearOffParameter =
builder.getExtensionTearOffParameter(i);
@@ -869,16 +900,21 @@
libraryBuilder.loader.transformPostInference(
extensionTearOffParameter,
transformSetLiterals,
- transformCollections);
+ transformCollections,
+ libraryBuilder.library);
}
}
}
}
- typeInferrer?.inferFunctionBody(this, _computeReturnTypeContext(member),
- asyncModifier, builder.member.function, body);
if (body != null) {
- libraryBuilder.loader.transformPostInference(
- body, transformSetLiterals, transformCollections);
+ body = typeInferrer?.inferFunctionBody(
+ this,
+ _computeReturnTypeContext(member),
+ asyncModifier,
+ builder.member.function,
+ body);
+ libraryBuilder.loader.transformPostInference(body, transformSetLiterals,
+ transformCollections, libraryBuilder.library);
}
if (builder.returnType != null) {
@@ -1334,8 +1370,8 @@
constructor.initializers.add(initializer);
}
setParents(constructor.initializers, constructor);
- libraryBuilder.loader.transformListPostInference(
- constructor.initializers, transformSetLiterals, transformCollections);
+ libraryBuilder.loader.transformListPostInference(constructor.initializers,
+ transformSetLiterals, transformCollections, libraryBuilder.library);
if (constructor.function.body == null) {
/// >If a generative constructor c is not a redirecting constructor
/// >and no body is provided, then c implicitly has an empty body {}.
@@ -1481,7 +1517,8 @@
} else {
VariableDeclaration variable =
forest.createVariableDeclarationForValue(expression);
- push(new Cascade(variable)..fileOffset = expression.fileOffset);
+ push(new Cascade(variable, isNullAware: optional('?..', token))
+ ..fileOffset = expression.fileOffset);
push(_createReadOnlyVariableAccess(
variable, token, expression.fileOffset, null));
}
@@ -3151,8 +3188,10 @@
functionNestingLevel == 0 &&
memberKind != MemberKind.GeneralizedFunctionType) {
FunctionBuilder member = this.member;
- parameter = member.getFormal(name.name);
+ parameter = member.getFormal(name);
if (parameter == null) {
+ // This happens when the list of formals (originally) contains a
+ // ParserRecovery - then the popped list becomes null.
push(new ParserRecovery(nameToken.charOffset));
return;
}
@@ -3172,7 +3211,9 @@
initializer.fileOffset,
noLength);
} else {
- variable.initializer = initializer..parent = variable;
+ if (!parameter.initializerWasInferred) {
+ variable.initializer = initializer..parent = variable;
+ }
}
} else if (kind != FormalParameterKind.mandatory) {
variable.initializer ??= forest.createNullLiteral(noLocation)
@@ -3182,6 +3223,7 @@
if (functionNestingLevel == 0) {
inferAnnotations(variable, annotations);
}
+ variable.clearAnnotations();
for (Expression annotation in annotations) {
variable.addAnnotation(annotation);
}
@@ -3424,15 +3466,18 @@
debugEvent("IndexedExpression");
Expression index = popForValue();
Object receiver = pop();
+ bool isNullAware = optional('?.[', openSquareBracket);
if (receiver is Generator) {
- push(receiver.buildIndexedAccess(index, openSquareBracket));
+ push(receiver.buildIndexedAccess(index, openSquareBracket,
+ isNullAware: isNullAware));
} else if (receiver is Expression) {
- push(IndexedAccessGenerator.make(
- this, openSquareBracket, receiver, index));
+ push(IndexedAccessGenerator.make(this, openSquareBracket, receiver, index,
+ isNullAware: isNullAware));
} else {
assert(receiver is Initializer);
push(IndexedAccessGenerator.make(
- this, openSquareBracket, toValue(receiver), index));
+ this, openSquareBracket, toValue(receiver), index,
+ isNullAware: isNullAware));
}
}
@@ -3489,7 +3534,7 @@
Object generator = pop();
if (generator is Generator) {
push(new DelayedPostfixIncrement(
- this, token, generator, incrementOperator(token), null));
+ this, token, generator, incrementOperator(token)));
} else {
push(wrapInProblem(
toValue(generator), fasta.messageNotAnLvalue, noLength));
@@ -5245,22 +5290,26 @@
/// immediately enclosing class. It is a static warning if the static type of
/// _id_ is not a subtype of _Tid_."
@override
- Initializer buildFieldInitializer(bool isSynthetic, String name,
+ List<Initializer> buildFieldInitializer(bool isSynthetic, String name,
int fieldNameOffset, int assignmentOffset, Expression expression,
{DartType formalType}) {
Builder builder = declarationBuilder.lookupLocalMember(name);
if (builder?.next != null) {
// Duplicated name, already reported.
- return new LocalInitializer(new VariableDeclaration.forValue(buildProblem(
- fasta.templateDuplicatedDeclarationUse.withArguments(name),
- fieldNameOffset,
- name.length)))
- ..fileOffset = fieldNameOffset;
+ return <Initializer>[
+ new LocalInitializer(new VariableDeclaration.forValue(buildProblem(
+ fasta.templateDuplicatedDeclarationUse.withArguments(name),
+ fieldNameOffset,
+ name.length)))
+ ..fileOffset = fieldNameOffset
+ ];
} else if (builder is FieldBuilder && builder.isDeclarationInstanceMember) {
initializedFields ??= <String, int>{};
if (initializedFields.containsKey(name)) {
- return buildDuplicatedInitializer(builder.field, expression, name,
- assignmentOffset, initializedFields[name]);
+ return <Initializer>[
+ buildDuplicatedInitializer(builder.field, expression, name,
+ assignmentOffset, initializedFields[name])
+ ];
}
initializedFields[name] = assignmentOffset;
if (builder.isFinal && builder.hasInitializer) {
@@ -5283,12 +5332,14 @@
]),
constness: Constness.explicitNew,
charOffset: assignmentOffset);
- return new ShadowInvalidFieldInitializer(
- builder.field,
- expression,
- new VariableDeclaration.forValue(
- forest.createThrow(assignmentOffset, invocation)))
- ..fileOffset = assignmentOffset;
+ return <Initializer>[
+ new ShadowInvalidFieldInitializer(
+ builder.field,
+ expression,
+ new VariableDeclaration.forValue(
+ forest.createThrow(assignmentOffset, invocation)))
+ ..fileOffset = assignmentOffset
+ ];
} else {
if (formalType != null &&
!typeEnvironment.isSubtypeOf(formalType, builder.field.type,
@@ -5304,17 +5355,18 @@
.withLocation(builder.fileUri, builder.charOffset, noLength)
]);
}
- return new FieldInitializer(builder.field, expression)
- ..fileOffset = assignmentOffset
- ..isSynthetic = isSynthetic;
+ return builder.buildInitializer(assignmentOffset, expression,
+ isSynthetic: isSynthetic);
}
} else {
- return buildInvalidInitializer(
- buildProblem(
- fasta.templateInitializerForStaticField.withArguments(name),
- fieldNameOffset,
- name.length),
- fieldNameOffset);
+ return <Initializer>[
+ buildInvalidInitializer(
+ buildProblem(
+ fasta.templateInitializerForStaticField.withArguments(name),
+ fieldNameOffset,
+ name.length),
+ fieldNameOffset)
+ ];
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 76a4af6..a1798c4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -12,6 +12,7 @@
FunctionNode,
InterfaceType,
InvalidType,
+ Library,
Member,
Name,
Nullability,
@@ -159,7 +160,8 @@
if (typeParameterCount != 0) {
List<DartType> types = new List<DartType>(typeParameterCount);
for (int i = 0; i < typeParameterCount; i++) {
- types[i] = new TypeParameterType(aTypeParameters[i], Nullability.legacy);
+ types[i] = new TypeParameterType.forAlphaRenaming(
+ bTypeParameters[i], aTypeParameters[i]);
}
substitution = Substitution.fromPairs(bTypeParameters, types);
for (int i = 0; i < typeParameterCount; i++) {
@@ -659,8 +661,8 @@
}
List<DartType> types = new List<DartType>(typeParameterCount);
for (int i = 0; i < typeParameterCount; i++) {
- types[i] =
- new TypeParameterType(aTypeParameters[i], Nullability.legacy);
+ types[i] = new TypeParameterType.forAlphaRenaming(
+ bTypeParameters[i], aTypeParameters[i]);
}
substitution = Substitution.fromPairs(bTypeParameters, types);
for (int i = 0; i < typeParameterCount; i++) {
@@ -979,8 +981,10 @@
if (inheritedType is ImplicitFieldType) {
SourceLibraryBuilder library = classBuilder.library;
(library.implicitlyTypedFields ??= <FieldBuilder>[]).add(a);
+ a.fieldType = inheritedType.createAlias(a);
+ } else {
+ a.fieldType = inheritedType;
}
- a.field.type = inheritedType;
}
}
return result;
@@ -1204,14 +1208,23 @@
}
/// Members (excluding setters) declared in [cls].
- List<ClassMember> localMembers =
- new List<ClassMember>.from(scope.localMembers)
- ..sort(compareDeclarations);
+ List<ClassMember> localMembers = <ClassMember>[];
/// Setters declared in [cls].
- List<ClassMember> localSetters =
- new List<ClassMember>.from(scope.localSetters)
- ..sort(compareDeclarations);
+ List<ClassMember> localSetters = <ClassMember>[];
+
+ for (MemberBuilder memberBuilder in scope.localMembers) {
+ localMembers.addAll(memberBuilder.localMembers);
+ localSetters.addAll(memberBuilder.localSetters);
+ }
+
+ for (MemberBuilder memberBuilder in scope.localSetters) {
+ localMembers.addAll(memberBuilder.localMembers);
+ localSetters.addAll(memberBuilder.localSetters);
+ }
+
+ localMembers.sort(compareDeclarations);
+ localSetters.sort(compareDeclarations);
// Add implied setters from fields in [localMembers].
localSetters = mergeAccessors(localMembers, localSetters);
@@ -1677,8 +1690,8 @@
new BuilderMixinInferrer(
classBuilder,
hierarchy.coreTypes,
- new TypeBuilderConstraintGatherer(
- hierarchy, mixedInType.classNode.typeParameters))
+ new TypeBuilderConstraintGatherer(hierarchy,
+ mixedInType.classNode.typeParameters, cls.enclosingLibrary))
.infer(cls);
List<TypeBuilder> inferredArguments =
new List<TypeBuilder>(typeArguments.length);
@@ -1782,8 +1795,8 @@
return result..last = this;
}
- String toString([StringBuffer sb]) {
- sb ??= new StringBuffer();
+ String toString() {
+ StringBuffer sb = new StringBuffer();
sb
..write(classBuilder.fullNameForErrors)
..writeln(":");
@@ -1967,9 +1980,9 @@
with StandardBounds {
final ClassHierarchyBuilder hierarchy;
- TypeBuilderConstraintGatherer(
- this.hierarchy, Iterable<TypeParameter> typeParameters)
- : super.subclassing(typeParameters);
+ TypeBuilderConstraintGatherer(this.hierarchy,
+ Iterable<TypeParameter> typeParameters, Library currentLibrary)
+ : super.subclassing(typeParameters, currentLibrary);
@override
Class get objectClass => hierarchy.objectClass;
@@ -2071,7 +2084,9 @@
if (type != null) {
type = Substitution.fromInterfaceType(
hierarchy.getKernelTypeAsInstanceOf(
- classBuilder.cls.thisType, b.member.enclosingClass))
+ hierarchy.coreTypes.thisInterfaceType(
+ classBuilder.cls, classBuilder.library.nonNullable),
+ b.member.enclosingClass))
.substituteType(type);
if (!a.hadTypesInferred || !b.isSetter) {
inferReturnType(
@@ -2093,7 +2108,9 @@
if (type != null) {
type = Substitution.fromInterfaceType(
hierarchy.getKernelTypeAsInstanceOf(
- classBuilder.cls.thisType, b.member.enclosingClass))
+ hierarchy.coreTypes.thisInterfaceType(
+ classBuilder.cls, classBuilder.library.nonNullable),
+ b.member.enclosingClass))
.substituteType(type);
if (!a.hadTypesInferred || !b.isGetter) {
inferParameterType(classBuilder, a, a.formals.single, type,
@@ -2117,22 +2134,24 @@
if (type != null) {
type = Substitution.fromInterfaceType(
hierarchy.getKernelTypeAsInstanceOf(
- classBuilder.cls.thisType, b.member.enclosingClass))
+ hierarchy.coreTypes.thisInterfaceType(
+ classBuilder.cls, classBuilder.library.nonNullable),
+ b.member.enclosingClass))
.substituteType(type);
- if (type != a.field.type) {
+ if (type != a.fieldType) {
if (a.hadTypesInferred) {
if (b.isSetter &&
(!impliesSetter(a) ||
- hierarchy.types.isSubtypeOfKernel(type, a.field.type,
+ hierarchy.types.isSubtypeOfKernel(type, a.fieldType,
SubtypeCheckMode.ignoringNullabilities))) {
- type = a.field.type;
+ type = a.fieldType;
} else {
reportCantInferFieldType(classBuilder, a);
type = const InvalidType();
}
}
debug?.log("Inferred type ${type} for ${fullName(a)}");
- a.field.type = type;
+ a.fieldType = type;
}
}
a.hadTypesInferred = true;
@@ -2320,7 +2339,8 @@
if (classBuilder.library is! SourceLibraryBuilder) {
return combinedMemberSignatureResult = declarations.first.member;
}
- DartType thisType = classBuilder.cls.thisType;
+ DartType thisType = hierarchy.coreTypes
+ .thisInterfaceType(classBuilder.cls, classBuilder.library.nonNullable);
ClassMember bestSoFar;
DartType bestTypeSoFar;
for (int i = declarations.length - 1; i >= 0; i--) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/collections.dart b/pkg/front_end/lib/src/fasta/kernel/collections.dart
index ce5307c..1e907ea 100644
--- a/pkg/front_end/lib/src/fasta/kernel/collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/collections.dart
@@ -18,7 +18,7 @@
transformList,
visitList;
-import 'package:kernel/type_environment.dart' show TypeEnvironment;
+import 'package:kernel/type_environment.dart' show StaticTypeContext;
import 'package:kernel/visitor.dart'
show
@@ -45,7 +45,7 @@
/// Spread and control-flow elements are not expressions and do not have a
/// static type.
@override
- DartType getStaticType(TypeEnvironment types) {
+ DartType getStaticType(StaticTypeContext context) {
return unsupported("getStaticType", fileOffset, getFileUri(this));
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index fe48a98..35868d9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -123,6 +123,7 @@
final ConstantsBackend backend;
final ConstantEvaluator constantEvaluator;
final TypeEnvironment typeEnvironment;
+ StaticTypeContext _staticTypeContext;
/// Whether to preserve constant [Field]s. All use-sites will be rewritten.
final bool keepFields;
@@ -150,6 +151,9 @@
// Transform the library/class members:
void convertLibrary(Library library) {
+ _staticTypeContext =
+ new StaticTypeContext.forAnnotations(library, typeEnvironment);
+
transformAnnotations(library.annotations, library);
transformList(library.dependencies, this, library);
@@ -166,6 +170,7 @@
return reference.node is Field && reference.canonicalName == null;
});
}
+ _staticTypeContext = null;
}
@override
@@ -186,6 +191,9 @@
@override
Class visitClass(Class node) {
+ StaticTypeContext oldStaticTypeContext = _staticTypeContext;
+ _staticTypeContext = new StaticTypeContext.forAnnotations(
+ node.enclosingLibrary, typeEnvironment);
constantEvaluator.withNewEnvironment(() {
transformAnnotations(node.annotations, node);
transformList(node.fields, this, node);
@@ -194,25 +202,32 @@
transformList(node.procedures, this, node);
transformList(node.redirectingFactoryConstructors, this, node);
});
+ _staticTypeContext = oldStaticTypeContext;
return node;
}
@override
Procedure visitProcedure(Procedure node) {
+ StaticTypeContext oldStaticTypeContext = _staticTypeContext;
+ _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
constantEvaluator.withNewEnvironment(() {
transformAnnotations(node.annotations, node);
node.function = node.function.accept<TreeNode>(this)..parent = node;
});
+ _staticTypeContext = oldStaticTypeContext;
return node;
}
@override
Constructor visitConstructor(Constructor node) {
+ StaticTypeContext oldStaticTypeContext = _staticTypeContext;
+ _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
constantEvaluator.withNewEnvironment(() {
transformAnnotations(node.annotations, node);
transformList(node.initializers, this, node);
node.function = node.function.accept<TreeNode>(this)..parent = node;
});
+ _staticTypeContext = oldStaticTypeContext;
return node;
}
@@ -231,12 +246,15 @@
@override
RedirectingFactoryConstructor visitRedirectingFactoryConstructor(
RedirectingFactoryConstructor node) {
+ StaticTypeContext oldStaticTypeContext = _staticTypeContext;
+ _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
constantEvaluator.withNewEnvironment(() {
transformAnnotations(node.annotations, node);
transformList(node.typeParameters, this, node);
transformList(node.positionalParameters, this, node);
transformList(node.namedParameters, this, node);
});
+ _staticTypeContext = oldStaticTypeContext;
return node;
}
@@ -320,7 +338,9 @@
@override
Field visitField(Field node) {
- return constantEvaluator.withNewEnvironment(() {
+ StaticTypeContext oldStaticTypeContext = _staticTypeContext;
+ _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
+ Field field = constantEvaluator.withNewEnvironment(() {
if (node.isConst) {
transformAnnotations(node.annotations, node);
node.initializer =
@@ -340,13 +360,16 @@
}
return node;
});
+ _staticTypeContext = oldStaticTypeContext;
+ return field;
}
// Handle use-sites of constants (and "inline" constant expressions):
@override
Expression visitSymbolLiteral(SymbolLiteral node) {
- return makeConstantExpression(constantEvaluator.evaluate(node), node);
+ return makeConstantExpression(
+ constantEvaluator.evaluate(_staticTypeContext, node), node);
}
@override
@@ -460,11 +483,11 @@
Constant evaluateWithContext(TreeNode treeContext, Expression node) {
if (treeContext == node) {
- return constantEvaluator.evaluate(node);
+ return constantEvaluator.evaluate(_staticTypeContext, node);
}
return constantEvaluator.runInsideContext(treeContext, () {
- return constantEvaluator.evaluate(node);
+ return constantEvaluator.evaluate(_staticTypeContext, node);
});
}
@@ -473,7 +496,8 @@
constant.expression is InvalidExpression) {
return constant.expression;
}
- return new ConstantExpression(constant, node.getStaticType(typeEnvironment))
+ return new ConstantExpression(
+ constant, node.getStaticType(_staticTypeContext))
..fileOffset = node.fileOffset;
}
@@ -493,6 +517,7 @@
final bool errorOnUnevaluatedConstant;
final CoreTypes coreTypes;
final TypeEnvironment typeEnvironment;
+ StaticTypeContext _staticTypeContext;
final ErrorReporter errorReporter;
final bool desugarSets;
@@ -582,7 +607,8 @@
/// Returns UnevaluatedConstant if the constant could not be evaluated.
/// If the expression in the UnevaluatedConstant is an InvalidExpression,
/// an error occurred during constant evaluation.
- Constant evaluate(Expression node) {
+ Constant evaluate(StaticTypeContext context, Expression node) {
+ _staticTypeContext = context;
seenUnevaluatedChild = false;
lazyDepth = 0;
try {
@@ -1243,7 +1269,7 @@
templateConstEvalInvalidType.withArguments(
message,
typeEnvironment.coreTypes.stringLegacyRawType,
- message.getType(typeEnvironment)));
+ message.getType(_staticTypeContext)));
}
}
} else {
@@ -1252,7 +1278,7 @@
templateConstEvalInvalidType.withArguments(
condition,
typeEnvironment.coreTypes.boolLegacyRawType,
- condition.getType(typeEnvironment)));
+ condition.getType(_staticTypeContext)));
}
}
@@ -1298,7 +1324,7 @@
return report(
node,
templateConstEvalInvalidEqualsOperandType.withArguments(
- receiver, receiver.getType(typeEnvironment)));
+ receiver, receiver.getType(_staticTypeContext)));
}
}
@@ -1318,7 +1344,7 @@
'+',
receiver,
typeEnvironment.coreTypes.stringLegacyRawType,
- other.getType(typeEnvironment)));
+ other.getType(_staticTypeContext)));
}
}
} else if (intFolder.isInt(receiver)) {
@@ -1338,7 +1364,7 @@
op,
other,
typeEnvironment.coreTypes.intLegacyRawType,
- other.getType(typeEnvironment)));
+ other.getType(_staticTypeContext)));
}
num receiverValue = (receiver as PrimitiveConstant<num>).value;
return canonicalize(evaluateBinaryNumericOperation(
@@ -1350,7 +1376,7 @@
op,
receiver,
typeEnvironment.coreTypes.numLegacyRawType,
- other.getType(typeEnvironment)));
+ other.getType(_staticTypeContext)));
}
} else if (receiver is DoubleConstant) {
if ((op == '|' || op == '&' || op == '^') ||
@@ -1361,7 +1387,7 @@
op,
receiver,
typeEnvironment.coreTypes.intLegacyRawType,
- receiver.getType(typeEnvironment)));
+ receiver.getType(_staticTypeContext)));
}
if (arguments.length == 0) {
switch (op) {
@@ -1382,7 +1408,7 @@
op,
receiver,
typeEnvironment.coreTypes.numLegacyRawType,
- other.getType(typeEnvironment)));
+ other.getType(_staticTypeContext)));
}
} else if (receiver is BoolConstant) {
if (arguments.length == 1) {
@@ -1435,7 +1461,7 @@
node.operator,
left,
typeEnvironment.coreTypes.boolLegacyRawType,
- right.getType(typeEnvironment)));
+ right.getType(_staticTypeContext)));
}
return report(
node,
@@ -1456,7 +1482,7 @@
node.operator,
left,
typeEnvironment.coreTypes.boolLegacyRawType,
- right.getType(typeEnvironment)));
+ right.getType(_staticTypeContext)));
}
return report(
node,
@@ -1496,7 +1522,7 @@
templateConstEvalInvalidType.withArguments(
condition,
typeEnvironment.coreTypes.boolLegacyRawType,
- condition.getType(typeEnvironment)));
+ condition.getType(_staticTypeContext)));
}
}
@@ -1780,7 +1806,7 @@
templateConstEvalInvalidType.withArguments(
constant,
typeEnvironment.coreTypes.boolLegacyRawType,
- constant.getType(typeEnvironment)));
+ constant.getType(_staticTypeContext)));
}
@override
@@ -1839,7 +1865,7 @@
bool hasPrimitiveEqual(Constant constant) {
if (intFolder.isInt(constant)) return true;
- DartType type = constant.getType(typeEnvironment);
+ DartType type = constant.getType(_staticTypeContext);
return !(type is InterfaceType && !classHasPrimitiveEqual(type.classNode));
}
@@ -1863,7 +1889,7 @@
value ? trueConstant : falseConstant;
bool isSubtype(Constant constant, DartType type) {
- DartType constantType = constant.getType(typeEnvironment);
+ DartType constantType = constant.getType(_staticTypeContext);
if (targetingJavaScript) {
if (constantType is InterfaceType &&
constantType.classNode == typeEnvironment.coreTypes.intClass &&
@@ -1892,7 +1918,7 @@
return report(
node,
templateConstEvalInvalidType.withArguments(
- constant, type, constant.getType(typeEnvironment)));
+ constant, type, constant.getType(_staticTypeContext)));
}
return constant;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 3fac4c1..ac47c4d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -81,7 +81,7 @@
import 'kernel_builder.dart' show LoadLibraryBuilder;
-import 'kernel_shadow_ast.dart';
+import 'internal_ast.dart';
/// A generator represents a subexpression for which we can't yet build an
/// expression because we don't yet know the context in which it's used.
@@ -149,16 +149,13 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false});
/// Returns a [Expression] representing a pre-increment or pre-decrement of
/// the generator.
Expression buildPrefixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return buildCompoundAssignment(
binaryOperator, _forest.createIntLiteral(offset, 1),
offset: offset,
@@ -166,21 +163,19 @@
// instance `++a?.b;` is not providing a void context making it default
// `true`.
voidContext: voidContext,
- interfaceTarget: interfaceTarget,
isPreIncDec: true);
}
/// Returns a [Expression] representing a post-increment or post-decrement of
/// the generator.
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget});
+ {int offset: TreeNode.noOffset, bool voidContext: false});
/// Returns a [Generator] or [Expression] representing an index access
/// (e.g. `a[b]`) with the generator on the receiver and [index] as the
/// index expression.
- Generator buildIndexedAccess(Expression index, Token token);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware});
/// Returns a [Expression] representing a compile-time error.
///
@@ -206,11 +201,13 @@
Expression buildForEffect() => buildSimpleRead();
- Initializer buildFieldInitializer(Map<String, int> initializedFields) {
- return _helper.buildInvalidInitializer(
- _helper.buildProblem(
- messageInvalidInitializer, fileOffset, lengthForToken(token)),
- fileOffset);
+ List<Initializer> buildFieldInitializer(Map<String, int> initializedFields) {
+ return <Initializer>[
+ _helper.buildInvalidInitializer(
+ _helper.buildProblem(
+ messageInvalidInitializer, fileOffset, lengthForToken(token)),
+ fileOffset)
+ ];
}
/// Returns an expression, generator or initializer for an invocation of this
@@ -383,39 +380,25 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _createRead(),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest
+ .createBinary(offset, _createRead(), binaryOperator, value);
return _createWrite(fileOffset, binary);
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
if (voidContext) {
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
VariableDeclaration read =
_helper.forest.createVariableDeclarationForValue(_createRead());
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _helper.createVariableGet(read, fileOffset),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest.createBinary(offset,
+ _helper.createVariableGet(read, fileOffset), binaryOperator, value);
VariableDeclaration write = _helper.forest
.createVariableDeclarationForValue(_createWrite(offset, binary));
return new LocalPostIncDec(read, write)..fileOffset = offset;
@@ -429,8 +412,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -519,7 +505,6 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return new CompoundPropertySet(receiver, name, binaryOperator, value,
@@ -533,28 +518,19 @@
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
if (voidContext) {
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
VariableDeclaration variable =
_helper.forest.createVariableDeclarationForValue(receiver);
VariableDeclaration read = _helper.forest.createVariableDeclarationForValue(
_forest.createPropertyGet(fileOffset,
_helper.createVariableGet(variable, receiver.fileOffset), name));
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _helper.createVariableGet(read, fileOffset),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest.createBinary(offset,
+ _helper.createVariableGet(read, fileOffset), binaryOperator, value);
VariableDeclaration write = _helper.forest
.createVariableDeclarationForValue(_helper.forest.createPropertySet(
fileOffset,
@@ -566,8 +542,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
/// Creates a [Generator] for the access of property [name] on [receiver].
@@ -661,41 +640,36 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
- MethodInvocation binary = _helper.forest.createMethodInvocation(
+ _helper.forest.createBinary(
offset,
_forest.createPropertyGet(
fileOffset, _forest.createThisExpression(fileOffset), name),
binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ value);
+ Expression binary = _helper.forest.createBinary(
+ offset,
+ _forest.createPropertyGet(
+ fileOffset, _forest.createThisExpression(fileOffset), name),
+ binaryOperator,
+ value);
return _createWrite(fileOffset, binary, forEffect: voidContext);
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
if (voidContext) {
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
VariableDeclaration read = _helper.forest.createVariableDeclarationForValue(
_forest.createPropertyGet(
fileOffset, _forest.createThisExpression(fileOffset), name));
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _helper.createVariableGet(read, fileOffset),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest.createBinary(offset,
+ _helper.createVariableGet(read, fileOffset), binaryOperator, value);
VariableDeclaration write = _helper.forest
.createVariableDeclarationForValue(
_createWrite(fileOffset, binary, forEffect: true));
@@ -709,8 +683,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -729,7 +706,8 @@
NullAwarePropertyAccessGenerator(ExpressionGeneratorHelper helper,
Token token, this.receiverExpression, this.name)
- : this.receiver = makeOrReuseVariable(receiverExpression),
+ : this.receiver =
+ helper.forest.createVariableDeclarationForValue(receiverExpression),
super(helper, token);
@override
@@ -780,7 +758,6 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return new NullAwareCompoundSet(
@@ -793,15 +770,10 @@
}
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return buildCompoundAssignment(
binaryOperator, _forest.createIntLiteral(offset, 1),
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
@override
@@ -810,8 +782,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -873,39 +848,25 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset = TreeNode.noOffset,
bool voidContext = false,
- Procedure interfaceTarget,
bool isPreIncDec = false,
bool isPostIncDec = false}) {
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _createRead(),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest
+ .createBinary(offset, _createRead(), binaryOperator, value);
return _createWrite(fileOffset, binary);
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
if (voidContext) {
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
VariableDeclaration read =
_helper.forest.createVariableDeclarationForValue(_createRead());
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _helper.createVariableGet(read, fileOffset),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest.createBinary(offset,
+ _helper.createVariableGet(read, fileOffset), binaryOperator, value);
VariableDeclaration write = _helper.forest
.createVariableDeclarationForValue(_createWrite(fileOffset, binary));
return new StaticPostIncDec(read, write)..fileOffset = offset;
@@ -940,8 +901,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -965,8 +929,9 @@
IndexedAccessGenerator(
ExpressionGeneratorHelper helper, Token token, this.receiver, this.index,
- {this.isNullAware: false})
- : super(helper, token);
+ {this.isNullAware})
+ : assert(isNullAware != null),
+ super(helper, token);
@override
String get _plainNameForRead => "[]";
@@ -976,56 +941,113 @@
@override
Expression buildSimpleRead() {
- return _helper.buildMethodInvocation(
- receiver,
- indexGetName,
- _helper.forest.createArguments(fileOffset, <Expression>[index]),
- fileOffset);
+ VariableDeclaration variable;
+ Expression receiverValue;
+ if (isNullAware) {
+ variable = _forest.createVariableDeclarationForValue(receiver);
+ receiverValue = _helper.createVariableGet(variable, fileOffset);
+ } else {
+ receiverValue = receiver;
+ }
+ Expression result =
+ _forest.createIndexGet(fileOffset, receiverValue, index);
+ if (isNullAware) {
+ result = new NullAwareMethodInvocation(variable, result)
+ ..fileOffset = fileOffset;
+ }
+ return result;
}
@override
Expression buildAssignment(Expression value, {bool voidContext: false}) {
- return new IndexSet(receiver, index, value,
- forEffect: voidContext, readOnlyReceiver: false)
- ..fileOffset = fileOffset;
+ VariableDeclaration variable;
+ Expression receiverValue;
+ bool readOnlyReceiver;
+ if (isNullAware) {
+ variable = _forest.createVariableDeclarationForValue(receiver);
+ receiverValue = _helper.createVariableGet(variable, fileOffset);
+ readOnlyReceiver = true;
+ } else {
+ receiverValue = receiver;
+ readOnlyReceiver = false;
+ }
+ Expression result = _forest.createIndexSet(
+ fileOffset, receiverValue, index, value,
+ forEffect: voidContext, readOnlyReceiver: readOnlyReceiver);
+ if (isNullAware) {
+ result = new NullAwareMethodInvocation(variable, result)
+ ..fileOffset = fileOffset;
+ }
+ return result;
}
@override
Expression buildIfNullAssignment(Expression value, DartType type, int offset,
{bool voidContext: false}) {
- return new IfNullIndexSet(receiver, index, value,
+ VariableDeclaration variable;
+ Expression receiverValue;
+ bool readOnlyReceiver;
+ if (isNullAware) {
+ variable = _forest.createVariableDeclarationForValue(receiver);
+ receiverValue = _helper.createVariableGet(variable, fileOffset);
+ readOnlyReceiver = true;
+ } else {
+ receiverValue = receiver;
+ readOnlyReceiver = false;
+ }
+
+ Expression result = new IfNullIndexSet(receiverValue, index, value,
readOffset: fileOffset,
testOffset: offset,
writeOffset: fileOffset,
- forEffect: voidContext)
+ forEffect: voidContext,
+ readOnlyReceiver: readOnlyReceiver)
..fileOffset = offset;
+ if (isNullAware) {
+ result = new NullAwareMethodInvocation(variable, result)
+ ..fileOffset = fileOffset;
+ }
+ return result;
}
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
- return new CompoundIndexSet(receiver, index, binaryOperator, value,
+ VariableDeclaration variable;
+ Expression receiverValue;
+ bool readOnlyReceiver;
+ if (isNullAware) {
+ variable = _forest.createVariableDeclarationForValue(receiver);
+ receiverValue = _helper.createVariableGet(variable, fileOffset);
+ readOnlyReceiver = true;
+ } else {
+ receiverValue = receiver;
+ readOnlyReceiver = false;
+ }
+
+ Expression result = new CompoundIndexSet(
+ receiverValue, index, binaryOperator, value,
readOffset: fileOffset,
binaryOffset: offset,
writeOffset: fileOffset,
forEffect: voidContext,
- forPostIncDec: isPostIncDec);
+ forPostIncDec: isPostIncDec,
+ readOnlyReceiver: readOnlyReceiver);
+ if (isNullAware) {
+ result = new NullAwareMethodInvocation(variable, result)
+ ..fileOffset = fileOffset;
+ }
+ return result;
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
@override
@@ -1036,9 +1058,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
- isNullAware: false);
+ isNullAware: isNullAware);
}
@override
@@ -1048,14 +1072,18 @@
printNodeOn(receiver, sink, syntheticNames: syntheticNames);
sink.write(", index: ");
printNodeOn(index, sink, syntheticNames: syntheticNames);
+ sink.write(", isNullAware: ${isNullAware}");
}
static Generator make(ExpressionGeneratorHelper helper, Token token,
- Expression receiver, Expression index) {
+ Expression receiver, Expression index,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
if (helper.forest.isThisExpression(receiver)) {
return new ThisIndexedAccessGenerator(helper, token, index);
} else {
- return new IndexedAccessGenerator(helper, token, receiver, index);
+ return new IndexedAccessGenerator(helper, token, receiver, index,
+ isNullAware: isNullAware);
}
}
}
@@ -1078,19 +1106,14 @@
@override
Expression buildSimpleRead() {
Expression receiver = _helper.forest.createThisExpression(fileOffset);
- return _helper.buildMethodInvocation(
- receiver,
- indexGetName,
- _helper.forest.createArguments(fileOffset, <Expression>[index]),
- fileOffset);
+ return _forest.createIndexGet(fileOffset, receiver, index);
}
@override
Expression buildAssignment(Expression value, {bool voidContext: false}) {
Expression receiver = _helper.forest.createThisExpression(fileOffset);
- return new IndexSet(receiver, index, value,
- forEffect: voidContext, readOnlyReceiver: true)
- ..fileOffset = fileOffset;
+ return _forest.createIndexSet(fileOffset, receiver, index, value,
+ forEffect: voidContext, readOnlyReceiver: true);
}
@override
@@ -1109,7 +1132,6 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
Expression receiver = _helper.forest.createThisExpression(fileOffset);
@@ -1124,15 +1146,10 @@
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
@override
@@ -1143,8 +1160,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -1213,7 +1233,6 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return new CompoundSuperIndexSet(
@@ -1227,15 +1246,10 @@
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
@override
@@ -1246,8 +1260,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -1326,7 +1343,7 @@
MemberBuilder getterBuilder,
MemberBuilder setterBuilder) {
return new StaticAccessGenerator(helper, token, targetName,
- getterBuilder?.member, setterBuilder?.member);
+ getterBuilder?.readTarget, setterBuilder?.writeTarget);
}
@override
@@ -1377,39 +1394,25 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset = TreeNode.noOffset,
bool voidContext = false,
- Procedure interfaceTarget,
bool isPreIncDec = false,
bool isPostIncDec = false}) {
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _createRead(),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest
+ .createBinary(offset, _createRead(), binaryOperator, value);
return _createWrite(fileOffset, binary);
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
if (voidContext) {
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
VariableDeclaration read =
_helper.forest.createVariableDeclarationForValue(_createRead());
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _helper.createVariableGet(read, fileOffset),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest.createBinary(offset,
+ _helper.createVariableGet(read, fileOffset), binaryOperator, value);
VariableDeclaration write = _helper.forest
.createVariableDeclarationForValue(_createWrite(offset, binary));
return new StaticPostIncDec(read, write)..fileOffset = offset;
@@ -1438,8 +1441,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -1590,8 +1596,9 @@
if (extensionTypeParameters != null) {
extensionTypeArguments = [];
for (TypeParameter typeParameter in extensionTypeParameters) {
- extensionTypeArguments
- .add(_forest.createTypeParameterType(typeParameter));
+ extensionTypeArguments.add(
+ _forest.createTypeParameterTypeWithDefaultNullabilityForLibrary(
+ typeParameter, extension.enclosingLibrary));
}
}
return extensionTypeArguments;
@@ -1657,39 +1664,25 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _createRead(),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest
+ .createBinary(offset, _createRead(), binaryOperator, value);
return _createWrite(fileOffset, binary, forEffect: voidContext);
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
if (voidContext) {
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
VariableDeclaration read =
_helper.forest.createVariableDeclarationForValue(_createRead());
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _helper.createVariableGet(read, fileOffset),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest.createBinary(offset,
+ _helper.createVariableGet(read, fileOffset), binaryOperator, value);
VariableDeclaration write = _helper.forest
.createVariableDeclarationForValue(
_createWrite(fileOffset, binary, forEffect: true));
@@ -1721,8 +1714,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -2013,18 +2009,16 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
if (isNullAware) {
VariableDeclaration variable =
_helper.forest.createVariableDeclarationForValue(receiver);
- MethodInvocation binary = _helper.forest.createMethodInvocation(
+ Expression binary = _helper.forest.createBinary(
offset,
_createRead(_helper.createVariableGet(variable, receiver.fileOffset)),
binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ value);
Expression write = _createWrite(fileOffset,
_helper.createVariableGet(variable, receiver.fileOffset), binary,
forEffect: voidContext, readOnlyReceiver: true);
@@ -2043,28 +2037,19 @@
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
if (voidContext) {
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
} else if (isNullAware) {
VariableDeclaration variable =
_helper.forest.createVariableDeclarationForValue(receiver);
VariableDeclaration read = _helper.forest
.createVariableDeclarationForValue(_createRead(
_helper.createVariableGet(variable, receiver.fileOffset)));
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _helper.createVariableGet(read, fileOffset),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest.createBinary(offset,
+ _helper.createVariableGet(read, fileOffset), binaryOperator, value);
VariableDeclaration write = _helper.forest
.createVariableDeclarationForValue(_createWrite(fileOffset,
_helper.createVariableGet(variable, receiver.fileOffset), binary,
@@ -2079,12 +2064,8 @@
VariableDeclaration read = _helper.forest
.createVariableDeclarationForValue(_createRead(
_helper.createVariableGet(variable, receiver.fileOffset)));
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _helper.createVariableGet(read, fileOffset),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest.createBinary(offset,
+ _helper.createVariableGet(read, fileOffset), binaryOperator, value);
VariableDeclaration write = _helper.forest
.createVariableDeclarationForValue(_createWrite(fileOffset,
_helper.createVariableGet(variable, receiver.fileOffset), binary,
@@ -2139,8 +2120,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -2186,6 +2170,8 @@
/// The number of type parameters declared on the extension declaration.
final int extensionTypeParameterCount;
+ final bool isNullAware;
+
ExplicitExtensionIndexedAccessGenerator(
ExpressionGeneratorHelper helper,
Token token,
@@ -2196,9 +2182,11 @@
this.receiver,
this.index,
this.explicitTypeArguments,
- this.extensionTypeParameterCount)
+ this.extensionTypeParameterCount,
+ {this.isNullAware})
: assert(readTarget != null || writeTarget != null),
assert(receiver != null),
+ assert(isNullAware != null),
super(helper, token);
factory ExplicitExtensionIndexedAccessGenerator.fromBuilder(
@@ -2211,7 +2199,9 @@
Expression receiver,
Expression index,
List<DartType> explicitTypeArguments,
- int extensionTypeParameterCount) {
+ int extensionTypeParameterCount,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
Procedure readTarget;
if (getterBuilder != null) {
if (getterBuilder is AccessErrorBuilder) {
@@ -2246,7 +2236,8 @@
receiver,
index,
explicitTypeArguments,
- extensionTypeParameterCount);
+ extensionTypeParameterCount,
+ isNullAware: isNullAware);
}
List<DartType> _createExtensionTypeArguments() {
@@ -2262,15 +2253,28 @@
if (readTarget == null) {
return _makeInvalidRead();
}
- return _helper.buildExtensionMethodInvocation(
+ VariableDeclaration variable;
+ Expression receiverValue;
+ if (isNullAware) {
+ variable = _forest.createVariableDeclarationForValue(receiver);
+ receiverValue = _helper.createVariableGet(variable, fileOffset);
+ } else {
+ receiverValue = receiver;
+ }
+ Expression result = _helper.buildExtensionMethodInvocation(
fileOffset,
readTarget,
_forest.createArgumentsForExtensionMethod(
- fileOffset, extensionTypeParameterCount, 0, receiver,
+ fileOffset, extensionTypeParameterCount, 0, receiverValue,
extensionTypeArguments: _createExtensionTypeArguments(),
extensionTypeArgumentOffset: extensionTypeArgumentOffset,
positionalArguments: <Expression>[index]),
isTearOff: false);
+ if (isNullAware) {
+ result = new NullAwareMethodInvocation(variable, result)
+ ..fileOffset = fileOffset;
+ }
+ return result;
}
@override
@@ -2278,61 +2282,116 @@
if (writeTarget == null) {
return _makeInvalidWrite(value);
}
+ VariableDeclaration variable;
+ Expression receiverValue;
+ if (isNullAware) {
+ variable = _forest.createVariableDeclarationForValue(receiver);
+ receiverValue = _helper.createVariableGet(variable, fileOffset);
+ } else {
+ receiverValue = receiver;
+ }
+ Expression result;
if (voidContext) {
- return _helper.buildExtensionMethodInvocation(
+ result = _helper.buildExtensionMethodInvocation(
fileOffset,
writeTarget,
_forest.createArgumentsForExtensionMethod(
- fileOffset, extensionTypeParameterCount, 0, receiver,
+ fileOffset, extensionTypeParameterCount, 0, receiverValue,
extensionTypeArguments: _createExtensionTypeArguments(),
extensionTypeArgumentOffset: extensionTypeArgumentOffset,
positionalArguments: <Expression>[index, value]),
isTearOff: false);
} else {
- return new ExtensionIndexSet(
- extension, explicitTypeArguments, receiver, writeTarget, index, value)
+ result = new ExtensionIndexSet(extension, explicitTypeArguments,
+ receiverValue, writeTarget, index, value)
..fileOffset = fileOffset;
}
+ if (isNullAware) {
+ result = new NullAwareMethodInvocation(variable, result)
+ ..fileOffset = fileOffset;
+ }
+ return result;
}
@override
Expression buildIfNullAssignment(Expression value, DartType type, int offset,
{bool voidContext: false}) {
- return new IfNullExtensionIndexSet(extension, explicitTypeArguments,
- receiver, readTarget, writeTarget, index, value,
+ VariableDeclaration variable;
+ Expression receiverValue;
+ bool readOnlyReceiver;
+ if (isNullAware) {
+ variable = _forest.createVariableDeclarationForValue(receiver);
+ receiverValue = _helper.createVariableGet(variable, fileOffset);
+ readOnlyReceiver = true;
+ } else {
+ receiverValue = receiver;
+ readOnlyReceiver = false;
+ }
+ Expression result = new IfNullExtensionIndexSet(
+ extension,
+ explicitTypeArguments,
+ receiverValue,
+ readTarget,
+ writeTarget,
+ index,
+ value,
readOffset: fileOffset,
testOffset: offset,
writeOffset: fileOffset,
- forEffect: voidContext)
+ forEffect: voidContext,
+ readOnlyReceiver: readOnlyReceiver)
..fileOffset = offset;
+ if (isNullAware) {
+ result = new NullAwareMethodInvocation(variable, result)
+ ..fileOffset = fileOffset;
+ }
+ return result;
}
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
- return new CompoundExtensionIndexSet(extension, explicitTypeArguments,
- receiver, readTarget, writeTarget, index, binaryOperator, value,
+ VariableDeclaration variable;
+ Expression receiverValue;
+ bool readOnlyReceiver;
+ if (isNullAware) {
+ variable = _forest.createVariableDeclarationForValue(receiver);
+ receiverValue = _helper.createVariableGet(variable, fileOffset);
+ readOnlyReceiver = true;
+ } else {
+ receiverValue = receiver;
+ readOnlyReceiver = false;
+ }
+ Expression result = new CompoundExtensionIndexSet(
+ extension,
+ explicitTypeArguments,
+ receiverValue,
+ readTarget,
+ writeTarget,
+ index,
+ binaryOperator,
+ value,
readOffset: fileOffset,
binaryOffset: offset,
writeOffset: fileOffset,
forEffect: voidContext,
- forPostIncDec: isPostIncDec);
+ forPostIncDec: isPostIncDec,
+ readOnlyReceiver: readOnlyReceiver);
+ if (isNullAware) {
+ result = new NullAwareMethodInvocation(variable, result)
+ ..fileOffset = fileOffset;
+ }
+ return result;
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
@override
@@ -2343,8 +2402,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -2423,16 +2485,13 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return _makeInvalidRead();
}
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return _makeInvalidRead();
}
@@ -2517,7 +2576,9 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
Builder getter = extensionBuilder.lookupLocalMemberByName(indexGetName);
Builder setter = extensionBuilder.lookupLocalMemberByName(indexSetName);
if (getter == null && setter == null) {
@@ -2537,7 +2598,8 @@
receiver,
index,
explicitTypeArguments,
- extensionBuilder.typeParameters?.length ?? 0);
+ extensionBuilder.typeParameters?.length ?? 0,
+ isNullAware: isNullAware);
}
@override
@@ -2589,29 +2651,19 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- buildSimpleRead(),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest
+ .createBinary(offset, buildSimpleRead(), binaryOperator, value);
return _makeInvalidWrite(binary);
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
@override
@@ -2625,8 +2677,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -2673,14 +2728,12 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return _helper.wrapInDeferredCheck(
suffixGenerator.buildCompoundAssignment(binaryOperator, value,
offset: offset,
voidContext: voidContext,
- interfaceTarget: interfaceTarget,
isPreIncDec: isPreIncDec,
isPostIncDec: isPostIncDec),
prefixGenerator.prefix,
@@ -2689,14 +2742,10 @@
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return _helper.wrapInDeferredCheck(
suffixGenerator.buildPostfixIncrement(binaryOperator,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget),
+ offset: offset, voidContext: voidContext),
prefixGenerator.prefix,
token.charOffset);
}
@@ -2781,8 +2830,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -3080,29 +3132,19 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
- MethodInvocation binary = _helper.forest.createMethodInvocation(
- offset,
- _createRead(),
- binaryOperator,
- _helper.forest.createArguments(offset, <Expression>[value]),
- interfaceTarget: interfaceTarget);
+ Expression binary = _helper.forest
+ .createBinary(offset, _createRead(), binaryOperator, value);
return _makeInvalidWrite(binary);
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
Expression value = _forest.createIntLiteral(offset, 1);
return buildCompoundAssignment(binaryOperator, value,
- offset: offset,
- voidContext: voidContext,
- interfaceTarget: interfaceTarget,
- isPostIncDec: true);
+ offset: offset, voidContext: voidContext, isPostIncDec: true);
}
@override
@@ -3113,10 +3155,13 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
// TODO(johnniwinther): The read-only quality of the variable should be
// passed on to the generator.
- return new IndexedAccessGenerator(_helper, token, _createRead(), index);
+ return new IndexedAccessGenerator(_helper, token, _createRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -3149,9 +3194,11 @@
withReceiver(Object receiver, int operatorOffset, {bool isNullAware}) => this;
@override
- Initializer buildFieldInitializer(Map<String, int> initializedFields) {
- return _helper.buildInvalidInitializer(
- buildError(_forest.createArgumentsEmpty(fileOffset), isSetter: true));
+ List<Initializer> buildFieldInitializer(Map<String, int> initializedFields) {
+ return <Initializer>[
+ _helper.buildInvalidInitializer(
+ buildError(_forest.createArgumentsEmpty(fileOffset), isSetter: true))
+ ];
}
@override
@@ -3176,7 +3223,6 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: -1,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return buildError(_forest.createArguments(fileOffset, <Expression>[value]),
@@ -3185,7 +3231,7 @@
@override
Expression buildPrefixIncrement(Name binaryOperator,
- {int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
+ {int offset: -1, bool voidContext: false}) {
return buildError(
_forest.createArguments(
fileOffset, <Expression>[_forest.createIntLiteral(offset, 1)]),
@@ -3195,7 +3241,7 @@
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
+ {int offset: -1, bool voidContext: false}) {
return buildError(
_forest.createArguments(
fileOffset, <Expression>[_forest.createIntLiteral(offset, 1)]),
@@ -3243,8 +3289,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
}
@@ -3295,7 +3344,6 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return _buildUnresolvedVariableAssignment(true, value);
@@ -3320,8 +3368,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
}
@@ -3357,7 +3408,6 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: -1,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return _makeInvalidWrite(value);
@@ -3365,13 +3415,13 @@
@override
Expression buildPrefixIncrement(Name binaryOperator,
- {int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
+ {int offset: -1, bool voidContext: false}) {
return _makeInvalidWrite(null);
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
+ {int offset: -1, bool voidContext: false}) {
return _makeInvalidWrite(null);
}
@@ -3387,8 +3437,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
}
@@ -3468,7 +3521,7 @@
}
@override
- Initializer buildFieldInitializer(Map<String, int> initializedFields) {
+ List<Initializer> buildFieldInitializer(Map<String, int> initializedFields) {
if (!identical("=", assignmentOperator) ||
generator is! ThisPropertyAccessGenerator) {
return generator.buildFieldInitializer(initializedFields);
@@ -3489,10 +3542,8 @@
class DelayedPostfixIncrement extends ContextAwareGenerator {
final Name binaryOperator;
- final Procedure interfaceTarget;
-
DelayedPostfixIncrement(ExpressionGeneratorHelper helper, Token token,
- Generator generator, this.binaryOperator, this.interfaceTarget)
+ Generator generator, this.binaryOperator)
: super(helper, token, generator);
@override
@@ -3501,25 +3552,19 @@
@override
Expression buildSimpleRead() {
return generator.buildPostfixIncrement(binaryOperator,
- offset: fileOffset,
- voidContext: false,
- interfaceTarget: interfaceTarget);
+ offset: fileOffset, voidContext: false);
}
@override
Expression buildForEffect() {
return generator.buildPostfixIncrement(binaryOperator,
- offset: fileOffset,
- voidContext: true,
- interfaceTarget: interfaceTarget);
+ offset: fileOffset, voidContext: true);
}
@override
void printOn(StringSink sink) {
sink.write(", binaryOperator: ");
sink.write(binaryOperator.name);
- sink.write(", interfaceTarget: ");
- printQualifiedNameOn(interfaceTarget, sink);
}
}
@@ -3553,7 +3598,6 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return _makeInvalidRead();
@@ -3561,9 +3605,7 @@
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return _makeInvalidRead();
}
@@ -3631,8 +3673,11 @@
Expression _makeInvalidWrite(Expression value) => _makeInvalidRead();
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -3678,7 +3723,6 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return _makeInvalidRead();
@@ -3686,9 +3730,7 @@
@override
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset = TreeNode.noOffset,
- bool voidContext = false,
- Procedure interfaceTarget}) {
+ {int offset = TreeNode.noOffset, bool voidContext = false}) {
return _makeInvalidRead();
}
@@ -3721,8 +3763,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
@override
@@ -3767,23 +3812,18 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return buildProblem();
}
Expression buildPrefixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return buildProblem();
}
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return buildProblem();
}
@@ -3791,8 +3831,8 @@
Expression _makeInvalidWrite(Expression value) => buildProblem();
- Initializer buildFieldInitializer(Map<String, int> initializedFields) {
- return _helper.buildInvalidInitializer(buildProblem());
+ List<Initializer> buildFieldInitializer(Map<String, int> initializedFields) {
+ return <Initializer>[_helper.buildInvalidInitializer(buildProblem())];
}
Expression doInvocation(int offset, Arguments arguments) {
@@ -3829,8 +3869,11 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
- return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index);
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
+ return new IndexedAccessGenerator(_helper, token, buildSimpleRead(), index,
+ isNullAware: isNullAware);
}
}
@@ -3928,9 +3971,11 @@
}
@override
- Initializer buildFieldInitializer(Map<String, int> initializedFields) {
+ List<Initializer> buildFieldInitializer(Map<String, int> initializedFields) {
Expression error = buildFieldInitializerError(initializedFields);
- return _helper.buildInvalidInitializer(error, error.fileOffset);
+ return <Initializer>[
+ _helper.buildInvalidInitializer(error, error.fileOffset)
+ ];
}
buildPropertyAccess(
@@ -4089,28 +4134,25 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return buildAssignmentError();
}
Expression buildPrefixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return buildAssignmentError();
}
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return buildAssignmentError();
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
if (isSuper) {
return new SuperIndexedAccessGenerator(
_helper,
@@ -4238,23 +4280,18 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return unsupported("buildCompoundAssignment", offset ?? fileOffset, _uri);
}
Expression buildPrefixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return unsupported("buildPrefixIncrement", offset ?? fileOffset, _uri);
}
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return unsupported("buildPostfixIncrement", offset ?? fileOffset, _uri);
}
@@ -4263,7 +4300,9 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
return unsupported("buildIndexedAccess", offsetForToken(token), _uri);
}
@@ -4317,23 +4356,18 @@
Expression buildCompoundAssignment(Name binaryOperator, Expression value,
{int offset: TreeNode.noOffset,
bool voidContext: false,
- Procedure interfaceTarget,
bool isPreIncDec: false,
bool isPostIncDec: false}) {
return unsupported("buildCompoundAssignment", offset ?? fileOffset, _uri);
}
Expression buildPrefixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return unsupported("buildPrefixIncrement", offset ?? fileOffset, _uri);
}
Expression buildPostfixIncrement(Name binaryOperator,
- {int offset: TreeNode.noOffset,
- bool voidContext: false,
- Procedure interfaceTarget}) {
+ {int offset: TreeNode.noOffset, bool voidContext: false}) {
return unsupported("buildPostfixIncrement", offset ?? fileOffset, _uri);
}
@@ -4342,7 +4376,9 @@
}
@override
- Generator buildIndexedAccess(Expression index, Token token) {
+ Generator buildIndexedAccess(Expression index, Token token,
+ {bool isNullAware}) {
+ assert(isNullAware != null);
return unsupported("buildIndexedAccess", offsetForToken(token), _uri);
}
@@ -4406,33 +4442,6 @@
}
}
-Expression makeLet(VariableDeclaration variable, Expression body) {
- if (variable == null) return body;
- return new Let(variable, body);
-}
-
-Expression makeBinary(Expression left, Name operator, Procedure interfaceTarget,
- Expression right, ExpressionGeneratorHelper helper,
- {int offset: TreeNode.noOffset}) {
- return new MethodInvocationImpl(left, operator,
- helper.forest.createArguments(offset, <Expression>[right]),
- interfaceTarget: interfaceTarget)
- ..fileOffset = offset;
-}
-
-Expression buildIsNull(
- Expression value, int offset, ExpressionGeneratorHelper helper) {
- return makeBinary(
- value, equalsName, null, helper.forest.createNullLiteral(offset), helper,
- offset: offset);
-}
-
-VariableDeclaration makeOrReuseVariable(Expression value) {
- // TODO: Devise a way to remember if a variable declaration was reused
- // or is fresh (hence needs a let binding).
- return new VariableDeclaration.forValue(value);
-}
-
int adjustForImplicitCall(String name, int offset) {
// Normally the offset is at the start of the token, but in this case,
// because we insert a '.call', we want it at the end instead.
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index 9930e0b..c83a89b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -63,7 +63,7 @@
Initializer buildInvalidInitializer(Expression expression, [int offset]);
- Initializer buildFieldInitializer(bool isSynthetic, String name,
+ List<Initializer> buildFieldInitializer(bool isSynthetic, String name,
int fieldNameOffset, int assignmentOffset, Expression expression,
{DartType formalType});
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 0b0b77f..391ea59 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -22,7 +22,7 @@
IfMapEntry,
SpreadElement;
-import 'kernel_shadow_ast.dart';
+import 'internal_ast.dart';
/// A shadow tree factory.
class Forest {
@@ -607,8 +607,15 @@
return new TypeParameter(name);
}
- TypeParameterType createTypeParameterType(TypeParameter typeParameter) {
- return new TypeParameterType(typeParameter, Nullability.legacy);
+ TypeParameterType createTypeParameterType(
+ TypeParameter typeParameter, Nullability nullability) {
+ return new TypeParameterType(typeParameter, nullability);
+ }
+
+ TypeParameterType createTypeParameterTypeWithDefaultNullabilityForLibrary(
+ TypeParameter typeParameter, Library library) {
+ return new TypeParameterType.withDefaultNullabilityForLibrary(
+ typeParameter, library);
}
FunctionExpression createFunctionExpression(
@@ -676,6 +683,23 @@
..fileOffset = fileOffset;
}
+ IndexGet createIndexGet(
+ int fileOffset, Expression receiver, Expression index) {
+ assert(fileOffset != null);
+ return new IndexGet(receiver, index)..fileOffset = fileOffset;
+ }
+
+ IndexSet createIndexSet(
+ int fileOffset, Expression receiver, Expression index, Expression value,
+ {bool forEffect, bool readOnlyReceiver}) {
+ assert(fileOffset != null);
+ assert(forEffect != null);
+ assert(readOnlyReceiver != null);
+ return new IndexSet(receiver, index, value,
+ forEffect: forEffect, readOnlyReceiver: readOnlyReceiver)
+ ..fileOffset = fileOffset;
+ }
+
EqualsExpression createEquals(
int fileOffset, Expression left, Expression right,
{bool isNot}) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
index 958b6c0..4e1e2a5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
@@ -13,7 +13,6 @@
Member,
Name,
NamedExpression,
- Nullability,
Procedure,
ProcedureKind,
ReturnStatement,
@@ -272,7 +271,8 @@
.toList();
List<DartType> typeArguments = function.typeParameters
.map<DartType>((typeParameter) =>
- new TypeParameterType(typeParameter, Nullability.legacy))
+ new TypeParameterType.withDefaultNullabilityForLibrary(
+ typeParameter, enclosingClass.enclosingLibrary))
.toList();
Arguments arguments = new Arguments(positionalArguments,
types: typeArguments, named: namedArguments);
@@ -322,7 +322,8 @@
..isGenericCovariantImpl = targetTypeParameter.isGenericCovariantImpl;
typeParameters[i] = typeParameter;
additionalSubstitution[targetTypeParameter] =
- new TypeParameterType(typeParameter, Nullability.legacy);
+ new TypeParameterType.forAlphaRenaming(
+ targetTypeParameter, typeParameter);
}
substitution = Substitution.combine(
substitution, Substitution.fromMap(additionalSubstitution));
@@ -381,7 +382,9 @@
Substitution _substitutionFor(Member candidate, Class class_) {
return Substitution.fromInterfaceType(hierarchy.getKernelTypeAsInstanceOf(
- class_.thisType, candidate.enclosingClass));
+ hierarchy.coreTypes
+ .thisInterfaceType(class_, class_.enclosingLibrary.nonNullable),
+ candidate.enclosingClass));
}
List<VariableDeclaration> getPositionalParameters(Member member) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
index edd980c..8070c5d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/implicit_field_type.dart
@@ -9,37 +9,96 @@
import 'package:kernel/ast.dart'
show DartType, DartTypeVisitor, DartTypeVisitor1, Nullability, Visitor;
-import '../builder/member_builder.dart';
+import '../builder/field_builder.dart';
import '../problems.dart' show unsupported;
-class ImplicitFieldType extends DartType {
- final MemberBuilder memberBuilder;
+abstract class ImplicitFieldType extends DartType {
+ SourceFieldBuilder get fieldBuilder;
+ Token get initializerToken;
+ void set initializerToken(Token value);
+ bool get isStarted;
+ void set isStarted(bool value);
+
+ ImplicitFieldType._();
+
+ factory ImplicitFieldType(
+ SourceFieldBuilder fieldBuilder, Token initializerToken) =
+ _ImplicitFieldTypeRoot;
+
+ @override
+ Nullability get nullability =>
+ unsupported("nullability", fieldBuilder.charOffset, fieldBuilder.fileUri);
+
+ @override
+ R accept<R>(DartTypeVisitor<R> v) {
+ throw unsupported("accept", fieldBuilder.charOffset, fieldBuilder.fileUri);
+ }
+
+ @override
+ R accept1<R, A>(DartTypeVisitor1<R, A> v, arg) {
+ throw unsupported("accept1", fieldBuilder.charOffset, fieldBuilder.fileUri);
+ }
+
+ @override
+ visitChildren(Visitor<Object> v) {
+ unsupported("visitChildren", fieldBuilder.charOffset, fieldBuilder.fileUri);
+ }
+
+ @override
+ ImplicitFieldType withNullability(Nullability nullability) {
+ return unsupported(
+ "withNullability", fieldBuilder.charOffset, fieldBuilder.fileUri);
+ }
+
+ ImplicitFieldType createAlias(SourceFieldBuilder target) =>
+ new _ImplicitFieldTypeAlias(this, target);
+
+ @override
+ bool operator ==(Object other) {
+ if (identical(this, other)) return true;
+ return other is ImplicitFieldType && fieldBuilder == other.fieldBuilder;
+ }
+
+ @override
+ int get hashCode => fieldBuilder.hashCode;
+
+ DartType inferType();
+}
+
+class _ImplicitFieldTypeRoot extends ImplicitFieldType {
+ final SourceFieldBuilder fieldBuilder;
Token initializerToken;
bool isStarted = false;
- ImplicitFieldType(this.memberBuilder, this.initializerToken);
+ _ImplicitFieldTypeRoot(this.fieldBuilder, this.initializerToken) : super._();
- Nullability get nullability => unsupported(
- "nullability", memberBuilder.charOffset, memberBuilder.fileUri);
+ DartType inferType() => fieldBuilder.inferType();
+}
- R accept<R>(DartTypeVisitor<R> v) {
- throw unsupported(
- "accept", memberBuilder.charOffset, memberBuilder.fileUri);
+class _ImplicitFieldTypeAlias extends ImplicitFieldType {
+ final ImplicitFieldType _root;
+ final SourceFieldBuilder _targetFieldBuilder;
+
+ _ImplicitFieldTypeAlias(this._root, this._targetFieldBuilder)
+ : assert(_root.fieldBuilder != _targetFieldBuilder),
+ super._();
+
+ SourceFieldBuilder get fieldBuilder => _root.fieldBuilder;
+
+ Token get initializerToken => _root.initializerToken;
+
+ void set initializerToken(Token value) {
+ _root.initializerToken = value;
}
- R accept1<R, A>(DartTypeVisitor1<R, A> v, arg) {
- throw unsupported(
- "accept1", memberBuilder.charOffset, memberBuilder.fileUri);
+ bool get isStarted => _root.isStarted;
+
+ void set isStarted(bool value) {
+ _root.isStarted = value;
}
- visitChildren(Visitor<Object> v) {
- unsupported(
- "visitChildren", memberBuilder.charOffset, memberBuilder.fileUri);
- }
-
- ImplicitFieldType withNullability(Nullability nullability) {
- return unsupported(
- "withNullability", memberBuilder.charOffset, memberBuilder.fileUri);
+ DartType inferType() {
+ return _targetFieldBuilder.fieldType = _root.inferType();
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index f1f9283..26597c3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -2,12 +2,78 @@
// 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.
-part of "kernel_shadow_ast.dart";
+import 'dart:core' hide MapEntry;
+
+import 'package:kernel/ast.dart';
+
+import 'package:kernel/type_algebra.dart' show Substitution;
+
+import 'package:kernel/type_environment.dart';
+
+import '../../base/instrumentation.dart'
+ show
+ InstrumentationValueForMember,
+ InstrumentationValueForType,
+ InstrumentationValueForTypeArgs;
+
+import '../builder/library_builder.dart';
+
+import '../fasta_codes.dart'
+ show
+ messageCantDisambiguateAmbiguousInformation,
+ messageCantDisambiguateNotEnoughInformation,
+ messageNonNullAwareSpreadIsNull,
+ messageSwitchExpressionNotAssignableCause,
+ noLength,
+ templateCantInferTypeDueToCircularity,
+ templateForInLoopElementTypeNotAssignable,
+ templateForInLoopTypeNotIterable,
+ templateIntegerLiteralIsOutOfRange,
+ templateSpreadElementTypeMismatch,
+ templateSpreadMapEntryElementKeyTypeMismatch,
+ templateSpreadMapEntryElementValueTypeMismatch,
+ templateSpreadMapEntryTypeMismatch,
+ templateSpreadTypeMismatch,
+ templateSwitchExpressionNotAssignable,
+ templateUndefinedSetter;
+
+import '../names.dart';
+
+import '../problems.dart' show unhandled;
+
+import '../source/source_library_builder.dart' show SourceLibraryBuilder;
+
+import '../type_inference/type_inference_engine.dart';
+import '../type_inference/type_inferrer.dart';
+
+import '../type_inference/type_schema.dart' show UnknownType;
+
+import '../type_inference/type_schema_elimination.dart' show greatestClosure;
+
+import 'body_builder.dart' show combineStatements;
+
+import 'collections.dart'
+ show
+ ForElement,
+ ForInElement,
+ ForInMapEntry,
+ ForMapEntry,
+ IfElement,
+ IfMapEntry,
+ SpreadElement,
+ SpreadMapEntry,
+ convertToElement;
+
+import 'implicit_type_argument.dart' show ImplicitTypeArgument;
+
+import 'internal_ast.dart';
+
+import 'late_lowering.dart' as late_lowering;
class InferenceVisitor
implements
ExpressionVisitor1<ExpressionInferenceResult, DartType>,
- StatementVisitor<void>,
+ StatementVisitor<StatementInferenceResult>,
InitializerVisitor<void> {
final TypeInferrerImpl inferrer;
@@ -27,6 +93,20 @@
InferenceVisitor(this.inferrer);
+ Expression _clone(Expression node) {
+ if (node is ThisExpression) {
+ return new ThisExpression()..fileOffset = node.fileOffset;
+ } else if (node is VariableGet) {
+ assert(
+ node.variable.isFinal,
+ "Trying to clone VariableGet of non-final variable"
+ " ${node.variable}.");
+ return new VariableGet(node.variable, node.promotedType)
+ ..fileOffset = node.fileOffset;
+ }
+ throw new UnsupportedError("Clone not supported for ${node.runtimeType}.");
+ }
+
ExpressionInferenceResult _unhandledExpression(
Expression node, DartType typeContext) {
unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
@@ -112,19 +192,19 @@
return _unhandledExpression(node, typeContext);
}
- void _unhandledStatement(Statement node) {
- unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
+ StatementInferenceResult _unhandledStatement(Statement node) {
+ return unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
inferrer.helper.uri);
}
@override
- void defaultStatement(Statement node) {
- _unhandledStatement(node);
+ StatementInferenceResult defaultStatement(Statement node) {
+ return _unhandledStatement(node);
}
@override
- void visitAssertBlock(AssertBlock node) {
- _unhandledStatement(node);
+ StatementInferenceResult visitAssertBlock(AssertBlock node) {
+ return _unhandledStatement(node);
}
void _unhandledInitializer(Initializer node) {
@@ -175,11 +255,14 @@
@override
void visitAssertInitializer(AssertInitializer node) {
- inferrer.inferStatement(node.statement);
+ StatementInferenceResult result = inferrer.inferStatement(node.statement);
+ if (result.hasChanged) {
+ node.statement = result.statement..parent = node;
+ }
}
@override
- void visitAssertStatement(AssertStatement node) {
+ StatementInferenceResult visitAssertStatement(AssertStatement node) {
inferrer.flowAnalysis.assert_begin();
InterfaceType expectedType =
inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
@@ -198,6 +281,7 @@
node.message = messageResult.expression..parent = node;
}
inferrer.flowAnalysis.assert_end();
+ return const StatementInferenceResult();
}
@override
@@ -214,12 +298,37 @@
return new ExpressionInferenceResult(inferredType, node);
}
- @override
- void visitBlock(Block node) {
- inferrer.registerIfUnreachableForTesting(node);
- for (Statement statement in node.statements) {
- inferrer.inferStatement(statement);
+ List<Statement> _visitStatements<T extends Statement>(List<T> statements) {
+ List<Statement> result;
+ for (int index = 0; index < statements.length; index++) {
+ T statement = statements[index];
+ StatementInferenceResult statementResult =
+ inferrer.inferStatement(statement);
+ if (statementResult.hasChanged) {
+ if (result == null) {
+ result = <T>[];
+ result.addAll(statements.sublist(0, index));
+ }
+ if (statementResult.statementCount == 1) {
+ result.add(statementResult.statement);
+ } else {
+ result.addAll(statementResult.statements);
+ }
+ } else if (result != null) {
+ result.add(statement);
+ }
}
+ return result;
+ }
+
+ @override
+ StatementInferenceResult visitBlock(Block node) {
+ inferrer.registerIfUnreachableForTesting(node);
+ List<Statement> result = _visitStatements<Statement>(node.statements);
+ return result != null
+ ? new StatementInferenceResult.single(
+ new Block(result)..fileOffset = node.fileOffset)
+ : const StatementInferenceResult();
}
@override
@@ -231,9 +340,10 @@
}
@override
- void visitBreakStatement(BreakStatement node) {
+ StatementInferenceResult visitBreakStatement(BreakStatement node) {
// TODO(johnniwinther): Refactor break/continue encoding.
inferrer.flowAnalysis.handleBreak(node.target);
+ return const StatementInferenceResult();
}
ExpressionInferenceResult visitCascade(Cascade node, DartType typeContext) {
@@ -255,8 +365,19 @@
createVariable(expressionResults[index].expression, const VoidType()),
replacement);
}
- replacement = new Let(node.variable, replacement)
- ..fileOffset = node.fileOffset;
+
+ if (node.isNullAware) {
+ Member equalsMember = inferrer
+ .findInterfaceMember(result.inferredType, equalsName, node.fileOffset)
+ .member;
+ NullAwareGuard nullAwareGuard = new NullAwareGuard(
+ node.variable, node.variable.fileOffset, equalsMember);
+ replacement =
+ nullAwareGuard.createExpression(result.inferredType, replacement);
+ } else {
+ replacement = new Let(node.variable, replacement)
+ ..fileOffset = node.fileOffset;
+ }
return new ExpressionInferenceResult(result.inferredType, replacement);
}
@@ -339,7 +460,8 @@
getExplicitTypeArguments(node.arguments) != null;
DartType inferredType = inferrer.inferInvocation(typeContext,
node.fileOffset, node.target.function.thisFunctionType, node.arguments,
- returnType: computeConstructorReturnType(node.target),
+ returnType:
+ computeConstructorReturnType(node.target, inferrer.coreTypes),
isConst: node.isConst);
if (!inferrer.isTopLevel) {
SourceLibraryBuilder library = inferrer.library;
@@ -353,15 +475,18 @@
}
@override
- void visitContinueSwitchStatement(ContinueSwitchStatement node) {
+ StatementInferenceResult visitContinueSwitchStatement(
+ ContinueSwitchStatement node) {
// No inference needs to be done.
+ return const StatementInferenceResult();
}
ExpressionInferenceResult visitExtensionTearOff(
ExtensionTearOff node, DartType typeContext) {
FunctionType calleeType = node.target != null
? node.target.function.functionType
- : new FunctionType([], const DynamicType(), Nullability.legacy);
+ : new FunctionType(
+ [], const DynamicType(), inferrer.library.nonNullable);
TypeArgumentsInfo typeArgumentsInfo = getTypeArgumentsInfo(node.arguments);
DartType inferredType = inferrer.inferInvocation(
typeContext, node.fileOffset, calleeType, node.arguments);
@@ -465,7 +590,7 @@
Expression writeReceiver;
if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
readReceiver = receiver;
- writeReceiver = receiver.accept<TreeNode>(new CloneVisitor());
+ writeReceiver = _clone(receiver);
} else {
receiverVariable = createVariable(receiver, receiverType);
readReceiver = createVariableGet(receiverVariable);
@@ -565,9 +690,12 @@
}
@override
- void visitDoStatement(DoStatement node) {
+ StatementInferenceResult visitDoStatement(DoStatement node) {
inferrer.flowAnalysis.doStatement_bodyBegin(node);
- inferrer.inferStatement(node.body);
+ StatementInferenceResult bodyResult = inferrer.inferStatement(node.body);
+ if (bodyResult.hasChanged) {
+ node.body = bodyResult.statement..parent = node;
+ }
inferrer.flowAnalysis.doStatement_conditionBegin();
InterfaceType boolType =
inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
@@ -578,6 +706,7 @@
inferrer.ensureAssignableResult(boolType, conditionResult);
node.condition = condition..parent = node;
inferrer.flowAnalysis.doStatement_end(condition);
+ return const StatementInferenceResult();
}
ExpressionInferenceResult visitDoubleLiteral(
@@ -587,16 +716,18 @@
}
@override
- void visitEmptyStatement(EmptyStatement node) {
+ StatementInferenceResult visitEmptyStatement(EmptyStatement node) {
// No inference needs to be done.
+ return const StatementInferenceResult();
}
@override
- void visitExpressionStatement(ExpressionStatement node) {
+ StatementInferenceResult visitExpressionStatement(ExpressionStatement node) {
ExpressionInferenceResult result = inferrer.inferExpression(
node.expression, const UnknownType(), !inferrer.isTopLevel,
isVoidAllowed: true);
node.expression = result.expression..parent = node;
+ return const StatementInferenceResult();
}
ExpressionInferenceResult visitFactoryConstructorInvocationJudgment(
@@ -605,7 +736,8 @@
getExplicitTypeArguments(node.arguments) != null;
DartType inferredType = inferrer.inferInvocation(typeContext,
node.fileOffset, node.target.function.thisFunctionType, node.arguments,
- returnType: computeConstructorReturnType(node.target),
+ returnType:
+ computeConstructorReturnType(node.target, inferrer.coreTypes),
isConst: node.isConst);
node.hasBeenInferred = true;
if (!inferrer.isTopLevel) {
@@ -635,7 +767,7 @@
DartType elementType;
bool typeNeeded = false;
bool typeChecksNeeded = !inferrer.isTopLevel;
- if (VariableDeclarationImpl.isImplicitlyTyped(variable)) {
+ if (variable is VariableDeclarationImpl && variable.isImplicitlyTyped) {
typeNeeded = true;
elementType = const UnknownType();
} else {
@@ -658,7 +790,10 @@
if (body != null) {
inferrer.flowAnalysis
.forEach_bodyBegin(body?.parent, variable, variable.type);
- inferrer.inferStatement(body);
+ StatementInferenceResult bodyResult = inferrer.inferStatement(body);
+ if (bodyResult.hasChanged) {
+ body = bodyResult.statement;
+ }
inferrer.flowAnalysis.forEach_end();
}
@@ -693,7 +828,8 @@
Class iterableClass = isAsync
? inferrer.coreTypes.streamClass
: inferrer.coreTypes.iterableClass;
- DartType context = inferrer.wrapType(elementType, iterableClass);
+ DartType context = inferrer.wrapType(
+ elementType, iterableClass, inferrer.library.nonNullable);
ExpressionInferenceResult iterableResult = inferrer
.inferExpression(iterable, context, typeNeeded, isVoidAllowed: false);
DartType iterableType = iterableResult.inferredType;
@@ -701,7 +837,8 @@
DartType inferredExpressionType =
inferrer.resolveTypeParameter(iterableType);
iterable = inferrer.ensureAssignable(
- inferrer.wrapType(const DynamicType(), iterableClass),
+ inferrer.wrapType(
+ const DynamicType(), iterableClass, inferrer.library.nonNullable),
inferredExpressionType,
iterable,
template: templateForInLoopTypeNotIterable);
@@ -823,14 +960,37 @@
inferrer.flowAnalysis
.forEach_bodyBegin(body.parent, variable, variable.type);
if (body is Block) {
- for (Statement statement in body.statements) {
+ Block block = body;
+ List<Statement> result;
+ for (int index = 0; index < block.statements.length; index++) {
+ Statement statement = block.statements[index];
if (!skipStatement || statement != syntheticStatement) {
- inferrer.inferStatement(statement);
+ StatementInferenceResult statementResult =
+ inferrer.inferStatement(statement);
+ if (statementResult.hasChanged) {
+ if (result == null) {
+ result = <Statement>[];
+ result.addAll(block.statements.sublist(0, index));
+ }
+ if (statementResult.statementCount == 1) {
+ result.add(statementResult.statement);
+ } else {
+ result.addAll(statementResult.statements);
+ }
+ }
+ } else if (result != null) {
+ result.add(statement);
}
}
+ if (result != null) {
+ body = new Block(result)..fileOffset = body.fileOffset;
+ }
} else {
if (!skipStatement) {
- inferrer.inferStatement(body);
+ StatementInferenceResult bodyResult = inferrer.inferStatement(body);
+ if (bodyResult.hasChanged) {
+ body = bodyResult.statement;
+ }
}
}
inferrer.flowAnalysis.forEach_end();
@@ -857,7 +1017,7 @@
}
@override
- void visitForInStatement(ForInStatement node) {
+ StatementInferenceResult visitForInStatement(ForInStatement node) {
ForInResult result;
if (node.variable.name == null) {
result = handleForInWithoutVariable(
@@ -871,11 +1031,14 @@
node.variable = result.variable..parent = node;
node.iterable = result.iterable..parent = node;
node.body = result.body..parent = node;
+ return const StatementInferenceResult();
}
@override
- void visitForStatement(ForStatement node) {
- for (VariableDeclaration variable in node.variables) {
+ StatementInferenceResult visitForStatement(ForStatement node) {
+ List<VariableDeclaration> variables;
+ for (int index = 0; index < node.variables.length; index++) {
+ VariableDeclaration variable = node.variables[index];
if (variable.name == null) {
if (variable.initializer != null) {
ExpressionInferenceResult result = inferrer.inferExpression(
@@ -885,9 +1048,30 @@
variable.type = result.inferredType;
}
} else {
- inferrer.inferStatement(variable);
+ StatementInferenceResult variableResult =
+ inferrer.inferStatement(variable);
+ if (variableResult.hasChanged) {
+ if (variables == null) {
+ variables = <VariableDeclaration>[];
+ variables.addAll(node.variables.sublist(0, index));
+ }
+ if (variableResult.statementCount == 1) {
+ variables.add(variableResult.statement);
+ } else {
+ for (VariableDeclaration variable in variableResult.statements) {
+ variables.add(variable);
+ }
+ }
+ } else if (variables != null) {
+ variables.add(variable);
+ }
}
}
+ if (variables != null) {
+ node.variables.clear();
+ node.variables.addAll(variables);
+ setParents(variables, node);
+ }
inferrer.flowAnalysis.for_conditionBegin(node);
if (node.condition != null) {
InterfaceType expectedType =
@@ -901,7 +1085,10 @@
}
inferrer.flowAnalysis.for_bodyBegin(node.body, node.condition);
- inferrer.inferStatement(node.body);
+ StatementInferenceResult bodyResult = inferrer.inferStatement(node.body);
+ if (bodyResult.hasChanged) {
+ node.body = bodyResult.statement..parent = node;
+ }
inferrer.flowAnalysis.for_updaterBegin();
for (int index = 0; index < node.updates.length; index++) {
ExpressionInferenceResult updateResult = inferrer.inferExpression(
@@ -910,6 +1097,7 @@
node.updates[index] = updateResult.expression..parent = node;
}
inferrer.flowAnalysis.for_end();
+ return const StatementInferenceResult();
}
DartType visitFunctionNode(FunctionNode node, DartType typeContext,
@@ -919,16 +1107,18 @@
}
@override
- void visitFunctionDeclaration(covariant FunctionDeclarationImpl node) {
+ StatementInferenceResult visitFunctionDeclaration(
+ covariant FunctionDeclarationImpl node) {
inferrer.flowAnalysis.functionExpression_begin(node);
inferrer.inferMetadataKeepingHelper(
node.variable, node.variable.annotations);
DartType returnContext =
- node._hasImplicitReturnType ? null : node.function.returnType;
+ node.hasImplicitReturnType ? null : node.function.returnType;
DartType inferredType =
visitFunctionNode(node.function, null, returnContext, node.fileOffset);
node.variable.type = inferredType;
inferrer.flowAnalysis.functionExpression_end();
+ return const StatementInferenceResult();
}
@override
@@ -1001,7 +1191,7 @@
}
@override
- void visitIfStatement(IfStatement node) {
+ StatementInferenceResult visitIfStatement(IfStatement node) {
InterfaceType expectedType =
inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
ExpressionInferenceResult conditionResult = inferrer.inferExpression(
@@ -1011,12 +1201,20 @@
inferrer.ensureAssignableResult(expectedType, conditionResult);
node.condition = condition..parent = node;
inferrer.flowAnalysis.ifStatement_thenBegin(condition);
- inferrer.inferStatement(node.then);
+ StatementInferenceResult thenResult = inferrer.inferStatement(node.then);
+ if (thenResult.hasChanged) {
+ node.then = thenResult.statement..parent = node;
+ }
if (node.otherwise != null) {
inferrer.flowAnalysis.ifStatement_elseBegin();
- inferrer.inferStatement(node.otherwise);
+ StatementInferenceResult otherwiseResult =
+ inferrer.inferStatement(node.otherwise);
+ if (otherwiseResult.hasChanged) {
+ node.otherwise = otherwiseResult.statement..parent = node;
+ }
}
inferrer.flowAnalysis.ifStatement_end(node.otherwise != null);
+ return const StatementInferenceResult();
}
ExpressionInferenceResult visitIntJudgment(
@@ -1100,8 +1298,12 @@
}
@override
- void visitLabeledStatement(LabeledStatement node) {
- inferrer.inferStatement(node.body);
+ StatementInferenceResult visitLabeledStatement(LabeledStatement node) {
+ StatementInferenceResult bodyResult = inferrer.inferStatement(node.body);
+ if (bodyResult.hasChanged) {
+ node.body = bodyResult.statement..parent = node;
+ }
+ return const StatementInferenceResult();
}
DartType getSpreadElementType(DartType spreadType, bool isNullAware) {
@@ -1128,8 +1330,10 @@
if (element is SpreadElement) {
ExpressionInferenceResult spreadResult = inferrer.inferExpression(
element.expression,
- new InterfaceType(inferrer.coreTypes.iterableClass,
- Nullability.legacy, <DartType>[inferredTypeArgument]),
+ new InterfaceType(
+ inferrer.coreTypes.iterableClass,
+ inferrer.library.nullableIfTrue(element.isNullAware),
+ <DartType>[inferredTypeArgument]),
inferenceNeeded || typeChecksNeeded,
isVoidAllowed: true);
element.expression = spreadResult.expression..parent = element;
@@ -1203,21 +1407,45 @@
thenResult.inferredType, otherwiseResult.inferredType),
element);
} else if (element is ForElement) {
- for (VariableDeclaration declaration in element.variables) {
- if (declaration.name == null) {
- if (declaration.initializer != null) {
+ // TODO(johnniwinther): Use _visitStatements instead.
+ List<VariableDeclaration> variables;
+ for (int index = 0; index < element.variables.length; index++) {
+ VariableDeclaration variable = element.variables[index];
+ if (variable.name == null) {
+ if (variable.initializer != null) {
ExpressionInferenceResult initializerResult =
- inferrer.inferExpression(declaration.initializer,
- declaration.type, inferenceNeeded || typeChecksNeeded,
+ inferrer.inferExpression(variable.initializer, variable.type,
+ inferenceNeeded || typeChecksNeeded,
isVoidAllowed: true);
- declaration.initializer = initializerResult.expression
- ..parent = declaration;
- declaration.type = initializerResult.inferredType;
+ variable.initializer = initializerResult.expression
+ ..parent = variable;
+ variable.type = initializerResult.inferredType;
}
} else {
- inferrer.inferStatement(declaration);
+ StatementInferenceResult variableResult =
+ inferrer.inferStatement(variable);
+ if (variableResult.hasChanged) {
+ if (variables == null) {
+ variables = <VariableDeclaration>[];
+ variables.addAll(element.variables.sublist(0, index));
+ }
+ if (variableResult.statementCount == 1) {
+ variables.add(variableResult.statement);
+ } else {
+ for (VariableDeclaration variable in variableResult.statements) {
+ variables.add(variable);
+ }
+ }
+ } else if (variables != null) {
+ variables.add(variable);
+ }
}
}
+ if (variables != null) {
+ element.variables.clear();
+ element.variables.addAll(variables);
+ setParents(variables, element);
+ }
inferrer.flowAnalysis.for_conditionBegin(element);
if (element.condition != null) {
ExpressionInferenceResult conditionResult = inferrer.inferExpression(
@@ -1347,7 +1575,8 @@
ExpressionInferenceResult visitListLiteral(
ListLiteral node, DartType typeContext) {
Class listClass = inferrer.coreTypes.listClass;
- InterfaceType listType = listClass.thisType;
+ InterfaceType listType = inferrer.coreTypes
+ .thisInterfaceType(listClass, inferrer.library.nonNullable);
List<DartType> inferredTypes;
DartType inferredTypeArgument;
List<DartType> formalTypes;
@@ -1364,8 +1593,14 @@
}
if (inferenceNeeded) {
inferredTypes = [const UnknownType()];
- inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(listType,
- listClass.typeParameters, null, null, typeContext, inferredTypes,
+ inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
+ listType,
+ listClass.typeParameters,
+ null,
+ null,
+ typeContext,
+ inferredTypes,
+ inferrer.library.library,
isConst: node.isConst);
inferredTypeArgument = inferredTypes[0];
} else {
@@ -1394,7 +1629,8 @@
formalTypes,
actualTypes,
typeContext,
- inferredTypes);
+ inferredTypes,
+ inferrer.library.library);
inferredTypeArgument = inferredTypes[0];
inferrer.instrumentation?.record(
inferrer.uriForInstrumentation,
@@ -1410,7 +1646,7 @@
}
}
DartType inferredType = new InterfaceType(
- listClass, Nullability.legacy, [inferredTypeArgument]);
+ listClass, inferrer.library.nonNullable, [inferredTypeArgument]);
if (!inferrer.isTopLevel) {
SourceLibraryBuilder library = inferrer.library;
if (inferenceNeeded) {
@@ -1564,7 +1800,9 @@
mapEntryClass ??=
inferrer.coreTypes.index.getClass('dart:core', 'MapEntry');
// TODO(dmitryas): Handle the case of an ambiguous Set.
- entry.entryType = new InterfaceType(mapEntryClass, Nullability.legacy,
+ entry.entryType = new InterfaceType(
+ mapEntryClass,
+ inferrer.library.nonNullable,
<DartType>[actualKeyType, actualValueType]);
bool isMap = inferrer.typeSchemaEnvironment.isSubtypeOf(
@@ -1640,21 +1878,45 @@
}
return entry;
} else if (entry is ForMapEntry) {
- for (VariableDeclaration declaration in entry.variables) {
- if (declaration.name == null) {
- if (declaration.initializer != null) {
+ // TODO(johnniwinther): Use _visitStatements instead.
+ List<VariableDeclaration> variables;
+ for (int index = 0; index < entry.variables.length; index++) {
+ VariableDeclaration variable = entry.variables[index];
+ if (variable.name == null) {
+ if (variable.initializer != null) {
ExpressionInferenceResult result = inferrer.inferExpression(
- declaration.initializer,
- declaration.type,
+ variable.initializer,
+ variable.type,
inferenceNeeded || typeChecksNeeded,
isVoidAllowed: true);
- declaration.initializer = result.expression..parent = declaration;
- declaration.type = result.inferredType;
+ variable.initializer = result.expression..parent = variable;
+ variable.type = result.inferredType;
}
} else {
- inferrer.inferStatement(declaration);
+ StatementInferenceResult variableResult =
+ inferrer.inferStatement(variable);
+ if (variableResult.hasChanged) {
+ if (variables == null) {
+ variables = <VariableDeclaration>[];
+ variables.addAll(entry.variables.sublist(0, index));
+ }
+ if (variableResult.statementCount == 1) {
+ variables.add(variableResult.statement);
+ } else {
+ for (VariableDeclaration variable in variableResult.statements) {
+ variables.add(variable);
+ }
+ }
+ } else if (variables != null) {
+ variables.add(variable);
+ }
}
}
+ if (variables != null) {
+ entry.variables.clear();
+ entry.variables.addAll(variables);
+ setParents(variables, entry);
+ }
inferrer.flowAnalysis.for_conditionBegin(entry);
if (entry.condition != null) {
ExpressionInferenceResult conditionResult = inferrer.inferExpression(
@@ -1820,7 +2082,8 @@
ExpressionInferenceResult visitMapLiteral(
MapLiteral node, DartType typeContext) {
Class mapClass = inferrer.coreTypes.mapClass;
- InterfaceType mapType = mapClass.thisType;
+ InterfaceType mapType = inferrer.coreTypes
+ .thisInterfaceType(mapClass, inferrer.library.nonNullable);
List<DartType> inferredTypes;
DartType inferredKeyType;
DartType inferredValueType;
@@ -1866,8 +2129,14 @@
}
if (inferenceNeeded) {
inferredTypes = [const UnknownType(), const UnknownType()];
- inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(mapType,
- mapClass.typeParameters, null, null, typeContext, inferredTypes,
+ inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
+ mapType,
+ mapClass.typeParameters,
+ null,
+ null,
+ typeContext,
+ inferredTypes,
+ inferrer.library.library,
isConst: node.isConst);
inferredKeyType = inferredTypes[0];
inferredValueType = inferredTypes[1];
@@ -1888,8 +2157,10 @@
spreadTypeContext = inferrer.typeSchemaEnvironment
.getTypeAsInstanceOf(typeContext, inferrer.coreTypes.iterableClass);
} else if (!typeContextIsIterable && typeContextIsMap) {
- spreadTypeContext = new InterfaceType(inferrer.coreTypes.mapClass,
- Nullability.legacy, <DartType>[inferredKeyType, inferredValueType]);
+ spreadTypeContext = new InterfaceType(
+ inferrer.coreTypes.mapClass,
+ inferrer.library.nonNullable,
+ <DartType>[inferredKeyType, inferredValueType]);
}
for (int index = 0; index < node.entries.length; ++index) {
MapEntry entry = node.entries[index];
@@ -1921,7 +2192,8 @@
if (canBeSet && !canBeMap) {
List<Expression> setElements = <Expression>[];
List<DartType> formalTypesForSet = <DartType>[];
- InterfaceType setType = inferrer.coreTypes.setClass.thisType;
+ InterfaceType setType = inferrer.coreTypes.thisInterfaceType(
+ inferrer.coreTypes.setClass, inferrer.library.nonNullable);
for (int i = 0; i < node.entries.length; ++i) {
setElements.add(convertToElement(node.entries[i], inferrer.helper,
inferrer.assignedVariables.reassignInfo));
@@ -1936,14 +2208,17 @@
null,
typeContext,
inferredTypesForSet,
+ inferrer.library.library,
isConst: node.isConst);
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
- inferrer.coreTypes.setClass.thisType,
+ inferrer.coreTypes.thisInterfaceType(
+ inferrer.coreTypes.setClass, inferrer.library.nonNullable),
inferrer.coreTypes.setClass.typeParameters,
formalTypesForSet,
actualTypesForSet,
typeContext,
- inferredTypesForSet);
+ inferredTypesForSet,
+ inferrer.library.library);
DartType inferredTypeArgument = inferredTypesForSet[0];
inferrer.instrumentation?.record(
inferrer.uriForInstrumentation,
@@ -1966,7 +2241,7 @@
}
DartType inferredType = new InterfaceType(inferrer.coreTypes.setClass,
- Nullability.legacy, inferredTypesForSet);
+ inferrer.library.nonNullable, inferredTypesForSet);
return new ExpressionInferenceResult(inferredType, setLiteral);
}
if (canBeSet && canBeMap && node.entries.isNotEmpty) {
@@ -1988,7 +2263,8 @@
formalTypes,
actualTypes,
typeContext,
- inferredTypes);
+ inferredTypes,
+ inferrer.library.library);
inferredKeyType = inferredTypes[0];
inferredValueType = inferredTypes[1];
inferrer.instrumentation?.record(
@@ -2007,8 +2283,8 @@
node.entries[index] = entry..parent = node;
}
}
- DartType inferredType = new InterfaceType(
- mapClass, Nullability.legacy, [inferredKeyType, inferredValueType]);
+ DartType inferredType = new InterfaceType(mapClass,
+ inferrer.library.nonNullable, [inferredKeyType, inferredValueType]);
if (!inferrer.isTopLevel) {
SourceLibraryBuilder library = inferrer.library;
// Either both [_declaredKeyType] and [_declaredValueType] are omitted or
@@ -2134,7 +2410,7 @@
ExpressionInferenceResult visitNullAwareMethodInvocation(
NullAwareMethodInvocation node, DartType typeContext) {
- inferrer.inferStatement(node.variable);
+ inferrer.inferSyntheticVariable(node.variable);
ExpressionInferenceResult invocationResult = inferrer.inferExpression(
node.invocation, typeContext, true,
isVoidAllowed: true);
@@ -2149,7 +2425,7 @@
ExpressionInferenceResult visitNullAwarePropertyGet(
NullAwarePropertyGet node, DartType typeContext) {
- inferrer.inferStatement(node.variable);
+ inferrer.inferSyntheticVariable(node.variable);
ExpressionInferenceResult readResult =
inferrer.inferExpression(node.read, const UnknownType(), true);
Member equalsMember = inferrer
@@ -2163,7 +2439,7 @@
ExpressionInferenceResult visitNullAwarePropertySet(
NullAwarePropertySet node, DartType typeContext) {
- inferrer.inferStatement(node.variable);
+ inferrer.inferSyntheticVariable(node.variable);
ExpressionInferenceResult writeResult =
inferrer.inferExpression(node.write, typeContext, true);
Member equalsMember = inferrer
@@ -2177,7 +2453,7 @@
ExpressionInferenceResult visitNullAwareExtension(
NullAwareExtension node, DartType typeContext) {
- inferrer.inferStatement(node.variable);
+ inferrer.inferSyntheticVariable(node.variable);
ExpressionInferenceResult expressionResult =
inferrer.inferExpression(node.expression, const UnknownType(), true);
Member equalsMember = inferrer
@@ -2191,8 +2467,8 @@
ExpressionInferenceResult visitStaticPostIncDec(
StaticPostIncDec node, DartType typeContext) {
- inferrer.inferStatement(node.read);
- inferrer.inferStatement(node.write);
+ inferrer.inferSyntheticVariable(node.read);
+ inferrer.inferSyntheticVariable(node.write);
DartType inferredType = node.read.type;
Expression replacement =
@@ -2203,8 +2479,8 @@
ExpressionInferenceResult visitSuperPostIncDec(
SuperPostIncDec node, DartType typeContext) {
- inferrer.inferStatement(node.read);
- inferrer.inferStatement(node.write);
+ inferrer.inferSyntheticVariable(node.read);
+ inferrer.inferSyntheticVariable(node.write);
DartType inferredType = node.read.type;
Expression replacement =
@@ -2215,8 +2491,8 @@
ExpressionInferenceResult visitLocalPostIncDec(
LocalPostIncDec node, DartType typeContext) {
- inferrer.inferStatement(node.read);
- inferrer.inferStatement(node.write);
+ inferrer.inferSyntheticVariable(node.read);
+ inferrer.inferSyntheticVariable(node.write);
DartType inferredType = node.read.type;
Expression replacement =
new Let(node.read, createLet(node.write, createVariableGet(node.read)))
@@ -2226,9 +2502,11 @@
ExpressionInferenceResult visitPropertyPostIncDec(
PropertyPostIncDec node, DartType typeContext) {
- inferrer.inferStatement(node.variable);
- inferrer.inferStatement(node.read);
- inferrer.inferStatement(node.write);
+ if (node.variable != null) {
+ inferrer.inferSyntheticVariable(node.variable);
+ }
+ inferrer.inferSyntheticVariable(node.read);
+ inferrer.inferSyntheticVariable(node.write);
DartType inferredType = node.read.type;
Expression replacement;
@@ -2267,7 +2545,7 @@
Expression writeReceiver;
if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
readReceiver = receiver;
- writeReceiver = receiver.accept<TreeNode>(new CloneVisitor());
+ writeReceiver = _clone(receiver);
} else {
receiverVariable = createVariable(receiver, receiverType);
inferrer.instrumentation?.record(
@@ -2312,7 +2590,7 @@
ExpressionInferenceResult visitIfNullPropertySet(
IfNullPropertySet node, DartType typeContext) {
- inferrer.inferStatement(node.variable);
+ inferrer.inferSyntheticVariable(node.variable);
ExpressionInferenceResult readResult = inferrer.inferExpression(
node.read, const UnknownType(), true,
isVoidAllowed: true);
@@ -2409,6 +2687,41 @@
return new ExpressionInferenceResult(inferredType, replacement);
}
+ ExpressionInferenceResult visitIndexGet(IndexGet node, DartType typeContext) {
+ ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+ node.receiver, const UnknownType(), true,
+ isVoidAllowed: true);
+ Expression receiver;
+ NullAwareGuard nullAwareGuard;
+ if (inferrer.isNonNullableByDefault) {
+ nullAwareGuard = receiverResult.nullAwareGuard;
+ receiver = receiverResult.nullAwareAction;
+ } else {
+ receiver = receiverResult.expression;
+ }
+ DartType receiverType = receiverResult.inferredType;
+
+ ObjectAccessTarget indexGetTarget = inferrer.findInterfaceMember(
+ receiverType, indexGetName, node.fileOffset,
+ includeExtensionMethods: true);
+
+ DartType indexType = inferrer.getIndexKeyType(indexGetTarget, receiverType);
+
+ MethodContravarianceCheckKind readCheckKind =
+ inferrer.preCheckInvocationContravariance(receiverType, indexGetTarget,
+ isThisReceiver: node.receiver is ThisExpression);
+
+ ExpressionInferenceResult indexResult = inferrer
+ .inferExpression(node.index, indexType, true, isVoidAllowed: true);
+
+ Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
+
+ ExpressionInferenceResult replacement = _computeIndexGet(node.fileOffset,
+ receiver, receiverType, indexGetTarget, index, readCheckKind);
+ return new ExpressionInferenceResult.nullAware(
+ replacement.inferredType, replacement.expression, nullAwareGuard);
+ }
+
ExpressionInferenceResult visitIndexSet(IndexSet node, DartType typeContext) {
ExpressionInferenceResult receiverResult = inferrer.inferExpression(
node.receiver, const UnknownType(), true,
@@ -2480,7 +2793,7 @@
replacement = createLet(receiverVariable, replacement);
}
}
- replacement..fileOffset = node.fileOffset;
+ replacement.fileOffset = node.fileOffset;
return new ExpressionInferenceResult.nullAware(
inferredType, replacement, nullAwareGuard);
}
@@ -2628,8 +2941,8 @@
VariableDeclaration receiverVariable;
Expression readReceiver = receiver;
Expression writeReceiver;
- if (node.readOnlyReceiver) {
- writeReceiver = readReceiver.accept<TreeNode>(new CloneVisitor());
+ if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+ writeReceiver = _clone(readReceiver);
} else {
receiverVariable = createVariable(readReceiver, receiverType);
readReceiver = createVariableGet(receiverVariable);
@@ -2922,8 +3235,17 @@
Expression receiver =
inferrer.ensureAssignableResult(receiverType, receiverResult);
- VariableDeclaration receiverVariable =
- createVariable(receiver, receiverType);
+ VariableDeclaration receiverVariable;
+ Expression readReceiver;
+ Expression writeReceiver;
+ if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+ readReceiver = receiver;
+ writeReceiver = _clone(receiver);
+ } else {
+ receiverVariable = createVariable(receiver, receiverType);
+ readReceiver = createVariableGet(receiverVariable);
+ writeReceiver = createVariableGet(receiverVariable);
+ }
ObjectAccessTarget readTarget = node.getter != null
? new ExtensionAccessTarget(
@@ -2953,7 +3275,7 @@
ExpressionInferenceResult readResult = _computeIndexGet(
node.readOffset,
- createVariableGet(receiverVariable),
+ readReceiver,
receiverType,
readTarget,
readIndex,
@@ -2984,15 +3306,10 @@
value = createVariableGet(valueVariable);
}
- Expression write = _computeIndexSet(
- node.writeOffset,
- createVariableGet(receiverVariable),
- receiverType,
- writeTarget,
- writeIndex,
- value);
+ Expression write = _computeIndexSet(node.writeOffset, writeReceiver,
+ receiverType, writeTarget, writeIndex, value);
- Expression inner;
+ Expression replacement;
if (node.forEffect) {
// Encode `Extension(o)[a] ??= b` as:
//
@@ -3006,7 +3323,7 @@
ConditionalExpression conditional = new ConditionalExpression(equalsNull,
write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
..fileOffset = node.testOffset;
- inner = createLet(indexVariable, conditional);
+ replacement = createLet(indexVariable, conditional);
} else {
// Encode `Extension(o)[a] ??= b` as:
//
@@ -3034,11 +3351,13 @@
createVariableGet(readVariable),
inferredType)
..fileOffset = node.fileOffset;
- inner = createLet(indexVariable, createLet(readVariable, conditional));
+ replacement =
+ createLet(indexVariable, createLet(readVariable, conditional));
}
-
- Expression replacement = new Let(receiverVariable, inner)
- ..fileOffset = node.fileOffset;
+ if (receiverVariable != null) {
+ replacement = new Let(receiverVariable, replacement);
+ }
+ replacement.fileOffset = node.fileOffset;
return new ExpressionInferenceResult(inferredType, replacement);
}
@@ -3318,7 +3637,8 @@
Expression write;
if (writeTarget.isMissing) {
write = inferrer.createMissingIndexSet(
- fileOffset, receiver, receiverType, index, value);
+ fileOffset, receiver, receiverType, index, value,
+ forEffect: true, readOnlyReceiver: true);
} else if (writeTarget.isExtensionMember) {
assert(writeTarget.extensionMethodKind != ProcedureKind.Setter);
write = new StaticInvocation(
@@ -3513,7 +3833,7 @@
Expression readReceiver = receiver;
Expression writeReceiver;
if (node.readOnlyReceiver) {
- writeReceiver = readReceiver.accept<TreeNode>(new CloneVisitor());
+ writeReceiver = _clone(readReceiver);
} else {
receiverVariable = createVariable(readReceiver, receiverType);
readReceiver = createVariableGet(receiverVariable);
@@ -3528,8 +3848,7 @@
inferrer.preCheckInvocationContravariance(receiverType, readTarget,
isThisReceiver: node.receiver is ThisExpression);
- DartType readIndexType = inferrer.getPositionalParameterTypeForTarget(
- readTarget, receiverType, 0);
+ DartType readIndexType = inferrer.getIndexKeyType(readTarget, receiverType);
ExpressionInferenceResult indexResult = inferrer
.inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
@@ -3564,8 +3883,8 @@
receiverType, indexSetName, node.writeOffset,
includeExtensionMethods: true);
- DartType writeIndexType = inferrer.getPositionalParameterTypeForTarget(
- writeTarget, receiverType, 0);
+ DartType writeIndexType =
+ inferrer.getIndexKeyType(writeTarget, receiverType);
Expression writeIndex = createVariableGet(indexVariable);
writeIndex = inferrer.ensureAssignable(
writeIndexType, indexResult.inferredType, writeIndex);
@@ -3769,8 +4088,8 @@
: const ObjectAccessTarget.missing();
DartType readType = inferrer.getReturnType(readTarget, inferrer.thisType);
- DartType readIndexType = inferrer.getPositionalParameterTypeForTarget(
- readTarget, inferrer.thisType, 0);
+ DartType readIndexType =
+ inferrer.getIndexKeyType(readTarget, inferrer.thisType);
ExpressionInferenceResult indexResult = inferrer
.inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
@@ -3820,8 +4139,8 @@
? new ObjectAccessTarget.interfaceMember(node.setter)
: const ObjectAccessTarget.missing();
- DartType writeIndexType = inferrer.getPositionalParameterTypeForTarget(
- writeTarget, inferrer.thisType, 0);
+ DartType writeIndexType =
+ inferrer.getIndexKeyType(writeTarget, inferrer.thisType);
Expression writeIndex = createVariableGet(indexVariable);
writeIndex = inferrer.ensureAssignable(
writeIndexType, indexResult.inferredType, writeIndex);
@@ -3927,17 +4246,25 @@
node.getter, null, ProcedureKind.Operator, extensionTypeArguments)
: const ObjectAccessTarget.missing();
- DartType receiverType = inferrer.getPositionalParameterTypeForTarget(
- readTarget, receiverResult.inferredType, 0);
+ DartType receiverType = inferrer.getExtensionReceiverType(
+ node.extension, extensionTypeArguments);
Expression receiver =
inferrer.ensureAssignableResult(receiverType, receiverResult);
- VariableDeclaration receiverVariable =
- createVariable(receiver, receiverType);
+ VariableDeclaration receiverVariable;
+ Expression readReceiver;
+ Expression writeReceiver;
+ if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+ readReceiver = receiver;
+ writeReceiver = _clone(receiver);
+ } else {
+ receiverVariable = createVariable(receiver, receiverType);
+ readReceiver = createVariableGet(receiverVariable);
+ writeReceiver = createVariableGet(receiverVariable);
+ }
- DartType readIndexType = inferrer.getPositionalParameterTypeForTarget(
- readTarget, receiverType, 0);
+ DartType readIndexType = inferrer.getIndexKeyType(readTarget, receiverType);
ExpressionInferenceResult indexResult = inferrer
.inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
@@ -3949,7 +4276,7 @@
ExpressionInferenceResult readResult = _computeIndexGet(
node.readOffset,
- createVariableGet(receiverVariable),
+ readReceiver,
receiverType,
readTarget,
readIndex,
@@ -3978,8 +4305,8 @@
node.setter, null, ProcedureKind.Operator, extensionTypeArguments)
: const ObjectAccessTarget.missing();
- DartType writeIndexType = inferrer.getPositionalParameterTypeForTarget(
- writeTarget, receiverType, 0);
+ DartType writeIndexType =
+ inferrer.getIndexSetValueType(writeTarget, receiverType);
Expression writeIndex = createVariableGet(indexVariable);
writeIndex = inferrer.ensureAssignable(
writeIndexType, indexResult.inferredType, writeIndex);
@@ -3998,15 +4325,10 @@
valueExpression = createVariableGet(valueVariable);
}
- Expression write = _computeIndexSet(
- node.writeOffset,
- createVariableGet(receiverVariable),
- receiverType,
- writeTarget,
- writeIndex,
- valueExpression);
+ Expression write = _computeIndexSet(node.writeOffset, writeReceiver,
+ receiverType, writeTarget, writeIndex, valueExpression);
- Expression inner;
+ Expression replacement;
if (node.forEffect) {
assert(leftVariable == null);
assert(valueVariable == null);
@@ -4016,7 +4338,7 @@
// let indexVariable = a in
// receiverVariable.[]=(receiverVariable, o.[](indexVariable) + b)
//
- inner = createLet(indexVariable, write);
+ replacement = createLet(indexVariable, write);
} else if (node.forPostIncDec) {
// Encode `Extension(o)[a]++` as:
//
@@ -4032,7 +4354,7 @@
VariableDeclaration writeVariable =
createVariable(write, const VoidType());
- inner = createLet(
+ replacement = createLet(
indexVariable,
createLet(leftVariable,
createLet(writeVariable, createVariableGet(leftVariable))));
@@ -4051,14 +4373,16 @@
VariableDeclaration writeVariable =
createVariable(write, const VoidType());
- inner = createLet(
+ replacement = createLet(
indexVariable,
createLet(valueVariable,
createLet(writeVariable, createVariableGet(valueVariable))));
}
- Expression replacement = new Let(receiverVariable, inner)
- ..fileOffset = node.fileOffset;
+ if (receiverVariable != null) {
+ replacement = new Let(receiverVariable, replacement);
+ }
+ replacement.fileOffset = node.fileOffset;
return new ExpressionInferenceResult(
node.forPostIncDec ? readType : binaryType, replacement);
}
@@ -4265,13 +4589,14 @@
List<DartType> typeArguments =
new List<DartType>(classTypeParameters.length);
for (int i = 0; i < typeArguments.length; i++) {
- typeArguments[i] =
- new TypeParameterType(classTypeParameters[i], Nullability.legacy);
+ typeArguments[i] = new TypeParameterType.withDefaultNullabilityForLibrary(
+ classTypeParameters[i], inferrer.library.library);
}
ArgumentsImpl.setNonInferrableArgumentTypes(node.arguments, typeArguments);
inferrer.inferInvocation(null, node.fileOffset,
node.target.function.thisFunctionType, node.arguments,
- returnType: node.target.enclosingClass.thisType,
+ returnType: inferrer.coreTypes.thisInterfaceType(
+ node.target.enclosingClass, inferrer.library.nonNullable),
skipTypeArgumentInference: true);
ArgumentsImpl.removeNonInferrableArgumentTypes(node.arguments);
}
@@ -4283,7 +4608,8 @@
}
@override
- void visitReturnStatement(covariant ReturnStatementImpl node) {
+ StatementInferenceResult visitReturnStatement(
+ covariant ReturnStatementImpl node) {
ClosureContext closureContext = inferrer.closureContext;
DartType typeContext = !closureContext.isGenerator
? closureContext.returnOrYieldContext
@@ -4300,13 +4626,15 @@
}
closureContext.handleReturn(inferrer, node, inferredType, node.isArrow);
inferrer.flowAnalysis.handleExit();
+ return const StatementInferenceResult();
}
@override
ExpressionInferenceResult visitSetLiteral(
SetLiteral node, DartType typeContext) {
Class setClass = inferrer.coreTypes.setClass;
- InterfaceType setType = setClass.thisType;
+ InterfaceType setType = inferrer.coreTypes
+ .thisInterfaceType(setClass, inferrer.library.nonNullable);
List<DartType> inferredTypes;
DartType inferredTypeArgument;
List<DartType> formalTypes;
@@ -4323,8 +4651,14 @@
}
if (inferenceNeeded) {
inferredTypes = [const UnknownType()];
- inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(setType,
- setClass.typeParameters, null, null, typeContext, inferredTypes,
+ inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
+ setType,
+ setClass.typeParameters,
+ null,
+ null,
+ typeContext,
+ inferredTypes,
+ inferrer.library.library,
isConst: node.isConst);
inferredTypeArgument = inferredTypes[0];
} else {
@@ -4353,7 +4687,8 @@
formalTypes,
actualTypes,
typeContext,
- inferredTypes);
+ inferredTypes,
+ inferrer.library.library);
inferredTypeArgument = inferredTypes[0];
inferrer.instrumentation?.record(
inferrer.uriForInstrumentation,
@@ -4368,8 +4703,8 @@
inferredSpreadTypes, inferredConditionTypes);
}
}
- DartType inferredType =
- new InterfaceType(setClass, Nullability.legacy, [inferredTypeArgument]);
+ DartType inferredType = new InterfaceType(
+ setClass, inferrer.library.nonNullable, [inferredTypeArgument]);
if (!inferrer.isTopLevel) {
SourceLibraryBuilder library = inferrer.library;
if (inferenceNeeded) {
@@ -4419,7 +4754,8 @@
StaticInvocation node, DartType typeContext) {
FunctionType calleeType = node.target != null
? node.target.function.functionType
- : new FunctionType([], const DynamicType(), Nullability.legacy);
+ : new FunctionType(
+ [], const DynamicType(), inferrer.library.nonNullable);
TypeArgumentsInfo typeArgumentsInfo = getTypeArgumentsInfo(node.arguments);
DartType inferredType = inferrer.inferInvocation(
typeContext, node.fileOffset, calleeType, node.arguments);
@@ -4529,7 +4865,7 @@
}
@override
- void visitSwitchStatement(SwitchStatement node) {
+ StatementInferenceResult visitSwitchStatement(SwitchStatement node) {
ExpressionInferenceResult expressionResult = inferrer.inferExpression(
node.expression, const UnknownType(), true,
isVoidAllowed: false);
@@ -4567,9 +4903,14 @@
]);
}
}
- inferrer.inferStatement(switchCase.body);
+ StatementInferenceResult bodyResult =
+ inferrer.inferStatement(switchCase.body);
+ if (bodyResult.hasChanged) {
+ switchCase.body = bodyResult.statement..parent = switchCase;
+ }
}
inferrer.flowAnalysis.switchStatement_end(hasDefault);
+ return const StatementInferenceResult();
}
@override
@@ -4602,13 +4943,19 @@
if (node.stackTrace != null) {
inferrer.flowAnalysis.initialize(node.stackTrace);
}
- inferrer.inferStatement(node.body);
+ StatementInferenceResult bodyResult = inferrer.inferStatement(node.body);
+ if (bodyResult.hasChanged) {
+ node.body = bodyResult.statement..parent = node;
+ }
}
@override
- void visitTryCatch(TryCatch node) {
+ StatementInferenceResult visitTryCatch(TryCatch node) {
inferrer.flowAnalysis.tryCatchStatement_bodyBegin();
- inferrer.inferStatement(node.body);
+ StatementInferenceResult bodyResult = inferrer.inferStatement(node.body);
+ if (bodyResult.hasChanged) {
+ node.body = bodyResult.statement..parent = node;
+ }
inferrer.flowAnalysis.tryCatchStatement_bodyEnd(node.body);
for (Catch catch_ in node.catches) {
inferrer.flowAnalysis
@@ -4619,15 +4966,24 @@
inferrer.flowAnalysis.tryCatchStatement_catchEnd();
}
inferrer.flowAnalysis.tryCatchStatement_end();
+ return const StatementInferenceResult();
}
@override
- void visitTryFinally(TryFinally node) {
+ StatementInferenceResult visitTryFinally(TryFinally node) {
inferrer.flowAnalysis.tryFinallyStatement_bodyBegin();
- inferrer.inferStatement(node.body);
+ StatementInferenceResult bodyResult = inferrer.inferStatement(node.body);
+ if (bodyResult.hasChanged) {
+ node.body = bodyResult.statement..parent = node;
+ }
inferrer.flowAnalysis.tryFinallyStatement_finallyBegin(node.finalizer);
- inferrer.inferStatement(node.finalizer);
+ StatementInferenceResult finalizerResult =
+ inferrer.inferStatement(node.finalizer);
+ if (finalizerResult.hasChanged) {
+ node.finalizer = finalizerResult.statement..parent = node;
+ }
inferrer.flowAnalysis.tryFinallyStatement_end(node.finalizer);
+ return const StatementInferenceResult();
}
@override
@@ -4641,26 +4997,39 @@
@override
ExpressionInferenceResult visitVariableSet(
VariableSet node, DartType typeContext) {
- DartType writeContext = node.variable.type;
+ VariableDeclarationImpl variable = node.variable;
+ DartType writeContext = variable.type;
ExpressionInferenceResult rhsResult = inferrer.inferExpression(
node.value, writeContext ?? const UnknownType(), true,
isVoidAllowed: true);
Expression rhs = inferrer.ensureAssignableResult(writeContext, rhsResult,
fileOffset: node.fileOffset, isVoidAllowed: writeContext is VoidType);
- node.value = rhs..parent = node;
- inferrer.flowAnalysis.write(node.variable, rhsResult.inferredType);
- return new ExpressionInferenceResult(rhsResult.inferredType, node);
+ inferrer.flowAnalysis.write(variable, rhsResult.inferredType);
+ if (variable.lateSetter != null) {
+ return new ExpressionInferenceResult(
+ rhsResult.inferredType,
+ new MethodInvocation(
+ new VariableGet(variable.lateSetter)
+ ..fileOffset = node.fileOffset,
+ callName,
+ new Arguments(<Expression>[rhs])..fileOffset = node.fileOffset)
+ ..fileOffset = node.fileOffset);
+ } else {
+ node.value = rhs..parent = node;
+ return new ExpressionInferenceResult(rhsResult.inferredType, node);
+ }
}
@override
- void visitVariableDeclaration(covariant VariableDeclarationImpl node) {
+ StatementInferenceResult visitVariableDeclaration(
+ covariant VariableDeclarationImpl node) {
DartType declaredType =
- node._implicitlyTyped ? const UnknownType() : node.type;
+ node.isImplicitlyTyped ? const UnknownType() : node.type;
DartType inferredType;
ExpressionInferenceResult initializerResult;
if (node.initializer != null) {
initializerResult = inferrer.inferExpression(node.initializer,
- declaredType, !inferrer.isTopLevel || node._implicitlyTyped,
+ declaredType, !inferrer.isTopLevel || node.isImplicitlyTyped,
isVoidAllowed: true);
inferredType =
inferrer.inferDeclarationType(initializerResult.inferredType);
@@ -4668,7 +5037,7 @@
} else {
inferredType = const DynamicType();
}
- if (node._implicitlyTyped) {
+ if (node.isImplicitlyTyped) {
inferrer.instrumentation?.record(
inferrer.uriForInstrumentation,
node.fileOffset,
@@ -4684,12 +5053,98 @@
}
if (!inferrer.isTopLevel) {
SourceLibraryBuilder library = inferrer.library;
- if (node._implicitlyTyped) {
+ if (node.isImplicitlyTyped) {
library.checkBoundsInVariableDeclaration(
node, inferrer.typeSchemaEnvironment, inferrer.helper.uri,
inferred: true);
}
}
+ if (node.isLate &&
+ !inferrer.library.loader.target.backendTarget.supportsLateFields) {
+ int fileOffset = node.fileOffset;
+
+ List<Statement> result = <Statement>[];
+ result.add(node);
+
+ VariableDeclaration isSetVariable;
+ if (node.type.isPotentiallyNullable) {
+ isSetVariable = new VariableDeclaration('#${node.name}#isSet',
+ initializer: new BoolLiteral(false)..fileOffset = fileOffset,
+ type: inferrer.coreTypes.boolRawType(inferrer.library.nonNullable))
+ ..fileOffset = fileOffset;
+ result.add(isSetVariable);
+ }
+
+ Expression createVariableRead() => new VariableGet(node);
+ Expression createIsSetRead() => new VariableGet(isSetVariable);
+ Expression createVariableWrite(Expression value) =>
+ new VariableSet(node, value);
+ Expression createIsSetWrite(Expression value) =>
+ new VariableSet(isSetVariable, value);
+
+ VariableDeclaration getVariable =
+ new VariableDeclaration('#${node.name}#get')..fileOffset = fileOffset;
+ FunctionDeclaration getter = new FunctionDeclaration(
+ getVariable,
+ new FunctionNode(
+ node.initializer == null
+ ? late_lowering.createGetterBodyWithoutInitializer(
+ fileOffset, node.name, node.type, 'Local',
+ createVariableRead: createVariableRead,
+ createIsSetRead: createIsSetRead)
+ : late_lowering.createGetterWithInitializer(
+ fileOffset, node.name, node.type, node.initializer,
+ createVariableRead: createVariableRead,
+ createVariableWrite: createVariableWrite,
+ createIsSetRead: createIsSetRead,
+ createIsSetWrite: createIsSetWrite),
+ returnType: node.type))
+ ..fileOffset = fileOffset;
+ getVariable.type = getter.function.functionType;
+ node.lateGetter = getVariable;
+ result.add(getter);
+
+ if (!node.isFinal || node.initializer == null) {
+ VariableDeclaration setVariable =
+ new VariableDeclaration('#${node.name}#set')
+ ..fileOffset = fileOffset;
+ VariableDeclaration setterParameter =
+ new VariableDeclaration(null, type: node.type)
+ ..fileOffset = fileOffset;
+ FunctionDeclaration setter = new FunctionDeclaration(
+ setVariable,
+ new FunctionNode(
+ node.isFinal
+ ? late_lowering.createSetterBodyFinal(fileOffset,
+ node.name, setterParameter, node.type, 'Local',
+ shouldReturnValue: true,
+ createVariableRead: createVariableRead,
+ createVariableWrite: createVariableWrite,
+ createIsSetRead: createIsSetRead,
+ createIsSetWrite: createIsSetWrite)
+ : late_lowering.createSetterBody(
+ fileOffset, node.name, setterParameter, node.type,
+ shouldReturnValue: true,
+ createVariableWrite: createVariableWrite,
+ createIsSetWrite: createIsSetWrite)
+ ..fileOffset = fileOffset,
+ positionalParameters: <VariableDeclaration>[
+ setterParameter
+ ]))
+ // TODO(johnniwinther): Reinsert the file offset when the vm doesn't
+ // use it for function declaration identity.
+ /*..fileOffset = fileOffset*/;
+ setVariable.type = setter.function.functionType;
+ node.lateSetter = setVariable;
+ result.add(setter);
+ }
+ node.isLate = false;
+ node.type = node.type.withNullability(Nullability.nullable);
+ node.initializer = null;
+
+ return new StatementInferenceResult.multiple(node.fileOffset, result);
+ }
+ return const StatementInferenceResult();
}
@override
@@ -4706,9 +5161,9 @@
if (inferrer.isNonNullableByDefault) {
promotedType = inferrer.flowAnalysis.variableRead(node, variable);
} else {
- bool mutatedInClosure = variable._mutatedInClosure;
+ bool mutatedInClosure = variable.mutatedInClosure;
promotedType = inferrer.typePromoter
- .computePromotedType(node._fact, node._scope, mutatedInClosure);
+ .computePromotedType(node.fact, node.scope, mutatedInClosure);
}
if (promotedType != null) {
inferrer.instrumentation?.record(
@@ -4719,15 +5174,24 @@
}
node.promotedType = promotedType;
DartType type = promotedType ?? declaredOrInferredType;
- if (variable._isLocalFunction) {
+ if (variable.isLocalFunction) {
return inferrer.instantiateTearOff(type, typeContext, node);
+ } else if (variable.lateGetter != null) {
+ return new ExpressionInferenceResult(
+ type,
+ new MethodInvocation(
+ new VariableGet(variable.lateGetter)
+ ..fileOffset = node.fileOffset,
+ callName,
+ new Arguments(<Expression>[])..fileOffset = node.fileOffset)
+ ..fileOffset = node.fileOffset);
} else {
return new ExpressionInferenceResult(type, node);
}
}
@override
- void visitWhileStatement(WhileStatement node) {
+ StatementInferenceResult visitWhileStatement(WhileStatement node) {
InterfaceType expectedType =
inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
ExpressionInferenceResult conditionResult = inferrer.inferExpression(
@@ -4736,11 +5200,15 @@
Expression condition =
inferrer.ensureAssignableResult(expectedType, conditionResult);
node.condition = condition..parent = node;
- inferrer.inferStatement(node.body);
+ StatementInferenceResult bodyResult = inferrer.inferStatement(node.body);
+ if (bodyResult.hasChanged) {
+ node.body = bodyResult.statement..parent = node;
+ }
+ return const StatementInferenceResult();
}
@override
- void visitYieldStatement(YieldStatement node) {
+ StatementInferenceResult visitYieldStatement(YieldStatement node) {
ClosureContext closureContext = inferrer.closureContext;
ExpressionInferenceResult expressionResult;
if (closureContext.isGenerator) {
@@ -4750,7 +5218,8 @@
typeContext,
closureContext.isAsync
? inferrer.coreTypes.streamClass
- : inferrer.coreTypes.iterableClass);
+ : inferrer.coreTypes.iterableClass,
+ inferrer.library.nonNullable);
}
expressionResult = inferrer.inferExpression(
node.expression, typeContext, true,
@@ -4761,16 +5230,17 @@
isVoidAllowed: true);
}
closureContext.handleYield(inferrer, node, expressionResult);
+ return const StatementInferenceResult();
}
@override
ExpressionInferenceResult visitLoadLibrary(
covariant LoadLibraryImpl node, DartType typeContext) {
DartType inferredType = inferrer.typeSchemaEnvironment
- .futureType(const DynamicType(), Nullability.legacy);
+ .futureType(const DynamicType(), inferrer.library.nullable);
if (node.arguments != null) {
FunctionType calleeType =
- new FunctionType([], inferredType, Nullability.legacy);
+ new FunctionType([], inferredType, inferrer.library.nonNullable);
inferrer.inferInvocation(
typeContext, node.fileOffset, calleeType, node.arguments);
}
@@ -4782,8 +5252,8 @@
DartType inferredType = new FunctionType(
[],
inferrer.typeSchemaEnvironment
- .futureType(const DynamicType(), Nullability.legacy),
- Nullability.legacy);
+ .futureType(const DynamicType(), inferrer.library.nullable),
+ inferrer.library.nonNullable);
Expression replacement = new StaticGet(node.target)
..fileOffset = node.fileOffset;
return new ExpressionInferenceResult(inferredType, replacement);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
similarity index 95%
rename from pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
rename to pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index ae75f53..b97a372 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -22,48 +22,17 @@
import 'package:kernel/ast.dart';
-import 'package:kernel/type_algebra.dart' show Substitution;
-
-import 'package:kernel/type_environment.dart';
-
-import 'package:kernel/clone.dart';
-
-import '../../base/instrumentation.dart'
- show
- InstrumentationValueForMember,
- InstrumentationValueForType,
- InstrumentationValueForTypeArgs;
-
-import '../builder/library_builder.dart';
+import 'package:kernel/core_types.dart';
import '../fasta_codes.dart'
- show
- messageCantDisambiguateAmbiguousInformation,
- messageCantDisambiguateNotEnoughInformation,
- messageNonNullAwareSpreadIsNull,
- messageSwitchExpressionNotAssignableCause,
- noLength,
- templateCantInferTypeDueToCircularity,
- templateForInLoopElementTypeNotAssignable,
- templateForInLoopTypeNotIterable,
- templateIntegerLiteralIsOutOfRange,
- templateSpreadElementTypeMismatch,
- templateSpreadMapEntryElementKeyTypeMismatch,
- templateSpreadMapEntryElementValueTypeMismatch,
- templateSpreadMapEntryTypeMismatch,
- templateSpreadTypeMismatch,
- templateSwitchExpressionNotAssignable,
- templateUndefinedSetter,
- templateWebLiteralCannotBeRepresentedExactly;
+ show noLength, templateWebLiteralCannotBeRepresentedExactly;
import '../names.dart';
-import '../problems.dart' show unhandled, unsupported;
+import '../problems.dart' show unsupported;
import '../source/source_class_builder.dart' show SourceClassBuilder;
-import '../source/source_library_builder.dart' show SourceLibraryBuilder;
-
import '../type_inference/type_inference_engine.dart';
import '../type_inference/type_inferrer.dart';
@@ -72,33 +41,17 @@
import '../type_inference/type_schema.dart' show UnknownType;
-import '../type_inference/type_schema_elimination.dart' show greatestClosure;
-
import '../type_inference/type_schema_environment.dart'
show TypeSchemaEnvironment;
-import 'body_builder.dart' show combineStatements;
-
-import 'collections.dart'
- show
- ForElement,
- ForInElement,
- ForInMapEntry,
- ForMapEntry,
- IfElement,
- IfMapEntry,
- SpreadElement,
- SpreadMapEntry,
- convertToElement;
-
-import 'implicit_type_argument.dart' show ImplicitTypeArgument;
-
-part "inference_visitor.dart";
+import 'inference_visitor.dart';
/// Computes the return type of a (possibly factory) constructor.
-InterfaceType computeConstructorReturnType(Member constructor) {
+InterfaceType computeConstructorReturnType(
+ Member constructor, CoreTypes coreTypes) {
if (constructor is Constructor) {
- return constructor.enclosingClass.thisType;
+ return coreTypes.thisInterfaceType(
+ constructor.enclosingClass, constructor.enclosingLibrary.nonNullable);
} else {
return constructor.function.returnType;
}
@@ -261,6 +214,7 @@
IfNullPropertySet,
IfNullSet,
IfNullSuperIndexSet,
+ IndexGet,
IndexSet,
LoadLibraryTearOff,
LocalPostIncDec,
@@ -380,6 +334,8 @@
/// initializer;
VariableDeclaration variable;
+ final bool isNullAware;
+
/// The expressions performed on [variable].
final List<Expression> expressions = <Expression>[];
@@ -387,7 +343,7 @@
/// variable. Caller is responsible for ensuring that [variable]'s
/// initializer is the expression preceding the first `..` of the cascade
/// expression.
- Cascade(this.variable) {
+ Cascade(this.variable, {this.isNullAware}) : assert(isNullAware != null) {
variable?.parent = this;
}
@@ -490,7 +446,7 @@
/// Front end specific implementation of [FunctionDeclaration].
class FunctionDeclarationImpl extends FunctionDeclaration {
- bool _hasImplicitReturnType = false;
+ bool hasImplicitReturnType = false;
FunctionDeclarationImpl(
VariableDeclarationImpl variable, FunctionNode function)
@@ -498,7 +454,7 @@
static void setHasImplicitReturnType(
FunctionDeclarationImpl declaration, bool hasImplicitReturnType) {
- declaration._hasImplicitReturnType = hasImplicitReturnType;
+ declaration.hasImplicitReturnType = hasImplicitReturnType;
}
}
@@ -857,7 +813,7 @@
@override
int getVariableFunctionNestingLevel(VariableDeclaration variable) {
if (variable is VariableDeclarationImpl) {
- return variable._functionNestingLevel;
+ return variable.functionNestingLevel;
} else {
// Hack to deal with the fact that BodyBuilder still creates raw
// VariableDeclaration objects sometimes.
@@ -871,7 +827,7 @@
bool isPromotionCandidate(VariableDeclaration variable) {
assert(variable is VariableDeclarationImpl);
VariableDeclarationImpl kernelVariableDeclaration = variable;
- return !kernelVariableDeclaration._isLocalFunction;
+ return !kernelVariableDeclaration.isLocalFunction;
}
@override
@@ -882,7 +838,7 @@
@override
void setVariableMutatedAnywhere(VariableDeclaration variable) {
if (variable is VariableDeclarationImpl) {
- variable._mutatedAnywhere = true;
+ variable.mutatedAnywhere = true;
} else {
// Hack to deal with the fact that BodyBuilder still creates raw
// VariableDeclaration objects sometimes.
@@ -894,7 +850,7 @@
@override
void setVariableMutatedInClosure(VariableDeclaration variable) {
if (variable is VariableDeclarationImpl) {
- variable._mutatedInClosure = true;
+ variable.mutatedInClosure = true;
} else {
// Hack to deal with the fact that BodyBuilder still creates raw
// VariableDeclaration objects sometimes.
@@ -906,7 +862,7 @@
@override
bool wasVariableMutatedAnywhere(VariableDeclaration variable) {
if (variable is VariableDeclarationImpl) {
- return variable._mutatedAnywhere;
+ return variable.mutatedAnywhere;
} else {
// Hack to deal with the fact that BodyBuilder still creates raw
// VariableDeclaration objects sometimes.
@@ -921,25 +877,35 @@
class VariableDeclarationImpl extends VariableDeclaration {
final bool forSyntheticToken;
- final bool _implicitlyTyped;
+ /// Determine whether the given [VariableDeclarationImpl] had an implicit
+ /// type.
+ ///
+ /// This is static to avoid introducing a method that would be visible to
+ /// the kernel.
+ final bool isImplicitlyTyped;
// TODO(ahe): Remove this field. We can get rid of it by recording closure
// mutation in [BodyBuilder].
- final int _functionNestingLevel;
+ final int functionNestingLevel;
// TODO(ahe): Remove this field. It's only used locally when compiling a
// method, and this can thus be tracked in a [Set] (actually, tracking this
// information in a [List] is probably even faster as the average size will
// be close to zero).
- bool _mutatedInClosure = false;
+ bool mutatedInClosure = false;
// TODO(ahe): Investigate if this can be removed.
- bool _mutatedAnywhere = false;
+ bool mutatedAnywhere = false;
+ /// Determines whether the given [VariableDeclarationImpl] represents a
+ /// local function.
+ ///
+ /// This is static to avoid introducing a method that would be visible to the
+ /// kernel.
// TODO(ahe): Investigate if this can be removed.
- final bool _isLocalFunction;
+ final bool isLocalFunction;
- VariableDeclarationImpl(String name, this._functionNestingLevel,
+ VariableDeclarationImpl(String name, this.functionNestingLevel,
{this.forSyntheticToken: false,
Expression initializer,
DartType type,
@@ -950,8 +916,8 @@
bool isLocalFunction: false,
bool isLate: false,
bool isRequired: false})
- : _implicitlyTyped = type == null,
- _isLocalFunction = isLocalFunction,
+ : isImplicitlyTyped = type == null,
+ isLocalFunction = isLocalFunction,
super(name,
initializer: initializer,
type: type ?? const DynamicType(),
@@ -964,42 +930,29 @@
VariableDeclarationImpl.forEffect(Expression initializer)
: forSyntheticToken = false,
- _functionNestingLevel = 0,
- _implicitlyTyped = false,
- _isLocalFunction = false,
+ functionNestingLevel = 0,
+ isImplicitlyTyped = false,
+ isLocalFunction = false,
super.forValue(initializer);
VariableDeclarationImpl.forValue(Expression initializer)
: forSyntheticToken = false,
- _functionNestingLevel = 0,
- _implicitlyTyped = true,
- _isLocalFunction = false,
+ functionNestingLevel = 0,
+ isImplicitlyTyped = true,
+ isLocalFunction = false,
super.forValue(initializer);
- /// Determine whether the given [VariableDeclarationImpl] had an implicit
- /// type.
- ///
- /// This is static to avoid introducing a method that would be visible to
- /// the kernel.
- static bool isImplicitlyTyped(VariableDeclarationImpl variable) =>
- variable._implicitlyTyped;
-
- /// Determines whether the given [VariableDeclarationImpl] represents a
- /// local function.
- ///
- /// This is static to avoid introducing a method that would be visible to the
- /// kernel.
- static bool isLocalFunction(VariableDeclarationImpl variable) =>
- variable._isLocalFunction;
+ VariableDeclaration lateGetter;
+ VariableDeclaration lateSetter;
}
/// Front end specific implementation of [VariableGet].
class VariableGetImpl extends VariableGet {
- final TypePromotionFact _fact;
+ final TypePromotionFact fact;
- final TypePromotionScope _scope;
+ final TypePromotionScope scope;
- VariableGetImpl(VariableDeclaration variable, this._fact, this._scope)
+ VariableGetImpl(VariableDeclaration variable, this.fact, this.scope)
: super(variable);
}
@@ -1567,6 +1520,47 @@
}
}
+/// Internal expression representing an index get expression.
+class IndexGet extends InternalExpression {
+ /// The receiver on which the index set operation is performed.
+ Expression receiver;
+
+ /// The index expression of the operation.
+ Expression index;
+
+ IndexGet(this.receiver, this.index) {
+ receiver?.parent = this;
+ index?.parent = this;
+ }
+
+ @override
+ ExpressionInferenceResult acceptInference(
+ InferenceVisitor visitor, DartType typeContext) {
+ return visitor.visitIndexGet(this, typeContext);
+ }
+
+ @override
+ InternalExpressionKind get kind => InternalExpressionKind.IndexGet;
+
+ @override
+ void visitChildren(Visitor<dynamic> v) {
+ receiver?.accept(v);
+ index?.accept(v);
+ }
+
+ @override
+ void transformChildren(Transformer v) {
+ if (receiver != null) {
+ receiver = receiver.accept<TreeNode>(v);
+ receiver?.parent = this;
+ }
+ if (index != null) {
+ index = index.accept<TreeNode>(v);
+ index?.parent = this;
+ }
+ }
+}
+
/// Internal expression representing an index set expression.
///
/// An index set expression of the form `o[a] = b` used for value is encoded as
@@ -2002,15 +1996,24 @@
/// If `true`, the expression is only need for effect and not for its value.
final bool forEffect;
+ /// If `true`, the receiver is read-only and therefore doesn't need a
+ /// temporary variable for its value.
+ final bool readOnlyReceiver;
+
IfNullExtensionIndexSet(this.extension, this.explicitTypeArguments,
this.receiver, this.getter, this.setter, this.index, this.value,
- {this.readOffset, this.testOffset, this.writeOffset, this.forEffect})
+ {this.readOffset,
+ this.testOffset,
+ this.writeOffset,
+ this.forEffect,
+ this.readOnlyReceiver})
: assert(explicitTypeArguments == null ||
explicitTypeArguments.length == extension.typeParameters.length),
assert(readOffset != null),
assert(testOffset != null),
assert(writeOffset != null),
- assert(forEffect != null) {
+ assert(forEffect != null),
+ assert(readOnlyReceiver != null) {
receiver?.parent = this;
index?.parent = this;
value?.parent = this;
@@ -2474,6 +2477,10 @@
/// If `true`, the expression is a post-fix inc/dec expression.
final bool forPostIncDec;
+ /// If `true` the receiver can be cloned instead of creating a temporary
+ /// variable.
+ final bool readOnlyReceiver;
+
CompoundExtensionIndexSet(
this.extension,
this.explicitTypeArguments,
@@ -2487,14 +2494,16 @@
this.binaryOffset,
this.writeOffset,
this.forEffect,
- this.forPostIncDec})
+ this.forPostIncDec,
+ this.readOnlyReceiver})
: assert(explicitTypeArguments == null ||
explicitTypeArguments.length == extension.typeParameters.length),
assert(readOffset != null),
assert(binaryOffset != null),
assert(writeOffset != null),
assert(forEffect != null),
- assert(forPostIncDec != null) {
+ assert(forPostIncDec != null),
+ assert(readOnlyReceiver != null) {
receiver?.parent = this;
index?.parent = this;
rhs?.parent = this;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
index 975c09a..29365bc 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_api.dart
@@ -82,7 +82,7 @@
VoidType,
setParents;
-export 'kernel_shadow_ast.dart'
+export 'internal_ast.dart'
show
ArgumentsImpl,
Cascade,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 0a6001d..dbd9dfb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -31,11 +31,14 @@
RedirectingInitializer,
Source,
SuperInitializer,
+ Supertype,
TypeParameter,
TypeParameterType,
VariableDeclaration,
VariableGet;
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+
import 'package:kernel/clone.dart' show CloneVisitor;
import 'package:kernel/type_algebra.dart' show substitute;
@@ -44,6 +47,8 @@
import 'package:kernel/type_environment.dart' show TypeEnvironment;
+import 'package:kernel/verifier.dart' show verifyGetStaticType;
+
import '../../api_prototype/file_system.dart' show FileSystem;
import '../builder/builder.dart';
@@ -559,8 +564,9 @@
List<DartType> typeParameterTypes = new List<DartType>();
for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
TypeParameter typeParameter = enclosingClass.typeParameters[i];
- typeParameterTypes
- .add(new TypeParameterType(typeParameter, Nullability.legacy));
+ typeParameterTypes.add(
+ new TypeParameterType.withDefaultNullabilityForLibrary(
+ typeParameter, enclosingClass.enclosingLibrary));
}
return new InterfaceType(
enclosingClass, Nullability.legacy, typeParameterTypes);
@@ -835,6 +841,12 @@
void verify() {
// TODO(ahe): How to handle errors.
verifyComponent(component);
+ ClassHierarchy hierarchy = new ClassHierarchy(component,
+ onAmbiguousSupertypes: (Class cls, Supertype a, Supertype b) {
+ // An error has already been reported.
+ });
+ verifyGetStaticType(
+ new TypeEnvironment(loader.coreTypes, hierarchy), component);
ticker.logMs("Verified component");
}
@@ -866,6 +878,10 @@
}
}
}
+
+ void releaseAncillaryResources() {
+ component = null;
+ }
}
/// Looks for a constructor call that matches `super()` from a constructor in
diff --git a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
new file mode 100644
index 0000000..02f87f8
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
@@ -0,0 +1,222 @@
+// Copyright (c) 2016, 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.
+
+import 'package:kernel/ast.dart' hide MapEntry;
+
+import '../names.dart';
+
+Statement createGetterWithInitializer(
+ int fileOffset, String name, DartType type, Expression initializer,
+ {Expression createVariableRead(),
+ Expression createVariableWrite(Expression value),
+ Expression createIsSetRead(),
+ Expression createIsSetWrite(Expression value)}) {
+ if (type.isPotentiallyNullable) {
+ // Generate:
+ //
+ // if (!_#isSet#field) {
+ // _#isSet#field = true
+ // _#field = <init>;
+ // }
+ // return _#field;
+ return new Block(<Statement>[
+ new IfStatement(
+ new Not(createIsSetRead()..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ new Block(<Statement>[
+ new ExpressionStatement(
+ createIsSetWrite(new BoolLiteral(true)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ new ExpressionStatement(
+ createVariableWrite(initializer)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ ]),
+ null)
+ ..fileOffset = fileOffset,
+ new ReturnStatement(createVariableRead()..fileOffset = fileOffset)
+ ..fileOffset = fileOffset
+ ])
+ ..fileOffset = fileOffset;
+ } else {
+ // Generate:
+ //
+ // return let # = _#field in # == null ? _#field = <init> : #;
+ VariableDeclaration variable = new VariableDeclaration.forValue(
+ createVariableRead()..fileOffset = fileOffset,
+ type: type.withNullability(Nullability.nullable))
+ ..fileOffset = fileOffset;
+ return new ReturnStatement(
+ new Let(
+ variable,
+ new ConditionalExpression(
+ new MethodInvocation(
+ new VariableGet(variable)..fileOffset = fileOffset,
+ equalsName,
+ new Arguments(<Expression>[
+ new NullLiteral()..fileOffset = fileOffset
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ createVariableWrite(initializer)..fileOffset = fileOffset,
+ new VariableGet(variable, type)..fileOffset = fileOffset,
+ type)
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
+ }
+}
+
+Statement createGetterBodyWithoutInitializer(
+ int fileOffset, String name, DartType type, String variableKindName,
+ {Expression createVariableRead(), Expression createIsSetRead()}) {
+ Expression exception = new Throw(
+ new StringLiteral("$variableKindName '${name}' has not been initialized.")
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
+ if (type.isPotentiallyNullable) {
+ // Generate:
+ //
+ // return _#isSet#field ? _#field : throw '...';
+ return new ReturnStatement(
+ new ConditionalExpression(createIsSetRead()..fileOffset = fileOffset,
+ createVariableRead()..fileOffset = fileOffset, exception, type)
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
+ } else {
+ // Generate:
+ //
+ // return let # = _#field in # == null ? throw '...' : #;
+ VariableDeclaration variable = new VariableDeclaration.forValue(
+ createVariableRead()..fileOffset = fileOffset,
+ type: type.withNullability(Nullability.nullable))
+ ..fileOffset = fileOffset;
+ return new ReturnStatement(
+ new Let(
+ variable,
+ new ConditionalExpression(
+ new MethodInvocation(
+ new VariableGet(variable)..fileOffset = fileOffset,
+ equalsName,
+ new Arguments(<Expression>[
+ new NullLiteral()..fileOffset = fileOffset
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ exception,
+ new VariableGet(variable, type)..fileOffset = fileOffset,
+ type)
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
+ }
+}
+
+Statement createSetterBody(
+ int fileOffset, String name, VariableDeclaration parameter, DartType type,
+ {bool shouldReturnValue,
+ Expression createVariableWrite(Expression value),
+ Expression createIsSetWrite(Expression value)}) {
+ Statement createReturn(Expression value) {
+ if (shouldReturnValue) {
+ return new ReturnStatement(value)..fileOffset = fileOffset;
+ } else {
+ return new ExpressionStatement(value)..fileOffset = fileOffset;
+ }
+ }
+
+ Statement assignment = createReturn(
+ createVariableWrite(new VariableGet(parameter)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset);
+
+ if (type.isPotentiallyNullable) {
+ // Generate:
+ //
+ // _#isSet#field = true;
+ // return _#field = parameter
+ //
+ return new Block([
+ new ExpressionStatement(
+ createIsSetWrite(new BoolLiteral(true)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ assignment
+ ])
+ ..fileOffset = fileOffset;
+ } else {
+ // Generate:
+ //
+ // return _#field = parameter
+ //
+ return assignment;
+ }
+}
+
+Statement createSetterBodyFinal(int fileOffset, String name,
+ VariableDeclaration parameter, DartType type, String variableKindName,
+ {bool shouldReturnValue,
+ Expression createVariableRead(),
+ Expression createVariableWrite(Expression value),
+ Expression createIsSetRead(),
+ Expression createIsSetWrite(Expression value)}) {
+ Expression exception = new Throw(
+ new StringLiteral(
+ "${variableKindName} '${name}' has already been initialized.")
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
+
+ Statement createReturn(Expression value) {
+ if (shouldReturnValue) {
+ return new ReturnStatement(value)..fileOffset = fileOffset;
+ } else {
+ return new ExpressionStatement(value)..fileOffset = fileOffset;
+ }
+ }
+
+ if (type.isPotentiallyNullable) {
+ // Generate:
+ //
+ // if (_#isSet#field) {
+ // throw '...';
+ // } else
+ // _#isSet#field = true;
+ // return _#field = parameter
+ // }
+ return new IfStatement(
+ createIsSetRead()..fileOffset = fileOffset,
+ new ExpressionStatement(exception)..fileOffset = fileOffset,
+ new Block([
+ new ExpressionStatement(
+ createIsSetWrite(new BoolLiteral(true)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ createReturn(createVariableWrite(
+ new VariableGet(parameter)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset)
+ ])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
+ } else {
+ // Generate:
+ //
+ // if (_#field == null) {
+ // return _#field = parameter;
+ // } else {
+ // throw '...';
+ // }
+ return new IfStatement(
+ new MethodInvocation(
+ createVariableRead()..fileOffset = fileOffset,
+ equalsName,
+ new Arguments(
+ <Expression>[new NullLiteral()..fileOffset = fileOffset])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset,
+ createReturn(createVariableWrite(
+ new VariableGet(parameter)..fileOffset = fileOffset)
+ ..fileOffset = fileOffset),
+ new ExpressionStatement(exception)..fileOffset = fileOffset,
+ )..fileOffset = fileOffset;
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
index e56558a..5added1 100644
--- a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
@@ -14,7 +14,6 @@
Let,
Member,
NullLiteral,
- Nullability,
Procedure,
StaticGet,
StringLiteral,
@@ -136,8 +135,8 @@
List<DartType> typeArguments = <DartType>[]..length =
member.function.typeParameters.length;
for (int i = 0; i < typeArguments.length; i++) {
- typeArguments[i] = new TypeParameterType(
- member.function.typeParameters[i], Nullability.legacy);
+ typeArguments[i] = new TypeParameterType.withDefaultNullabilityForLibrary(
+ member.function.typeParameters[i], member.enclosingLibrary);
}
// We use the [tortoise and hare algorithm]
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
index 369a2d3..e8ce83d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_collections.dart
@@ -24,6 +24,7 @@
IfStatement,
InterfaceType,
Let,
+ Library,
ListConcatenation,
ListLiteral,
MapConcatenation,
@@ -32,7 +33,6 @@
MethodInvocation,
Name,
Not,
- Nullability,
NullLiteral,
Procedure,
PropertyGet,
@@ -85,6 +85,12 @@
final Field mapEntryValue;
final SourceLoaderDataForTesting dataForTesting;
+ /// Library that contains the transformed nodes.
+ ///
+ /// The transformation of the nodes is affected by the NNBD opt-in status of
+ /// the library.
+ Library _currentLibrary;
+
static Procedure _findSetFactory(CoreTypes coreTypes) {
Procedure factory = coreTypes.index.getMember('dart:core', 'Set', '');
RedirectingFactoryBody body = factory?.function?.body;
@@ -132,13 +138,13 @@
new StaticInvocation(
setFactory, new Arguments([], types: [elementType])),
type: new InterfaceType(
- coreTypes.setClass, Nullability.legacy, [elementType]),
+ coreTypes.setClass, _currentLibrary.nonNullable, [elementType]),
isFinal: true);
} else {
result = new VariableDeclaration.forValue(
new ListLiteral([], typeArgument: elementType),
type: new InterfaceType(
- coreTypes.listClass, Nullability.legacy, [elementType]),
+ coreTypes.listClass, _currentLibrary.nonNullable, [elementType]),
isFinal: true);
}
List<Statement> body = [result];
@@ -335,7 +341,7 @@
// Build a block expression and create an empty map.
VariableDeclaration result = new VariableDeclaration.forValue(
new MapLiteral([], keyType: node.keyType, valueType: node.valueType),
- type: new InterfaceType(coreTypes.mapClass, Nullability.legacy,
+ type: new InterfaceType(coreTypes.mapClass, _currentLibrary.nonNullable,
[node.keyType, node.valueType]),
isFinal: true);
List<Statement> body = [result];
@@ -448,14 +454,16 @@
}
DartType entryType = new InterfaceType(
- mapEntryClass, Nullability.legacy, <DartType>[keyType, valueType]);
+ mapEntryClass,
+ _currentLibrary.nullableIfTrue(entry.isNullAware),
+ <DartType>[keyType, valueType]);
VariableDeclaration elt;
Statement loopBody;
if (entry.entryType == null ||
!typeEnvironment.isSubtypeOf(entry.entryType, entryType,
SubtypeCheckMode.ignoringNullabilities)) {
elt = new VariableDeclaration(null,
- type: new InterfaceType(mapEntryClass, Nullability.legacy,
+ type: new InterfaceType(mapEntryClass, _currentLibrary.nonNullable,
<DartType>[const DynamicType(), const DynamicType()]),
isFinal: true);
VariableDeclaration keyVar = new VariableDeclaration.forValue(
@@ -653,4 +661,18 @@
return new MapConcatenation(parts,
keyType: node.keyType, valueType: node.valueType);
}
+
+ void enterLibrary(Library library) {
+ assert(
+ _currentLibrary == null,
+ "Attempting to enter library '${library.fileUri}' "
+ "without having exited library '${_currentLibrary.fileUri}'.");
+ _currentLibrary = library;
+ }
+
+ void exitLibrary() {
+ assert(_currentLibrary != null,
+ "Attempting to exit a library without having entered one.");
+ _currentLibrary = null;
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart b/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
index 0a61069..7b3a8de 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
@@ -12,9 +12,9 @@
Expression,
InterfaceType,
Let,
+ Library,
MethodInvocation,
Name,
- Nullability,
Procedure,
SetLiteral,
StaticInvocation,
@@ -36,6 +36,12 @@
final Procedure setFactory;
final Procedure addMethod;
+ /// Library that contains the transformed nodes.
+ ///
+ /// The transformation of the nodes is affected by the NNBD opt-in status of
+ /// the library.
+ Library _currentLibrary;
+
static Procedure _findSetFactory(CoreTypes coreTypes) {
Procedure factory = coreTypes.index.getMember('dart:core', 'Set', '');
RedirectingFactoryBody body = factory?.function?.body;
@@ -58,8 +64,8 @@
VariableDeclaration setVar = new VariableDeclaration.forValue(
new StaticInvocation(
setFactory, new Arguments([], types: [node.typeArgument])),
- type: new InterfaceType(
- coreTypes.setClass, Nullability.legacy, [node.typeArgument]));
+ type: new InterfaceType(coreTypes.setClass, _currentLibrary.nonNullable,
+ [node.typeArgument]));
// Innermost body of let chain: setVar
Expression setExp = new VariableGet(setVar);
for (int i = node.expressions.length - 1; i >= 0; i--) {
@@ -75,4 +81,18 @@
}
return new Let(setVar, setExp);
}
+
+ void enterLibrary(Library library) {
+ assert(
+ _currentLibrary == null,
+ "Attempting to enter library '${library.fileUri}' "
+ "without having exited library '${_currentLibrary.fileUri}'.");
+ _currentLibrary = library;
+ }
+
+ void exitLibrary() {
+ assert(_currentLibrary != null,
+ "Attempting to exit a library without having entered one.");
+ _currentLibrary = null;
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/types.dart b/pkg/front_end/lib/src/fasta/kernel/types.dart
index 37a3272..5f75c6d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/types.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/types.dart
@@ -38,15 +38,6 @@
/// Returns true if [s] is a subtype of [t].
bool isSubtypeOfKernel(DartType s, DartType t, SubtypeCheckMode mode) {
- // TODO(dmitryas): Remove InvalidType from subtype relation.
- if (s is InvalidType) {
- // InvalidType is a bottom type.
- return true;
- }
- if (t is InvalidType) {
- return false;
- }
-
IsSubtypeOf result = performNullabilityAwareSubtypeCheck(s, t);
switch (mode) {
case SubtypeCheckMode.withNullabilities:
@@ -75,6 +66,16 @@
if (s is NeverType) {
return new IsSubtypeOf.basedSolelyOnNullabilities(s, t);
}
+
+ // TODO(dmitryas): Remove InvalidType from subtype relation.
+ if (s is InvalidType) {
+ // InvalidType is a bottom type.
+ return const IsSubtypeOf.always();
+ }
+ if (t is InvalidType) {
+ return const IsSubtypeOf.never();
+ }
+
if (t is InterfaceType) {
Class cls = t.classNode;
if (cls == hierarchy.objectClass &&
@@ -275,8 +276,7 @@
hierarchy.coreTypes.functionLegacyRawType;
@override
- InterfaceType futureType(DartType type,
- [Nullability nullability = Nullability.legacy]) {
+ InterfaceType futureType(DartType type, Nullability nullability) {
return new InterfaceType(
hierarchy.coreTypes.futureClass, nullability, <DartType>[type]);
}
@@ -440,8 +440,8 @@
TypeParameter tTypeVariable = tTypeVariables[i];
result = result.and(
types.isSameTypeKernel(sTypeVariable.bound, tTypeVariable.bound));
- typeVariableSubstitution.add(new TypeParameterType(tTypeVariable,
- TypeParameterType.computeNullabilityFromBound(tTypeVariable)));
+ typeVariableSubstitution.add(new TypeParameterType.forAlphaRenaming(
+ sTypeVariable, tTypeVariable));
}
Substitution substitution =
Substitution.fromPairs(sTypeVariables, typeVariableSubstitution);
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index c24a87a..86b1ee5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -16,7 +16,6 @@
Component,
DartType,
Library,
- Nullability,
Procedure,
Supertype,
TreeNode,
@@ -98,7 +97,7 @@
..parent = fakeClass;
typeParams[typeParam] = newNode;
typeSubstitution[typeParam] =
- new TypeParameterType(newNode, Nullability.legacy);
+ new TypeParameterType.forAlphaRenaming(typeParam, newNode);
}
CloneVisitor cloner = new CloneVisitor(
typeSubstitution: typeSubstitution, typeParams: typeParams);
diff --git a/pkg/front_end/lib/src/fasta/scope.dart b/pkg/front_end/lib/src/fasta/scope.dart
index 1fb9f37..c564753 100644
--- a/pkg/front_end/lib/src/fasta/scope.dart
+++ b/pkg/front_end/lib/src/fasta/scope.dart
@@ -14,6 +14,7 @@
import 'builder/name_iterator.dart';
import 'builder/type_variable_builder.dart';
import 'kernel/body_builder.dart' show JumpTarget;
+import 'kernel/class_hierarchy_builder.dart' show ClassMember;
import 'fasta_codes.dart'
show
@@ -644,14 +645,10 @@
}
@override
- void inferType() {
- throw new UnsupportedError('AmbiguousMemberBuilder.inferType');
- }
+ List<ClassMember> get localMembers => const <ClassMember>[];
@override
- void inferCopiedType(covariant Object other) {
- throw new UnsupportedError('AmbiguousMemberBuilder.inferCopiedType');
- }
+ List<ClassMember> get localSetters => const <ClassMember>[];
}
class ScopeLocalDeclarationIterator implements Iterator<Builder> {
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index ade334e..12309a5 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -765,7 +765,7 @@
checkEmpty(token.charOffset);
if (names == null || currentClassIsParserRecovery) return;
- FieldBuilderImpl declaration = lookupBuilder(token, null, names.first);
+ SourceFieldBuilder declaration = lookupBuilder(token, null, names.first);
// TODO(paulberry): don't re-parse the field if we've already parsed it
// for type inference.
parseFields(
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index b27bedc..38b82ea 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -56,6 +56,7 @@
messageInterpolationInUri,
messageOperatorWithOptionalFormals,
messageTypedefNotFunction,
+ messageTypedefNotType,
Template,
templateCycleInTypeVariables,
templateDirectCycleInTypeVariables,
@@ -1440,7 +1441,7 @@
List<TypeVariableBuilder> typeVariables;
Object name;
int charOffset;
- FunctionTypeBuilder functionType;
+ TypeBuilder aliasedType;
if (equals == null) {
List<FormalParameterBuilder> formals = pop();
pop(); // formals offset
@@ -1460,7 +1461,7 @@
TypeParameterScopeKind.functionType, "#function_type",
hasMembers: false);
// TODO(dmitryas): Make sure that RHS of typedefs can't have '?'.
- functionType = library.addFunctionType(returnType, null, formals,
+ aliasedType = library.addFunctionType(returnType, null, formals,
const NullabilityBuilder.omitted(), charOffset);
} else {
Object type = pop();
@@ -1479,7 +1480,13 @@
// `type.typeVariables`. A typedef can have type variables, and a new
// function type can also have type variables (representing the type of
// a generic function).
- functionType = type;
+ aliasedType = type;
+ } else if (library.loader.target.enableNonfunctionTypeAliases) {
+ if (type is TypeBuilder) {
+ aliasedType = type;
+ } else {
+ addProblem(messageTypedefNotType, equals.charOffset, equals.length);
+ }
} else {
// TODO(ahe): Improve this error message.
addProblem(messageTypedefNotFunction, equals.charOffset, equals.length);
@@ -1488,7 +1495,7 @@
List<MetadataBuilder> metadata = pop();
checkEmpty(typedefKeyword.charOffset);
library.addFunctionTypeAlias(documentationComment, metadata, name,
- typeVariables, functionType, charOffset);
+ typeVariables, aliasedType, charOffset);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index b5b5959..3bd7bae 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -116,15 +116,18 @@
declaration.fileUri);
break;
case BuiltMemberKind.ExtensionField:
+ case BuiltMemberKind.LateIsSetField:
kind = ExtensionMemberKind.Field;
break;
case BuiltMemberKind.ExtensionMethod:
kind = ExtensionMemberKind.Method;
break;
case BuiltMemberKind.ExtensionGetter:
+ case BuiltMemberKind.LateGetter:
kind = ExtensionMemberKind.Getter;
break;
case BuiltMemberKind.ExtensionSetter:
+ case BuiltMemberKind.LateSetter:
kind = ExtensionMemberKind.Setter;
break;
case BuiltMemberKind.ExtensionOperator:
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 739d4fb..20b52a4 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -145,7 +145,6 @@
templateIncorrectTypeArgumentInferred,
templateIncorrectTypeArgumentQualified,
templateIncorrectTypeArgumentQualifiedInferred,
- templateIntersectionTypeAsTypeArgument,
templateLanguageVersionTooHigh,
templateLoadLibraryHidesMember,
templateLocalDefinitionHidesExport,
@@ -171,7 +170,7 @@
compareProcedures,
toKernelCombinators;
-import '../kernel/kernel_shadow_ast.dart';
+import '../kernel/internal_ast.dart';
import '../kernel/metadata_collector.dart';
@@ -214,12 +213,14 @@
// TODO(johnniwinther,jensj): Replace this with the correct scheme.
const int enableNonNullableDefaultMajorVersion = 2;
-const int enableNonNullableDefaultMinorVersion = 6;
+const int enableNonNullableDefaultMinorVersion = 7;
class SourceLibraryBuilder extends LibraryBuilderImpl {
static const String MALFORMED_URI_SCHEME = "org-dartlang-malformed-uri";
- final SourceLoader loader;
+ SourceLoader loader;
+
+ bool issueLexicalErrorsOnBodyBuild = false;
final TypeParameterScopeBuilder libraryDeclaration;
@@ -346,7 +347,9 @@
this._nameOrigin)
: currentTypeParameterScopeBuilder = libraryDeclaration,
super(
- fileUri, libraryDeclaration.toScope(importScope), new Scope.top());
+ fileUri, libraryDeclaration.toScope(importScope), new Scope.top()) {
+ library.isNonNullableByDefault = isNonNullableByDefault;
+ }
SourceLibraryBuilder(
Uri uri, Uri fileUri, Loader loader, SourceLibraryBuilder actualOrigin,
@@ -1783,14 +1786,14 @@
if (hasInitializer) {
modifiers |= hasInitializerMask;
}
- FieldBuilderImpl fieldBuilder = new FieldBuilderImpl(
+ SourceFieldBuilder fieldBuilder = new SourceFieldBuilder(
metadata, type, name, modifiers, this, charOffset, charEndOffset);
fieldBuilder.constInitializerToken = constInitializerToken;
addBuilder(name, fieldBuilder, charOffset);
if (type == null && initializerToken != null && fieldBuilder.next == null) {
// Only the first one (the last one in the linked list of next pointers)
// are added to the tree, had parent pointers and can infer correctly.
- fieldBuilder.field.type =
+ fieldBuilder.fieldType =
new ImplicitFieldType(fieldBuilder, initializerToken);
(implicitlyTypedFields ??= <FieldBuilder>[]).add(fieldBuilder);
}
@@ -2006,7 +2009,7 @@
List<MetadataBuilder> metadata,
String name,
List<TypeVariableBuilder> typeVariables,
- FunctionTypeBuilder type,
+ TypeBuilder type,
int charOffset) {
if (typeVariables != null) {
for (TypeVariableBuilder typeVariable in typeVariables) {
@@ -2618,15 +2621,6 @@
message = messageGenericFunctionTypeUsedAsActualTypeArgument;
}
typeParameter = null;
- } else if (argument is TypeParameterType &&
- argument.promotedBound != null) {
- addProblem(
- templateIntersectionTypeAsTypeArgument.withArguments(
- typeParameter.name, argument, argument.promotedBound),
- offset,
- noLength,
- fileUri);
- continue;
} else {
if (issue.enclosingType == null && targetReceiver != null) {
if (issueInferred) {
@@ -2805,8 +2799,8 @@
if (node.arguments.types.isEmpty) return;
Constructor constructor = node.target;
Class klass = constructor.enclosingClass;
- DartType constructedType =
- new InterfaceType(klass, Nullability.legacy, node.arguments.types);
+ DartType constructedType = new InterfaceType(
+ klass, klass.enclosingLibrary.nonNullable, node.arguments.types);
checkBoundsInType(
constructedType, typeEnvironment, fileUri, node.fileOffset,
inferred: inferred, allowSuperBounded: false);
@@ -2819,8 +2813,8 @@
Procedure factory = node.target;
assert(factory.isFactory);
Class klass = factory.enclosingClass;
- DartType constructedType =
- new InterfaceType(klass, Nullability.legacy, node.arguments.types);
+ DartType constructedType = new InterfaceType(
+ klass, klass.enclosingLibrary.nonNullable, node.arguments.types);
checkBoundsInType(
constructedType, typeEnvironment, fileUri, node.fileOffset,
inferred: inferred, allowSuperBounded: false);
@@ -2845,7 +2839,8 @@
if (issues != null) {
DartType targetReceiver;
if (klass != null) {
- targetReceiver = new InterfaceType(klass, Nullability.legacy);
+ targetReceiver =
+ new InterfaceType(klass, klass.enclosingLibrary.nonNullable);
}
String targetName = node.target.name.name;
reportTypeArgumentIssues(issues, fileUri, node.fileOffset,
@@ -2897,8 +2892,9 @@
for (int i = 0; i < instantiatedMethodParameters.length; ++i) {
instantiatedMethodParameters[i] =
new TypeParameter(methodParameters[i].name);
- substitutionMap[methodParameters[i]] = new TypeParameterType(
- instantiatedMethodParameters[i], Nullability.legacy);
+ substitutionMap[methodParameters[i]] =
+ new TypeParameterType.forAlphaRenaming(
+ methodParameters[i], instantiatedMethodParameters[i]);
}
for (int i = 0; i < instantiatedMethodParameters.length; ++i) {
instantiatedMethodParameters[i].bound =
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 085b89a..874292a 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -302,7 +302,10 @@
// We tokenize source files twice to keep memory usage low. This is the
// second time, and the first time was in [buildOutline] above. So this
// time we suppress lexical errors.
- Token tokens = await tokenize(library, suppressLexicalErrors: true);
+ bool suppressLexicalErrors = true;
+ if (library.issueLexicalErrorsOnBodyBuild) suppressLexicalErrors = false;
+ Token tokens =
+ await tokenize(library, suppressLexicalErrors: suppressLexicalErrors);
if (tokens == null) return;
DietListener listener = createDietListener(library);
DietParser parser = new DietParser(listener);
@@ -1043,31 +1046,44 @@
ticker.logMs("Performed top level inference");
}
- void transformPostInference(
- TreeNode node, bool transformSetLiterals, bool transformCollections) {
+ void transformPostInference(TreeNode node, bool transformSetLiterals,
+ bool transformCollections, Library clientLibrary) {
if (transformCollections) {
- node.accept(collectionTransformer ??= new CollectionTransformer(this));
+ collectionTransformer ??= new CollectionTransformer(this);
+ collectionTransformer.enterLibrary(clientLibrary);
+ node.accept(collectionTransformer);
+ collectionTransformer.exitLibrary();
}
if (transformSetLiterals) {
- node.accept(setLiteralTransformer ??= new SetLiteralTransformer(this));
+ setLiteralTransformer ??= new SetLiteralTransformer(this);
+ setLiteralTransformer.enterLibrary(clientLibrary);
+ node.accept(setLiteralTransformer);
+ setLiteralTransformer.exitLibrary();
}
}
- void transformListPostInference(List<TreeNode> list,
- bool transformSetLiterals, bool transformCollections) {
+ void transformListPostInference(
+ List<TreeNode> list,
+ bool transformSetLiterals,
+ bool transformCollections,
+ Library clientLibrary) {
if (transformCollections) {
CollectionTransformer transformer =
collectionTransformer ??= new CollectionTransformer(this);
+ transformer.enterLibrary(clientLibrary);
for (int i = 0; i < list.length; ++i) {
list[i] = list[i].accept(transformer);
}
+ transformer.exitLibrary();
}
if (transformSetLiterals) {
SetLiteralTransformer transformer =
setLiteralTransformer ??= new SetLiteralTransformer(this);
+ transformer.enterLibrary(clientLibrary);
for (int i = 0; i < list.length; ++i) {
list[i] = list[i].accept(transformer);
}
+ transformer.exitLibrary();
}
}
@@ -1105,7 +1121,17 @@
void releaseAncillaryResources() {
hierarchy = null;
+ builderHierarchy = null;
typeInferenceEngine = null;
+ builders?.clear();
+ libraries?.clear();
+ first = null;
+ sourceBytes?.clear();
+ target?.releaseAncillaryResources();
+ coreTypes = null;
+ instrumentation = null;
+ collectionTransformer = null;
+ setLiteralTransformer = null;
}
@override
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 7ff4363..160d2bb 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -52,6 +52,7 @@
bool enableNonNullable;
bool enableTripleShift;
bool enableVariance;
+ bool enableNonfunctionTypeAliases;
TargetImplementation(Ticker ticker, this.uriTranslator, this.backendTarget)
: enableExtensionMethods = CompilerContext.current.options
@@ -62,6 +63,8 @@
.isExperimentEnabled(ExperimentalFlag.tripleShift),
enableVariance = CompilerContext.current.options
.isExperimentEnabled(ExperimentalFlag.variance),
+ enableNonfunctionTypeAliases = CompilerContext.current.options
+ .isExperimentEnabled(ExperimentalFlag.nonfunctionTypeAliases),
super(ticker);
/// Creates a [LibraryBuilder] corresponding to [uri], if one doesn't exist
@@ -191,4 +194,6 @@
throw new StateError("Unparsable sdk version given: $currentSdkVersion");
}
}
+
+ void releaseAncillaryResources();
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/replacement_visitor.dart b/pkg/front_end/lib/src/fasta/type_inference/replacement_visitor.dart
new file mode 100644
index 0000000..ddcfb58
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/type_inference/replacement_visitor.dart
@@ -0,0 +1,124 @@
+// Copyright (c) 2017, 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.md file.
+
+import 'package:kernel/ast.dart' hide MapEntry;
+
+/// Helper visitor that clones a type if a nested type is replaced, and
+/// otherwise returns `null`.
+class ReplacementVisitor implements DartTypeVisitor<DartType> {
+ const ReplacementVisitor();
+
+ void changeVariance() {}
+
+ @override
+ DartType visitFunctionType(FunctionType node) {
+ DartType newReturnType = node.returnType.accept(this);
+ changeVariance();
+ List<DartType> newPositionalParameters = null;
+ for (int i = 0; i < node.positionalParameters.length; i++) {
+ DartType substitution = node.positionalParameters[i].accept(this);
+ if (substitution != null) {
+ newPositionalParameters ??=
+ node.positionalParameters.toList(growable: false);
+ newPositionalParameters[i] = substitution;
+ }
+ }
+ List<NamedType> newNamedParameters = null;
+ for (int i = 0; i < node.namedParameters.length; i++) {
+ DartType substitution = node.namedParameters[i].type.accept(this);
+ if (substitution != null) {
+ newNamedParameters ??= node.namedParameters.toList(growable: false);
+ newNamedParameters[i] = new NamedType(
+ node.namedParameters[i].name, substitution,
+ isRequired: node.namedParameters[i].isRequired);
+ }
+ }
+ changeVariance();
+ DartType typedefType = node.typedefType?.accept(this);
+ if (newReturnType == null &&
+ newPositionalParameters == null &&
+ newNamedParameters == null &&
+ typedefType == null) {
+ // No types had to be substituted.
+ return null;
+ } else {
+ return new FunctionType(
+ newPositionalParameters ?? node.positionalParameters,
+ newReturnType ?? node.returnType,
+ node.nullability,
+ namedParameters: newNamedParameters ?? node.namedParameters,
+ typeParameters: node.typeParameters,
+ requiredParameterCount: node.requiredParameterCount,
+ typedefType: typedefType);
+ }
+ }
+
+ @override
+ DartType visitInterfaceType(InterfaceType node) {
+ List<DartType> newTypeArguments = null;
+ for (int i = 0; i < node.typeArguments.length; i++) {
+ DartType substitution = node.typeArguments[i].accept(this);
+ if (substitution != null) {
+ newTypeArguments ??= node.typeArguments.toList(growable: false);
+ newTypeArguments[i] = substitution;
+ }
+ }
+ if (newTypeArguments == null) {
+ // No type arguments needed to be substituted.
+ return null;
+ } else {
+ return new InterfaceType(
+ node.classNode, node.nullability, newTypeArguments);
+ }
+ }
+
+ @override
+ DartType visitDynamicType(DynamicType node) => null;
+
+ @override
+ DartType visitNeverType(NeverType node) => null;
+
+ @override
+ DartType visitInvalidType(InvalidType node) => null;
+
+ @override
+ DartType visitBottomType(BottomType node) => null;
+
+ @override
+ DartType visitVoidType(VoidType node) => null;
+
+ @override
+ DartType visitTypeParameterType(TypeParameterType node) {
+ if (node.promotedBound != null) {
+ DartType newPromotedBound = node.promotedBound.accept(this);
+ if (newPromotedBound != null) {
+ return new TypeParameterType(node.parameter,
+ node.typeParameterTypeNullability, newPromotedBound);
+ }
+ }
+ return null;
+ }
+
+ @override
+ DartType visitTypedefType(TypedefType node) {
+ List<DartType> newTypeArguments = null;
+ for (int i = 0; i < node.typeArguments.length; i++) {
+ DartType substitution = node.typeArguments[i].accept(this);
+ if (substitution != null) {
+ newTypeArguments ??= node.typeArguments.toList(growable: false);
+ newTypeArguments[i] = substitution;
+ }
+ }
+ if (newTypeArguments == null) {
+ // No type arguments needed to be substituted.
+ return null;
+ } else {
+ return new TypedefType(
+ node.typedefNode, node.nullability, newTypeArguments);
+ }
+ }
+
+ @override
+ DartType defaultDartType(DartType node) => null;
+}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart b/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
index 6b1f45a..67147c8 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
@@ -14,7 +14,6 @@
InterfaceType,
InvalidType,
NamedType,
- Nullability,
TypeParameter,
TypeParameterType,
Variance,
@@ -24,6 +23,8 @@
import 'package:kernel/type_environment.dart' show SubtypeCheckMode;
+import 'package:kernel/src/future_or.dart';
+
import 'type_schema.dart' show UnknownType;
abstract class StandardBounds {
@@ -111,18 +112,22 @@
if (type2 is InterfaceType) {
if (type2.classNode == futureOrClass) {
// GLB(FutureOr<A>, FutureOr<B>) == FutureOr<GLB(A, B)>
+ DartType argument = getStandardLowerBound(
+ type1.typeArguments[0], type2.typeArguments[0]);
return new InterfaceType(
- futureOrClass, Nullability.legacy, <DartType>[
- getStandardLowerBound(
- type1.typeArguments[0], type2.typeArguments[0])
- ]);
+ futureOrClass, argument.nullability, <DartType>[argument]);
}
if (type2.classNode == futureClass) {
// GLB(FutureOr<A>, Future<B>) == Future<GLB(A, B)>
- return new InterfaceType(futureClass, Nullability.legacy, <DartType>[
- getStandardLowerBound(
- type1.typeArguments[0], type2.typeArguments[0])
- ]);
+ return new InterfaceType(
+ futureClass,
+ intersectNullabilities(
+ computeNullabilityOfFutureOr(type1, futureOrClass),
+ type2.nullability),
+ <DartType>[
+ getStandardLowerBound(
+ type1.typeArguments[0], type2.typeArguments[0])
+ ]);
}
}
// GLB(FutureOr<A>, B) == GLB(A, B)
@@ -136,9 +141,14 @@
if (type2 is InterfaceType && type2.classNode == futureOrClass) {
if (type1 is InterfaceType && type1.classNode == futureClass) {
// GLB(Future<A>, FutureOr<B>) == Future<GLB(B, A)>
- return new InterfaceType(futureClass, Nullability.legacy, <DartType>[
- getStandardLowerBound(type2.typeArguments[0], type1.typeArguments[0])
- ]);
+ return new InterfaceType(
+ futureClass,
+ intersectNullabilities(type1.nullability,
+ computeNullabilityOfFutureOr(type2, futureOrClass)),
+ <DartType>[
+ getStandardLowerBound(
+ type2.typeArguments[0], type1.typeArguments[0])
+ ]);
}
// GLB(A, FutureOr<B>) == GLB(B, A)
return getStandardLowerBound(type2.typeArguments[0], type1);
@@ -317,8 +327,8 @@
// Calculate the SLB of the return type.
DartType returnType = getStandardLowerBound(f.returnType, g.returnType);
- return new FunctionType(
- positionalParameters, returnType, Nullability.legacy,
+ return new FunctionType(positionalParameters, returnType,
+ intersectNullabilities(f.nullability, g.nullability),
namedParameters: namedParameters,
requiredParameterCount: requiredParameterCount);
}
@@ -345,7 +355,9 @@
// SUB(([int]) -> void, (int) -> void) = (int) -> void
if (f.requiredParameterCount != g.requiredParameterCount) {
return new InterfaceType(
- functionClass, Nullability.legacy, const <DynamicType>[]);
+ functionClass,
+ uniteNullabilities(f.nullability, g.nullability),
+ const <DynamicType>[]);
}
int requiredParameterCount = f.requiredParameterCount;
@@ -392,8 +404,8 @@
// Calculate the SUB of the return type.
DartType returnType = getStandardUpperBound(f.returnType, g.returnType);
- return new FunctionType(
- positionalParameters, returnType, Nullability.legacy,
+ return new FunctionType(positionalParameters, returnType,
+ uniteNullabilities(f.nullability, g.nullability),
namedParameters: namedParameters,
requiredParameterCount: requiredParameterCount);
}
@@ -453,7 +465,8 @@
tArgs[i] = getStandardUpperBound(tArgs1[i], tArgs2[i]);
}
}
- return new InterfaceType(type1.classNode, Nullability.legacy, tArgs);
+ return new InterfaceType(type1.classNode,
+ uniteNullabilities(type1.nullability, type2.nullability), tArgs);
}
return getLegacyLeastUpperBound(type1, type2);
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
index 691ecdb..c71249a 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
@@ -9,6 +9,7 @@
DynamicType,
FunctionType,
InterfaceType,
+ Library,
Member,
Name,
NamedType,
@@ -21,10 +22,11 @@
import 'package:kernel/type_algebra.dart' show substitute, Substitution;
-import 'type_schema.dart' show UnknownType;
+import 'package:kernel/type_environment.dart';
-import 'type_schema_environment.dart'
- show TypeConstraint, TypeSchemaEnvironment, substituteTypeParams;
+import 'package:kernel/src/future_or.dart';
+
+import 'type_schema.dart' show UnknownType;
import '../names.dart' show callName;
@@ -39,14 +41,18 @@
final List<TypeParameter> _parametersToConstrain;
+ final Library _currentLibrary;
+
/// Creates a [TypeConstraintGatherer] which is prepared to gather type
/// constraints for the given [typeParameters].
- TypeConstraintGatherer.subclassing(Iterable<TypeParameter> typeParameters)
+ TypeConstraintGatherer.subclassing(
+ Iterable<TypeParameter> typeParameters, this._currentLibrary)
: _parametersToConstrain = typeParameters.toList();
factory TypeConstraintGatherer(TypeSchemaEnvironment environment,
- Iterable<TypeParameter> typeParameters) {
- return new TypeSchemaConstraintGatherer(environment, typeParameters);
+ Iterable<TypeParameter> typeParameters, Library currentLibrary) {
+ return new TypeSchemaConstraintGatherer(
+ environment, typeParameters, currentLibrary);
}
Class get objectClass;
@@ -298,9 +304,12 @@
// constraints `C0`.
// - And `P` is a subtype match for `Q` with respect to `L` under
// constraints `C1`.
- InterfaceType subtypeFuture = futureType(subtypeArg, Nullability.legacy);
+ InterfaceType subtypeFuture =
+ futureType(subtypeArg, _currentLibrary.nonNullable);
return _isSubtypeMatch(subtypeFuture, supertype) &&
- _isSubtypeMatch(subtypeArg, supertype);
+ _isSubtypeMatch(subtypeArg, supertype) &&
+ new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype)
+ .isSubtypeWhenUsingNullabilities();
}
if (supertype is InterfaceType &&
@@ -313,8 +322,24 @@
// under constraints `C`
// - And `P` is a subtype match for `Q` with respect to `L` under
// constraints `C`
- DartType supertypeArg = supertype.typeArguments[0];
- DartType supertypeFuture = futureType(supertypeArg, Nullability.legacy);
+
+ // Since FutureOr<S> is a union type Future<S> U S where U denotes the
+ // union operation on types, T? is T U Null, T U T = T, S U T = T U S, and
+ // S U (T U V) = (S U T) U V, the following is true:
+ //
+ // - FutureOr<S?> = S? U Future<S?>?
+ // - FutureOr<S>? = S? U Future<S>?
+ //
+ // To compute the nullabilities for the two types in the union, the
+ // nullability of the argument and the declared nullability of FutureOr
+ // should be united. Also, computeNullability is used to fetch the
+ // nullability of the argument because it can be a FutureOr itself.
+ Nullability unitedNullability = uniteNullabilities(
+ computeNullability(supertype.typeArguments[0], futureOrClass),
+ supertype.nullability);
+ DartType supertypeArg =
+ supertype.typeArguments[0].withNullability(unitedNullability);
+ DartType supertypeFuture = futureType(supertypeArg, unitedNullability);
// The match against FutureOr<X> succeeds if the match against either
// Future<X> or X succeeds. If they both succeed, the one adding new
@@ -419,7 +444,7 @@
TypeParameter pFresh = new TypeParameter(params2[i].name);
freshTypeVariables.add(pFresh);
DartType variableFresh =
- new TypeParameterType(pFresh, Nullability.legacy);
+ new TypeParameterType.forAlphaRenaming(params2[i], pFresh);
substitution1[params1[i]] = variableFresh;
substitution2[params2[i]] = variableFresh;
DartType bound1 = substitute(params1[i].bound, substitution1);
@@ -434,9 +459,9 @@
class TypeSchemaConstraintGatherer extends TypeConstraintGatherer {
final TypeSchemaEnvironment environment;
- TypeSchemaConstraintGatherer(
- this.environment, Iterable<TypeParameter> typeParameters)
- : super.subclassing(typeParameters);
+ TypeSchemaConstraintGatherer(this.environment,
+ Iterable<TypeParameter> typeParameters, Library currentLibrary)
+ : super.subclassing(typeParameters, currentLibrary);
@override
Class get objectClass => environment.coreTypes.objectClass;
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart b/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart
new file mode 100644
index 0000000..1e67390
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2019, 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.md file.
+
+import 'package:kernel/ast.dart' hide MapEntry;
+
+import 'replacement_visitor.dart';
+
+/// Returns `true` if type contains a promoted type variable.
+bool hasPromotedTypeVariable(DartType type) {
+ return type.accept(const _HasPromotedTypeVariableVisitor());
+}
+
+/// Visitor that returns `true` if a type contains a promoted type variable.
+class _HasPromotedTypeVariableVisitor extends DartTypeVisitor<bool> {
+ const _HasPromotedTypeVariableVisitor();
+
+ @override
+ bool defaultDartType(DartType node) => false;
+
+ @override
+ bool visitFunctionType(FunctionType node) {
+ if (node.returnType.accept(this)) return true;
+ for (DartType parameterType in node.positionalParameters) {
+ if (parameterType.accept(this)) return true;
+ }
+ for (NamedType namedParameterType in node.namedParameters) {
+ if (namedParameterType.type.accept(this)) return true;
+ }
+ if (node.typedefType != null && node.typedefType.accept(this)) {
+ return true;
+ }
+ return false;
+ }
+
+ @override
+ bool visitInterfaceType(InterfaceType node) {
+ for (DartType typeArgument in node.typeArguments) {
+ if (typeArgument.accept(this)) return true;
+ }
+ return false;
+ }
+
+ @override
+ bool visitTypedefType(TypedefType node) {
+ for (DartType typeArgument in node.typeArguments) {
+ if (typeArgument.accept(this)) return true;
+ }
+ return false;
+ }
+
+ @override
+ bool visitTypeParameterType(TypeParameterType node) {
+ return node.promotedBound != null;
+ }
+}
+
+/// Returns [type] in which all promoted type variables have been replace with
+/// their unpromoted equivalents.
+DartType demoteType(DartType type) {
+ return type.accept(const _TypeVariableDemotion()) ?? type;
+}
+
+/// Visitor that replaces all promoted type variables the type variable itself.
+///
+/// The visitor returns `null` if the type wasn't changed.
+class _TypeVariableDemotion extends ReplacementVisitor {
+ const _TypeVariableDemotion();
+
+ @override
+ DartType visitTypeParameterType(TypeParameterType node) {
+ if (node.promotedBound != null) {
+ return new TypeParameterType(
+ node.parameter, node.typeParameterTypeNullability);
+ }
+ return node;
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index 696f7a4..609f21b 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -199,11 +199,7 @@
if (member is Field) {
DartType type = member.type;
if (type is ImplicitFieldType) {
- if (type.memberBuilder.member != member) {
- type.memberBuilder.inferCopiedType(member);
- } else {
- type.memberBuilder.inferType();
- }
+ type.inferType();
}
}
return member;
@@ -301,7 +297,8 @@
}
if (from is TypeParameterType) {
if (isSubtypeOf(to, from.promotedBound ?? from.bound)) {
- return new TypeParameterType(from.parameter, from.nullability, to);
+ return new TypeParameterType.intersection(
+ from.parameter, from.nullability, to);
}
}
return from;
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index ec83820..8db173a 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -6,7 +6,8 @@
import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
-import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart';
+import 'package:front_end/src/fasta/kernel/internal_ast.dart';
+import 'package:front_end/src/fasta/type_inference/type_demotion.dart';
import 'package:kernel/ast.dart';
@@ -32,14 +33,14 @@
import '../fasta_codes.dart';
-import '../kernel/expression_generator.dart' show buildIsNull;
-
-import '../kernel/kernel_shadow_ast.dart'
+import '../kernel/internal_ast.dart'
show
VariableDeclarationImpl,
getExplicitTypeArguments,
getExtensionTypeParameterCount;
+import '../kernel/inference_visitor.dart';
+
import '../kernel/type_algorithms.dart' show hasAnyTypeVariables;
import '../names.dart';
@@ -303,7 +304,8 @@
return;
}
DartType expectedType = node.isYieldStar
- ? _wrapAsyncOrGenerator(inferrer, returnOrYieldContext)
+ ? _wrapAsyncOrGenerator(
+ inferrer, returnOrYieldContext, inferrer.library.nonNullable)
: returnOrYieldContext;
Expression expression = inferrer.ensureAssignableResult(
expectedType, expressionResult,
@@ -344,7 +346,8 @@
inferredType = greatestClosure(inferrer.coreTypes, returnOrYieldContext);
}
- inferredType = _wrapAsyncOrGenerator(inferrer, inferredType);
+ inferredType = _wrapAsyncOrGenerator(
+ inferrer, inferredType, inferrer.library.nonNullable);
for (int i = 0; i < returnStatements.length; ++i) {
checkValidReturn(inferrer, inferredType, returnStatements[i],
returnExpressionTypes[i]);
@@ -353,15 +356,18 @@
return inferredType;
}
- DartType _wrapAsyncOrGenerator(TypeInferrerImpl inferrer, DartType type) {
+ DartType _wrapAsyncOrGenerator(
+ TypeInferrerImpl inferrer, DartType type, Nullability nullability) {
if (isGenerator) {
if (isAsync) {
- return inferrer.wrapType(type, inferrer.coreTypes.streamClass);
+ return inferrer.wrapType(
+ type, inferrer.coreTypes.streamClass, nullability);
} else {
- return inferrer.wrapType(type, inferrer.coreTypes.iterableClass);
+ return inferrer.wrapType(
+ type, inferrer.coreTypes.iterableClass, nullability);
}
} else if (isAsync) {
- return inferrer.wrapFutureType(type);
+ return inferrer.wrapFutureType(type, nullability);
} else {
return type;
}
@@ -408,7 +414,7 @@
InferenceHelper helper, DartType declaredType, Expression initializer);
/// Performs type inference on the given function body.
- void inferFunctionBody(InferenceHelper helper, DartType returnType,
+ Statement inferFunctionBody(InferenceHelper helper, DartType returnType,
AsyncMarker asyncMarker, FunctionNode function, Statement body);
/// Performs type inference on the given constructor initializer.
@@ -578,7 +584,8 @@
// and Future<T>.
DartType unfuturedExpectedType =
typeSchemaEnvironment.unfutureType(expectedType);
- DartType futuredExpectedType = wrapFutureType(unfuturedExpectedType);
+ DartType futuredExpectedType =
+ wrapFutureType(unfuturedExpectedType, library.nonNullable);
if (isAssignable(unfuturedExpectedType, actualType)) {
expectedType = unfuturedExpectedType;
} else if (isAssignable(futuredExpectedType, actualType)) {
@@ -607,8 +614,12 @@
VariableDeclaration t =
new VariableDeclaration.forValue(expression, type: actualType)
..fileOffset = fileOffset;
- Expression nullCheck =
- buildIsNull(new VariableGet(t), fileOffset, helper);
+ Expression nullCheck = new MethodInvocation(
+ new VariableGet(t),
+ equalsName,
+ new Arguments(
+ <Expression>[new NullLiteral()..fileOffset = fileOffset]))
+ ..fileOffset = fileOffset;
PropertyGet tearOff =
new PropertyGet(new VariableGet(t), callName, callMember)
..fileOffset = fileOffset;
@@ -702,8 +713,8 @@
DartType onType = extension.onType;
List<DartType> inferredTypes =
new List<DartType>.filled(typeParameters.length, const UnknownType());
- typeSchemaEnvironment.inferGenericFunctionOrType(
- null, typeParameters, [onType], [receiverType], null, inferredTypes);
+ typeSchemaEnvironment.inferGenericFunctionOrType(null, typeParameters,
+ [onType], [receiverType], null, inferredTypes, library.library);
return inferredTypes;
}
@@ -727,7 +738,7 @@
receiverType = resolveTypeParameter(receiverType);
- if (receiverType is FunctionType && name.name == 'call') {
+ if (receiverType is FunctionType && name == callName) {
return const ObjectAccessTarget.callFunction();
}
@@ -745,7 +756,7 @@
target = const ObjectAccessTarget.invalid();
} else if (receiverType is InterfaceType &&
receiverType.classNode == coreTypes.functionClass &&
- name.name == 'call') {
+ name == callName) {
target = const ObjectAccessTarget.callFunction();
} else {
target = const ObjectAccessTarget.missing();
@@ -949,7 +960,7 @@
return substitution.substituteType(new FunctionType(
functionType.positionalParameters.skip(1).toList(),
functionType.returnType,
- Nullability.legacy,
+ library.nonNullable,
namedParameters: functionType.namedParameters,
typeParameters: functionType.typeParameters
.skip(target.inferredExtensionTypeArguments.length)
@@ -1415,6 +1426,19 @@
return initializerType;
}
+ void inferSyntheticVariable(VariableDeclarationImpl variable) {
+ assert(variable.isImplicitlyTyped);
+ assert(variable.initializer != null);
+ ExpressionInferenceResult result = inferExpression(
+ variable.initializer, const UnknownType(), true,
+ isVoidAllowed: true);
+ variable.initializer = result.expression..parent = variable;
+ DartType inferredType = inferDeclarationType(result.inferredType);
+ instrumentation?.record(uriForInstrumentation, variable.fileOffset, 'type',
+ new InstrumentationValueForType(inferredType));
+ variable.type = inferredType;
+ }
+
/// Performs type inference on the given [expression].
///
/// [typeContext] is the expected type of the expression, based on surrounding
@@ -1484,8 +1508,9 @@
}
@override
- void inferFunctionBody(InferenceHelper helper, DartType returnType,
+ Statement inferFunctionBody(InferenceHelper helper, DartType returnType,
AsyncMarker asyncMarker, FunctionNode function, Statement body) {
+ assert(body != null);
assert(closureContext == null);
this.helper = helper;
closureContext = new ClosureContext(this, asyncMarker, returnType, false);
@@ -1497,7 +1522,7 @@
flowAnalysis.initialize(parameter);
}
}
- inferStatement(body);
+ StatementInferenceResult result = inferStatement(body);
closureContext = null;
this.helper = null;
if (dataForTesting != null) {
@@ -1507,6 +1532,7 @@
}
}
flowAnalysis.finish();
+ return result.hasChanged ? result.statement : body;
}
DartType inferInvocation(DartType typeContext, int offset,
@@ -1556,7 +1582,7 @@
FunctionType extensionFunctionType = new FunctionType(
[calleeType.positionalParameters.first],
const DynamicType(),
- Nullability.legacy,
+ library.nonNullable,
requiredParameterCount: 1,
typeParameters: calleeType.typeParameters
.take(extensionTypeParameterCount)
@@ -1580,7 +1606,7 @@
FunctionType targetFunctionType = new FunctionType(
calleeType.positionalParameters.skip(1).toList(),
calleeType.returnType,
- Nullability.legacy,
+ library.nonNullable,
requiredParameterCount: calleeType.requiredParameterCount - 1,
namedParameters: calleeType.namedParameters,
typeParameters: targetTypeParameters);
@@ -1668,7 +1694,8 @@
null,
null,
typeContext,
- inferredTypes);
+ inferredTypes,
+ library.library);
substitution =
Substitution.fromPairs(calleeTypeParameters, inferredTypes);
} else if (explicitTypeArguments != null &&
@@ -1782,9 +1809,12 @@
formalTypes,
actualTypes,
typeContext,
- inferredTypes);
+ inferredTypes,
+ library.library);
assert(inferredTypes.every((type) => isKnown(type)),
"Unknown type(s) in inferred types: $inferredTypes.");
+ assert(inferredTypes.every((type) => !hasPromotedTypeVariable(type)),
+ "Promoted type variable(s) in inferred types: $inferredTypes.");
substitution =
Substitution.fromPairs(calleeTypeParameters, inferredTypes);
instrumentation?.record(uriForInstrumentation, offset, 'typeArgs',
@@ -1921,7 +1951,8 @@
for (int i = 0; i < typeContext.typeParameters.length; i++) {
substitutionMap[typeContext.typeParameters[i]] =
i < typeParameters.length
- ? new TypeParameterType(typeParameters[i], Nullability.legacy)
+ ? new TypeParameterType.forAlphaRenaming(
+ typeContext.typeParameters[i], typeParameters[i])
: const DynamicType();
}
substitution = Substitution.fromMap(substitutionMap);
@@ -1940,7 +1971,7 @@
// `Qi[T/S]` with respect to `?`. Otherwise, let `Ri` be `dynamic`.
for (int i = 0; i < formals.length; i++) {
VariableDeclarationImpl formal = formals[i];
- if (VariableDeclarationImpl.isImplicitlyTyped(formal)) {
+ if (formal.isImplicitlyTyped) {
DartType inferredType;
if (formalTypesFromContext[i] == coreTypes.nullType) {
inferredType = coreTypes.objectRawType(library.nullable);
@@ -2035,6 +2066,368 @@
typeArguments: arguments.types));
}
+ ExpressionInferenceResult _inferDynamicInvocation(
+ int fileOffset,
+ NullAwareGuard nullAwareGuard,
+ Expression receiver,
+ Name name,
+ Arguments arguments,
+ DartType typeContext) {
+ DartType inferredType = inferInvocation(
+ typeContext, fileOffset, unknownFunction, arguments,
+ receiverType: const DynamicType());
+ assert(name != equalsName);
+ return new ExpressionInferenceResult.nullAware(
+ inferredType,
+ new MethodInvocationImpl(receiver, name, arguments)
+ ..fileOffset = fileOffset,
+ nullAwareGuard);
+ }
+
+ ExpressionInferenceResult _inferMissingInvocation(
+ int fileOffset,
+ NullAwareGuard nullAwareGuard,
+ Expression receiver,
+ DartType receiverType,
+ ObjectAccessTarget target,
+ Name name,
+ Arguments arguments,
+ DartType typeContext,
+ {bool isImplicitCall}) {
+ assert(isImplicitCall != null);
+ Expression error = createMissingMethodInvocation(
+ fileOffset, receiver, receiverType, name, arguments,
+ isImplicitCall: isImplicitCall);
+ inferInvocation(typeContext, fileOffset, unknownFunction, arguments,
+ receiverType: receiverType);
+ assert(name != equalsName);
+ // TODO(johnniwinther): Use InvalidType instead.
+ return new ExpressionInferenceResult(const DynamicType(), error);
+ }
+
+ ExpressionInferenceResult _inferExtensionInvocation(
+ int fileOffset,
+ NullAwareGuard nullAwareGuard,
+ Expression receiver,
+ DartType receiverType,
+ ObjectAccessTarget target,
+ Name name,
+ Arguments arguments,
+ DartType typeContext) {
+ assert(target.isExtensionMember);
+ DartType calleeType = getGetterType(target, receiverType);
+ FunctionType functionType = getFunctionType(target, receiverType, false);
+
+ // TODO(johnniwinther): Disallow all implicit non-function calls?
+ if (calleeType is! DynamicType &&
+ !(calleeType is InterfaceType &&
+ calleeType.classNode == coreTypes.functionClass) &&
+ identical(functionType, unknownFunction)) {
+ Expression error = helper.buildProblem(
+ // TODO(johnniwinther): Use a different message for implicit .call.
+ templateInvokeNonFunction.withArguments(name.name),
+ fileOffset,
+ noLength);
+ return new ExpressionInferenceResult(const DynamicType(), error);
+ }
+ StaticInvocation staticInvocation = transformExtensionMethodInvocation(
+ fileOffset, target, receiver, arguments);
+ DartType inferredType = inferInvocation(
+ typeContext, fileOffset, functionType, staticInvocation.arguments,
+ receiverType: receiverType, isImplicitExtensionMember: true);
+ if (!isTopLevel) {
+ library.checkBoundsInStaticInvocation(staticInvocation,
+ typeSchemaEnvironment, helper.uri, getTypeArgumentsInfo(arguments));
+ }
+ return new ExpressionInferenceResult.nullAware(
+ inferredType, staticInvocation, nullAwareGuard);
+ }
+
+ ExpressionInferenceResult _inferFunctionInvocation(
+ int fileOffset,
+ NullAwareGuard nullAwareGuard,
+ Expression receiver,
+ DartType receiverType,
+ ObjectAccessTarget target,
+ Arguments arguments,
+ DartType typeContext) {
+ assert(target.isCallFunction);
+ FunctionType functionType = getFunctionType(target, receiverType, false);
+ DartType inferredType = inferInvocation(
+ typeContext, fileOffset, functionType, arguments,
+ receiverType: receiverType);
+ // TODO(johnniwinther): Check that type arguments against the bounds.
+ return new ExpressionInferenceResult.nullAware(
+ inferredType,
+ new MethodInvocation(receiver, callName, arguments)
+ ..fileOffset = fileOffset,
+ nullAwareGuard);
+ }
+
+ ExpressionInferenceResult _inferInstanceMethodInvocation(
+ int fileOffset,
+ NullAwareGuard nullAwareGuard,
+ Expression receiver,
+ DartType receiverType,
+ ObjectAccessTarget target,
+ Arguments arguments,
+ DartType typeContext,
+ {bool isImplicitCall}) {
+ assert(isImplicitCall != null);
+ assert(target.isInstanceMember);
+ Procedure method = target.member;
+ assert(method.kind == ProcedureKind.Method,
+ "Unexpected instance method $method");
+ Name methodName = method.name;
+
+ if (receiverType == const DynamicType()) {
+ FunctionNode signature = method.function;
+ if (arguments.positional.length < signature.requiredParameterCount ||
+ arguments.positional.length > signature.positionalParameters.length) {
+ target = const ObjectAccessTarget.unresolved();
+ method = null;
+ }
+ for (NamedExpression argument in arguments.named) {
+ if (!signature.namedParameters
+ .any((declaration) => declaration.name == argument.name)) {
+ target = const ObjectAccessTarget.unresolved();
+ method = null;
+ }
+ }
+ if (instrumentation != null && method != null) {
+ instrumentation.record(uriForInstrumentation, fileOffset, 'target',
+ new InstrumentationValueForMember(method));
+ }
+ }
+
+ DartType calleeType = getGetterType(target, receiverType);
+ FunctionType functionType =
+ getFunctionType(target, receiverType, !isImplicitCall);
+
+ // TODO(johnniwinther): Refactor to avoid this test in multiple places,
+ // either by providing a shared helper method or avoiding the calleeType/
+ // functionType distinction altogether.
+ if (!target.isUnresolved &&
+ calleeType is! DynamicType &&
+ !(calleeType is InterfaceType &&
+ calleeType.classNode == coreTypes.functionClass) &&
+ identical(functionType, unknownFunction)) {
+ Expression error = helper.buildProblem(
+ templateInvokeNonFunction.withArguments(methodName.name),
+ fileOffset,
+ noLength);
+ return new ExpressionInferenceResult(const DynamicType(), error);
+ }
+ bool contravariantCheck = false;
+ if (receiver is! ThisExpression &&
+ method != null &&
+ returnedTypeParametersOccurNonCovariantly(
+ method.enclosingClass, method.function.returnType)) {
+ contravariantCheck = true;
+ }
+ DartType inferredType = inferInvocation(
+ typeContext, fileOffset, functionType, arguments,
+ receiverType: receiverType);
+
+ Expression replacement;
+ if (contravariantCheck) {
+ // TODO(johnniwinther): Merge with the replacement computation below.
+ replacement = new AsExpression(
+ new MethodInvocation(receiver, methodName, arguments, method)
+ ..fileOffset = fileOffset,
+ inferredType)
+ ..isTypeError = true
+ ..fileOffset = fileOffset;
+ if (instrumentation != null) {
+ int offset =
+ arguments.fileOffset == -1 ? fileOffset : arguments.fileOffset;
+ instrumentation.record(uriForInstrumentation, offset, 'checkReturn',
+ new InstrumentationValueForType(inferredType));
+ }
+ }
+
+ _checkBoundsInMethodInvocation(
+ target, receiverType, calleeType, methodName, arguments, fileOffset);
+
+ replacement ??=
+ new MethodInvocation(receiver, methodName, arguments, method)
+ ..fileOffset = fileOffset;
+
+ return new ExpressionInferenceResult.nullAware(
+ inferredType, replacement, nullAwareGuard);
+ }
+
+ ExpressionInferenceResult _inferInstanceGetterInvocation(
+ int fileOffset,
+ NullAwareGuard nullAwareGuard,
+ Expression receiver,
+ DartType receiverType,
+ ObjectAccessTarget target,
+ Arguments arguments,
+ DartType typeContext,
+ {bool isImplicitCall}) {
+ assert(isImplicitCall != null);
+ assert(target.isInstanceMember);
+ Procedure getter = target.member;
+ assert(getter.kind == ProcedureKind.Getter);
+
+ if (receiverType == const DynamicType() && getter is Procedure) {
+ FunctionNode signature = getter.function;
+ if (arguments.positional.length < signature.requiredParameterCount ||
+ arguments.positional.length > signature.positionalParameters.length) {
+ target = const ObjectAccessTarget.unresolved();
+ getter = null;
+ }
+ for (NamedExpression argument in arguments.named) {
+ if (!signature.namedParameters
+ .any((declaration) => declaration.name == argument.name)) {
+ target = const ObjectAccessTarget.unresolved();
+ getter = null;
+ }
+ }
+ if (instrumentation != null && getter != null) {
+ instrumentation.record(uriForInstrumentation, fileOffset, 'target',
+ new InstrumentationValueForMember(getter));
+ }
+ }
+
+ DartType calleeType = getGetterType(target, receiverType);
+ FunctionType functionType =
+ getFunctionType(target, receiverType, !isImplicitCall);
+
+ if (!target.isUnresolved &&
+ calleeType is! DynamicType &&
+ !(calleeType is InterfaceType &&
+ calleeType.classNode == coreTypes.functionClass) &&
+ identical(functionType, unknownFunction)) {
+ Expression error = helper.buildProblem(
+ templateInvokeNonFunction.withArguments(getter.name.name),
+ fileOffset,
+ noLength);
+ return new ExpressionInferenceResult(const DynamicType(), error);
+ }
+ bool contravariantCheck = false;
+ if (calleeType is! DynamicType &&
+ receiver is! ThisExpression &&
+ returnedTypeParametersOccurNonCovariantly(
+ getter.enclosingClass, getter.function.returnType)) {
+ contravariantCheck = true;
+ }
+
+ DartType inferredType = inferInvocation(
+ typeContext, fileOffset, functionType, arguments,
+ receiverType: receiverType);
+
+ if (isImplicitCall) {
+ Expression error = helper.buildProblem(
+ templateImplicitCallOfNonMethod.withArguments(receiverType),
+ fileOffset,
+ noLength);
+ return new ExpressionInferenceResult(const DynamicType(), error);
+ }
+
+ Expression replacement;
+ if (contravariantCheck) {
+ PropertyGet propertyGet = new PropertyGet(receiver, getter.name, getter);
+ AsExpression asExpression = new AsExpression(propertyGet, functionType)
+ ..isTypeError = true
+ ..fileOffset = fileOffset;
+ replacement = new MethodInvocation(asExpression, callName, arguments);
+ if (instrumentation != null) {
+ int offset =
+ arguments.fileOffset == -1 ? fileOffset : arguments.fileOffset;
+ instrumentation.record(uriForInstrumentation, offset,
+ 'checkGetterReturn', new InstrumentationValueForType(functionType));
+ }
+ }
+
+ _checkBoundsInMethodInvocation(
+ target, receiverType, calleeType, getter.name, arguments, fileOffset);
+
+ // TODO(johnniwinther): Always encode the call as an explicit .call and
+ // set the correct member on the invocation.
+ replacement ??=
+ new MethodInvocation(receiver, getter.name, arguments, getter)
+ ..fileOffset = fileOffset;
+
+ return new ExpressionInferenceResult.nullAware(
+ inferredType, replacement, nullAwareGuard);
+ }
+
+ ExpressionInferenceResult _inferInstanceFieldInvocation(
+ int fileOffset,
+ NullAwareGuard nullAwareGuard,
+ Expression receiver,
+ DartType receiverType,
+ ObjectAccessTarget target,
+ Arguments arguments,
+ DartType typeContext,
+ {bool isImplicitCall}) {
+ assert(isImplicitCall != null);
+ assert(target.isInstanceMember);
+ Field field = target.member;
+
+ DartType calleeType = getGetterType(target, receiverType);
+ FunctionType functionType =
+ getFunctionType(target, receiverType, !isImplicitCall);
+
+ if (calleeType is! DynamicType &&
+ !(calleeType is InterfaceType &&
+ calleeType.classNode == coreTypes.functionClass) &&
+ identical(functionType, unknownFunction)) {
+ Expression error = helper.buildProblem(
+ templateInvokeNonFunction.withArguments(target.member.name.name),
+ fileOffset,
+ noLength);
+ return new ExpressionInferenceResult(const DynamicType(), error);
+ }
+ bool contravariantCheck = false;
+ if (receiver is! ThisExpression &&
+ calleeType is! DynamicType &&
+ returnedTypeParametersOccurNonCovariantly(
+ field.enclosingClass, field.type)) {
+ contravariantCheck = true;
+ }
+
+ DartType inferredType = inferInvocation(
+ typeContext, fileOffset, functionType, arguments,
+ receiverType: receiverType);
+
+ if (isImplicitCall) {
+ Expression error = helper.buildProblem(
+ templateImplicitCallOfNonMethod.withArguments(receiverType),
+ fileOffset,
+ noLength);
+ return new ExpressionInferenceResult(const DynamicType(), error);
+ }
+
+ Expression replacement;
+ if (contravariantCheck) {
+ PropertyGet propertyGet = new PropertyGet(receiver, field.name, field);
+ AsExpression asExpression = new AsExpression(propertyGet, functionType)
+ ..isTypeError = true
+ ..fileOffset = fileOffset;
+ replacement = new MethodInvocation(asExpression, callName, arguments);
+ if (instrumentation != null) {
+ int offset =
+ arguments.fileOffset == -1 ? fileOffset : arguments.fileOffset;
+ instrumentation.record(uriForInstrumentation, offset,
+ 'checkGetterReturn', new InstrumentationValueForType(functionType));
+ }
+ }
+
+ _checkBoundsInMethodInvocation(
+ target, receiverType, calleeType, field.name, arguments, fileOffset);
+
+ // TODO(johnniwinther): Always encode the call as an explicit .call and
+ // set the correct member on the invocation.
+ replacement ??= new MethodInvocation(receiver, field.name, arguments, field)
+ ..fileOffset = fileOffset;
+
+ return new ExpressionInferenceResult.nullAware(
+ inferredType, replacement, nullAwareGuard);
+ }
+
/// Performs the core type inference algorithm for method invocations (this
/// handles both null-aware and non-null-aware method invocations).
ExpressionInferenceResult inferMethodInvocation(
@@ -2054,101 +2447,69 @@
ObjectAccessTarget target = findInterfaceMember(
receiverType, node.name, node.fileOffset,
instrumented: true, includeExtensionMethods: true);
- Expression error = reportMissingInterfaceMember(target, receiverType,
- node.name, node.fileOffset, templateUndefinedMethod);
- if (target.isInstanceMember) {
- Member interfaceMember = target.member;
- if (receiverType == const DynamicType() && interfaceMember is Procedure) {
- Arguments arguments = node.arguments;
- FunctionNode signature = interfaceMember.function;
- if (arguments.positional.length < signature.requiredParameterCount ||
- arguments.positional.length >
- signature.positionalParameters.length) {
- target = const ObjectAccessTarget.unresolved();
- interfaceMember = null;
- }
- for (NamedExpression argument in arguments.named) {
- if (!signature.namedParameters
- .any((declaration) => declaration.name == argument.name)) {
- target = const ObjectAccessTarget.unresolved();
- interfaceMember = null;
+ switch (target.kind) {
+ case ObjectAccessTargetKind.instanceMember:
+ Member member = target.member;
+ if (member is Procedure) {
+ if (member.kind == ProcedureKind.Getter) {
+ return _inferInstanceGetterInvocation(
+ node.fileOffset,
+ nullAwareGuard,
+ receiver,
+ receiverType,
+ target,
+ node.arguments,
+ typeContext,
+ isImplicitCall: node.isImplicitCall);
+ } else {
+ return _inferInstanceMethodInvocation(
+ node.fileOffset,
+ nullAwareGuard,
+ receiver,
+ receiverType,
+ target,
+ node.arguments,
+ typeContext,
+ isImplicitCall: node.isImplicitCall);
}
+ } else {
+ return _inferInstanceFieldInvocation(node.fileOffset, nullAwareGuard,
+ receiver, receiverType, target, node.arguments, typeContext,
+ isImplicitCall: node.isImplicitCall);
}
- if (instrumentation != null && interfaceMember != null) {
- instrumentation.record(uriForInstrumentation, node.fileOffset,
- 'target', new InstrumentationValueForMember(interfaceMember));
- }
- }
- node.interfaceTarget = interfaceMember;
+ break;
+ case ObjectAccessTargetKind.callFunction:
+ return _inferFunctionInvocation(node.fileOffset, nullAwareGuard,
+ receiver, receiverType, target, node.arguments, typeContext);
+ case ObjectAccessTargetKind.extensionMember:
+ return _inferExtensionInvocation(
+ node.fileOffset,
+ nullAwareGuard,
+ receiver,
+ receiverType,
+ target,
+ node.name,
+ node.arguments,
+ typeContext);
+ case ObjectAccessTargetKind.missing:
+ return _inferMissingInvocation(
+ node.fileOffset,
+ nullAwareGuard,
+ receiver,
+ receiverType,
+ target,
+ node.name,
+ node.arguments,
+ typeContext,
+ isImplicitCall: node.isImplicitCall);
+ case ObjectAccessTargetKind.dynamic:
+ case ObjectAccessTargetKind.invalid:
+ case ObjectAccessTargetKind.unresolved:
+ return _inferDynamicInvocation(node.fileOffset, nullAwareGuard,
+ receiver, node.name, node.arguments, typeContext);
}
-
- Name methodName = node.name;
- assert(target != null, "No target for ${node}.");
- bool isOverloadedArithmeticOperator =
- isOverloadedArithmeticOperatorAndType(target, receiverType);
- DartType calleeType = getGetterType(target, receiverType);
- FunctionType functionType =
- getFunctionType(target, receiverType, !node.isImplicitCall);
-
- if (!target.isUnresolved &&
- calleeType is! DynamicType &&
- !(calleeType is InterfaceType &&
- calleeType.classNode == coreTypes.functionClass) &&
- identical(functionType, unknownFunction)) {
- Expression error = helper.wrapInProblem(node,
- templateInvokeNonFunction.withArguments(methodName.name), noLength);
- return new ExpressionInferenceResult(const DynamicType(), error);
- }
- MethodContravarianceCheckKind checkKind = preCheckInvocationContravariance(
- receiverType, target,
- isThisReceiver: receiver is ThisExpression);
- Expression replacement;
- Arguments arguments = node.arguments;
- if (target.isExtensionMember) {
- StaticInvocation staticInvocation = transformExtensionMethodInvocation(
- node.fileOffset, target, receiver, node.arguments);
- arguments = staticInvocation.arguments;
- replacement = staticInvocation;
- } else {
- node.receiver = receiver..parent = node;
- arguments = node.arguments;
- replacement = node;
- }
- DartType inferredType = inferInvocation(
- typeContext, node.fileOffset, functionType, arguments,
- isOverloadedArithmeticOperator: isOverloadedArithmeticOperator,
- receiverType: receiverType,
- isImplicitExtensionMember: target.isExtensionMember);
- if (methodName.name == '==') {
- inferredType = coreTypes.boolRawType(library.nonNullable);
- }
- replacement = handleInvocationContravariance(checkKind, node, arguments,
- replacement, inferredType, functionType, node.fileOffset);
-
- if (node.isImplicitCall && target.isInstanceMember) {
- Member member = target.member;
- if (!(member is Procedure && member.kind == ProcedureKind.Method)) {
- Expression error = helper.wrapInProblem(
- node,
- templateImplicitCallOfNonMethod.withArguments(receiverType),
- noLength);
- return new ExpressionInferenceResult(const DynamicType(), error);
- }
- }
- if (!isTopLevel && target.isExtensionMember) {
- library.checkBoundsInStaticInvocation(replacement, typeSchemaEnvironment,
- helper.uri, getTypeArgumentsInfo(arguments));
- } else {
- _checkBoundsInMethodInvocation(target, receiverType, calleeType,
- methodName, arguments, node.fileOffset);
- }
- if (error != null) {
- // TODO(johnniwinther): Use InvalidType instead.
- return new ExpressionInferenceResult(const DynamicType(), error);
- }
-
- return new ExpressionInferenceResult.nullAware(
- inferredType, replacement, nullAwareGuard);
+ return unhandled('$target', 'inferMethodInvocation', node.fileOffset,
+ uriForInstrumentation);
}
void _checkBoundsInMethodInvocation(
@@ -2276,15 +2637,13 @@
///
/// Derived classes should override this method with logic that dispatches on
/// the statement type and calls the appropriate specialized "infer" method.
- void inferStatement(Statement statement) {
+ StatementInferenceResult inferStatement(Statement statement) {
registerIfUnreachableForTesting(statement);
// For full (non-top level) inference, we need access to the
// ExpressionGeneratorHelper so that we can perform error recovery.
if (!isTopLevel) assert(helper != null);
- if (statement != null) {
- statement.accept(new InferenceVisitor(this));
- }
+ return statement.accept(new InferenceVisitor(this));
}
/// Performs the type inference steps necessary to instantiate a tear-off
@@ -2300,8 +2659,8 @@
List<DartType> inferredTypes = new List<DartType>.filled(
typeParameters.length, const UnknownType());
FunctionType instantiatedType = functionType.withoutTypeParameters;
- typeSchemaEnvironment.inferGenericFunctionOrType(
- instantiatedType, typeParameters, [], [], context, inferredTypes);
+ typeSchemaEnvironment.inferGenericFunctionOrType(instantiatedType,
+ typeParameters, [], [], context, inferredTypes, library.library);
if (!isTopLevel) {
expression = new Instantiation(expression, inferredTypes)
..fileOffset = expression.fileOffset;
@@ -2418,19 +2777,22 @@
}
// TODO(paulberry): If [type] is a subtype of `Future`, should we just
// return it unmodified?
- return new InterfaceType(coreTypes.futureOrClass, Nullability.legacy,
- <DartType>[type ?? const DynamicType()]);
- }
-
- DartType wrapFutureType(DartType type) {
- DartType typeWithoutFutureOr = type ?? const DynamicType();
- return new InterfaceType(coreTypes.futureClass, Nullability.legacy,
- <DartType>[typeWithoutFutureOr]);
- }
-
- DartType wrapType(DartType type, Class class_) {
+ if (type == null) {
+ return coreTypes.futureRawType(library.nullable);
+ }
return new InterfaceType(
- class_, Nullability.legacy, <DartType>[type ?? const DynamicType()]);
+ coreTypes.futureOrClass, library.nonNullable, <DartType>[type]);
+ }
+
+ DartType wrapFutureType(DartType type, Nullability nullability) {
+ DartType typeWithoutFutureOr = type ?? const DynamicType();
+ return new InterfaceType(
+ coreTypes.futureClass, nullability, <DartType>[typeWithoutFutureOr]);
+ }
+
+ DartType wrapType(DartType type, Class class_, Nullability nullability) {
+ return new InterfaceType(
+ class_, nullability, <DartType>[type ?? const DynamicType()]);
}
Member _getInterfaceMember(
@@ -2480,8 +2842,7 @@
}
if (expression is VariableGet) {
VariableDeclaration variable = expression.variable;
- if (variable is VariableDeclarationImpl &&
- VariableDeclarationImpl.isLocalFunction(variable)) {
+ if (variable is VariableDeclarationImpl && variable.isLocalFunction) {
return templateInvalidCastLocalFunction;
}
}
@@ -2532,6 +2893,22 @@
}
}
+ Expression createMissingMethodInvocation(int fileOffset, Expression receiver,
+ DartType receiverType, Name name, Arguments arguments,
+ {bool isImplicitCall}) {
+ assert(isImplicitCall != null);
+ if (isTopLevel) {
+ return engine.forest
+ .createMethodInvocation(fileOffset, receiver, name, arguments);
+ } else {
+ return helper.buildProblem(
+ templateUndefinedMethod.withArguments(
+ name.name, resolveTypeParameter(receiverType)),
+ fileOffset,
+ isImplicitCall ? noLength : name.name.length);
+ }
+ }
+
Expression createMissingPropertyGet(int fileOffset, Expression receiver,
DartType receiverType, Name propertyName) {
if (isTopLevel) {
@@ -2566,11 +2943,7 @@
Expression createMissingIndexGet(int fileOffset, Expression receiver,
DartType receiverType, Expression index) {
if (isTopLevel) {
- return engine.forest.createMethodInvocation(
- fileOffset,
- receiver,
- indexGetName,
- engine.forest.createArguments(fileOffset, <Expression>[index]));
+ return engine.forest.createIndexGet(fileOffset, receiver, index);
} else {
return helper.buildProblem(
templateUndefinedMethod.withArguments(
@@ -2581,14 +2954,13 @@
}
Expression createMissingIndexSet(int fileOffset, Expression receiver,
- DartType receiverType, Expression index, Expression value) {
+ DartType receiverType, Expression index, Expression value,
+ {bool forEffect, bool readOnlyReceiver}) {
+ assert(forEffect != null);
+ assert(readOnlyReceiver != null);
if (isTopLevel) {
- return engine.forest.createMethodInvocation(
- fileOffset,
- receiver,
- indexSetName,
- engine.forest
- .createArguments(fileOffset, <Expression>[index, value]));
+ return engine.forest.createIndexSet(fileOffset, receiver, index, value,
+ forEffect: forEffect, readOnlyReceiver: readOnlyReceiver);
} else {
return helper.buildProblem(
templateUndefinedMethod.withArguments(
@@ -2759,9 +3131,10 @@
// substitute them before calling instantiate to bounds.
Substitution substitution = Substitution.fromPairs(
mixinClass.typeParameters,
- parameters
- .map((p) => new TypeParameterType(p, Nullability.legacy))
- .toList());
+ new List<DartType>.generate(
+ parameters.length,
+ (i) => new TypeParameterType.forAlphaRenaming(
+ mixinClass.typeParameters[i], parameters[i])));
for (TypeParameter p in parameters) {
p.bound = substitution.substituteType(p.bound);
}
@@ -2773,6 +3146,55 @@
}
}
+/// The result of a statement inference.
+class StatementInferenceResult {
+ const StatementInferenceResult();
+
+ factory StatementInferenceResult.single(Statement statement) =
+ SingleStatementInferenceResult;
+
+ factory StatementInferenceResult.multiple(
+ int fileOffset, List<Statement> statements) =
+ MultipleStatementInferenceResult;
+
+ bool get hasChanged => false;
+
+ Statement get statement =>
+ throw new UnsupportedError('StatementInferenceResult.statement');
+
+ int get statementCount =>
+ throw new UnsupportedError('StatementInferenceResult.statementCount');
+
+ List<Statement> get statements =>
+ throw new UnsupportedError('StatementInferenceResult.statements');
+}
+
+class SingleStatementInferenceResult implements StatementInferenceResult {
+ final Statement statement;
+
+ SingleStatementInferenceResult(this.statement);
+
+ bool get hasChanged => true;
+
+ int get statementCount => 1;
+
+ List<Statement> get statements =>
+ throw new UnsupportedError('SingleStatementInferenceResult.statements');
+}
+
+class MultipleStatementInferenceResult implements StatementInferenceResult {
+ final int fileOffset;
+ final List<Statement> statements;
+
+ MultipleStatementInferenceResult(this.fileOffset, this.statements);
+
+ bool get hasChanged => true;
+
+ Statement get statement => new Block(statements)..fileOffset = fileOffset;
+
+ int get statementCount => statements.length;
+}
+
/// The result of an expression inference.
class ExpressionInferenceResult {
/// The inferred type of the expression.
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
index ef4c2a6..56800aa 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
@@ -11,7 +11,7 @@
import '../problems.dart' show internalProblem;
-import '../kernel/kernel_shadow_ast.dart' show ShadowTypePromoter;
+import '../kernel/internal_ast.dart' show ShadowTypePromoter;
import 'type_schema_environment.dart' show TypeSchemaEnvironment;
@@ -694,7 +694,7 @@
previousType.bound, SubtypeCheckMode.ignoringNullabilities)) {
// The type we are checking against is a subtype of the bound of the
// previous type of the variable; we can promote the bound.
- return new TypeParameterType(
+ return new TypeParameterType.intersection(
previousType.parameter, previousType.nullability, checkedType);
} else {
// The types aren't sufficiently related; we can't promote.
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
index 9399c64..3ded48c 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema.dart
@@ -20,7 +20,7 @@
show Annotator, NameSystem, Printer, globalDebuggingNames;
/// Determines whether a type schema contains `?` somewhere inside it.
-bool isKnown(DartType schema) => schema.accept(new _IsKnownVisitor());
+bool isKnown(DartType schema) => schema.accept(const _IsKnownVisitor());
/// Converts a [DartType] to a string, representing the unknown type as `?`.
String typeSchemaToString(DartType schema) {
@@ -87,6 +87,8 @@
/// Visitor that computes [isKnown].
class _IsKnownVisitor extends DartTypeVisitor<bool> {
+ const _IsKnownVisitor();
+
@override
bool defaultDartType(DartType node) => node is! UnknownType;
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
index dc1b1be..95b32d1 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_elimination.dart
@@ -6,6 +6,7 @@
import 'package:kernel/core_types.dart' show CoreTypes;
+import 'replacement_visitor.dart';
import 'type_schema.dart' show UnknownType;
/// Returns the greatest closure of the given type [schema] with respect to `?`.
@@ -45,7 +46,7 @@
/// Each visitor method returns `null` if there are no `?`s contained in the
/// type, otherwise it returns the result of substituting `?` with `Null` or
/// `Object`, as appropriate.
-class _TypeSchemaEliminationVisitor implements DartTypeVisitor<DartType> {
+class _TypeSchemaEliminationVisitor extends ReplacementVisitor {
final DartType nullType;
bool isLeastClosure;
@@ -53,112 +54,8 @@
_TypeSchemaEliminationVisitor(CoreTypes coreTypes, this.isLeastClosure)
: nullType = coreTypes.nullType;
- @override
- DartType visitFunctionType(FunctionType node) {
- DartType newReturnType = node.returnType.accept(this);
+ void changeVariance() {
isLeastClosure = !isLeastClosure;
- List<DartType> newPositionalParameters = null;
- for (int i = 0; i < node.positionalParameters.length; i++) {
- DartType substitution = node.positionalParameters[i].accept(this);
- if (substitution != null) {
- newPositionalParameters ??=
- node.positionalParameters.toList(growable: false);
- newPositionalParameters[i] = substitution;
- }
- }
- List<NamedType> newNamedParameters = null;
- for (int i = 0; i < node.namedParameters.length; i++) {
- DartType substitution = node.namedParameters[i].type.accept(this);
- if (substitution != null) {
- newNamedParameters ??= node.namedParameters.toList(growable: false);
- newNamedParameters[i] = new NamedType(
- node.namedParameters[i].name, substitution,
- isRequired: node.namedParameters[i].isRequired);
- }
- }
- isLeastClosure = !isLeastClosure;
- DartType typedefType = node.typedefType?.accept(this);
- if (newReturnType == null &&
- newPositionalParameters == null &&
- newNamedParameters == null &&
- typedefType == null) {
- // No types had to be substituted.
- return null;
- } else {
- return new FunctionType(
- newPositionalParameters ?? node.positionalParameters,
- newReturnType ?? node.returnType,
- node.nullability,
- namedParameters: newNamedParameters ?? node.namedParameters,
- typeParameters: node.typeParameters,
- requiredParameterCount: node.requiredParameterCount,
- typedefType: typedefType);
- }
- }
-
- @override
- DartType visitInterfaceType(InterfaceType node) {
- List<DartType> newTypeArguments = null;
- for (int i = 0; i < node.typeArguments.length; i++) {
- DartType substitution = node.typeArguments[i].accept(this);
- if (substitution != null) {
- newTypeArguments ??= node.typeArguments.toList(growable: false);
- newTypeArguments[i] = substitution;
- }
- }
- if (newTypeArguments == null) {
- // No type arguments needed to be substituted.
- return null;
- } else {
- return new InterfaceType(
- node.classNode, node.nullability, newTypeArguments);
- }
- }
-
- @override
- DartType visitDynamicType(DynamicType node) => null;
-
- @override
- DartType visitNeverType(NeverType node) => null;
-
- @override
- DartType visitInvalidType(InvalidType node) => null;
-
- @override
- DartType visitBottomType(BottomType node) => null;
-
- @override
- DartType visitVoidType(VoidType node) => null;
-
- @override
- DartType visitTypeParameterType(TypeParameterType node) {
- if (node.promotedBound != null) {
- DartType newPromotedBound = node.promotedBound.accept(this);
- if (newPromotedBound != null) {
- return new TypeParameterType(node.parameter,
- node.typeParameterTypeNullability, newPromotedBound);
- }
- }
- return null;
- }
-
- @override
- DartType visitTypedefType(TypedefType node) {
- List<DartType> newTypeArguments = null;
- for (int i = 0; i < node.typeArguments.length; i++) {
- DartType substitution = node.typeArguments[i].accept(this);
- if (substitution != null) {
- newTypeArguments ??= node.typeArguments.toList(growable: false);
- newTypeArguments[i] = substitution;
- }
- }
- if (newTypeArguments == null) {
- // No type arguments needed to be substituted.
- return null;
- } else {
- return new TypedefType(
- node.typedefNode, node.nullability, newTypeArguments);
- }
}
@override
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
index 16cd881..16f0ff7 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
@@ -9,10 +9,11 @@
DynamicType,
FunctionType,
InterfaceType,
+ Library,
NamedType,
- Nullability,
Procedure,
- TypeParameter;
+ TypeParameter,
+ Variance;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -29,6 +30,8 @@
import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
+import 'type_demotion.dart';
+
import 'type_schema.dart' show UnknownType, typeSchemaToString, isKnown;
import 'type_schema_elimination.dart' show greatestClosure, leastClosure;
@@ -42,7 +45,7 @@
return new FunctionType(
type.positionalParameters.map(substitution.substituteType).toList(),
substitution.substituteType(type.returnType),
- Nullability.legacy,
+ type.nullability,
namedParameters: type.namedParameters
.map((named) => new NamedType(
named.name, substitution.substituteType(named.type),
@@ -167,6 +170,7 @@
List<DartType> actualTypes,
DartType returnContextType,
List<DartType> inferredTypes,
+ Library currentLibrary,
{bool isConst: false}) {
if (typeParametersToInfer.isEmpty) {
return;
@@ -177,7 +181,7 @@
// be subtypes (or supertypes) as necessary, and track the constraints that
// are implied by this.
TypeConstraintGatherer gatherer =
- new TypeConstraintGatherer(this, typeParametersToInfer);
+ new TypeConstraintGatherer(this, typeParametersToInfer, currentLibrary);
if (!isEmptyContext(returnContextType)) {
if (isConst) {
@@ -198,6 +202,10 @@
inferTypeFromConstraints(
gatherer.computeConstraints(), typeParametersToInfer, inferredTypes,
downwardsInferPhase: formalTypes == null);
+
+ for (int i = 0; i < inferredTypes.length; i++) {
+ inferredTypes[i] = demoteType(inferredTypes[i]);
+ }
}
bool hasOmittedBound(TypeParameter parameter) {
@@ -249,8 +257,9 @@
TypeConstraint constraint = constraints[typeParam];
if (downwardsInferPhase || !typeParam.isLegacyCovariant) {
- inferredTypes[i] =
- _inferTypeParameterFromContext(constraint, extendsConstraint);
+ inferredTypes[i] = _inferTypeParameterFromContext(
+ constraint, extendsConstraint,
+ isContravariant: typeParam.variance == Variance.contravariant);
} else {
inferredTypes[i] = _inferTypeParameterFromAll(
typesFromDownwardsInference[i], constraint, extendsConstraint);
@@ -351,21 +360,44 @@
///
/// If [grounded] is `true`, then the returned type is guaranteed to be a
/// known type (i.e. it will not contain any instances of `?`).
+ ///
+ /// If [isContravariant] is `true`, then we are solving for a contravariant
+ /// type parameter which means we choose the upper bound rather than the
+ /// lower bound for normally covariant type parameters.
DartType solveTypeConstraint(TypeConstraint constraint,
- {bool grounded: false}) {
- // Prefer the known bound, if any.
- if (isKnown(constraint.lower)) return constraint.lower;
- if (isKnown(constraint.upper)) return constraint.upper;
+ {bool grounded: false, bool isContravariant: false}) {
+ if (!isContravariant) {
+ // Prefer the known bound, if any.
+ if (isKnown(constraint.lower)) return constraint.lower;
+ if (isKnown(constraint.upper)) return constraint.upper;
- // Otherwise take whatever bound has partial information, e.g. `Iterable<?>`
- if (constraint.lower is! UnknownType) {
- return grounded
- ? leastClosure(coreTypes, constraint.lower)
- : constraint.lower;
+ // Otherwise take whatever bound has partial information,
+ // e.g. `Iterable<?>`
+ if (constraint.lower is! UnknownType) {
+ return grounded
+ ? leastClosure(coreTypes, constraint.lower)
+ : constraint.lower;
+ } else {
+ return grounded
+ ? greatestClosure(coreTypes, constraint.upper)
+ : constraint.upper;
+ }
} else {
- return grounded
- ? greatestClosure(coreTypes, constraint.upper)
- : constraint.upper;
+ // Prefer the known bound, if any.
+ if (isKnown(constraint.upper)) return constraint.upper;
+ if (isKnown(constraint.lower)) return constraint.lower;
+
+ // Otherwise take whatever bound has partial information,
+ // e.g. `Iterable<?>`
+ if (constraint.upper is! UnknownType) {
+ return grounded
+ ? greatestClosure(coreTypes, constraint.upper)
+ : constraint.upper;
+ } else {
+ return grounded
+ ? leastClosure(coreTypes, constraint.lower)
+ : constraint.lower;
+ }
}
}
@@ -394,8 +426,10 @@
}
DartType _inferTypeParameterFromContext(
- TypeConstraint constraint, DartType extendsConstraint) {
- DartType t = solveTypeConstraint(constraint);
+ TypeConstraint constraint, DartType extendsConstraint,
+ {bool isContravariant: false}) {
+ DartType t =
+ solveTypeConstraint(constraint, isContravariant: isContravariant);
if (!isKnown(t)) {
return t;
}
diff --git a/pkg/front_end/lib/src/fasta/util/textual_outline.dart b/pkg/front_end/lib/src/fasta/util/textual_outline.dart
new file mode 100644
index 0000000..ac59c1e
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/util/textual_outline.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2019, 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.
+
+import 'dart:typed_data' show Uint8List;
+
+import 'dart:io' show File;
+
+import 'package:_fe_analyzer_shared/src/parser/class_member_parser.dart'
+ show ClassMemberParser;
+
+import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
+ show ErrorToken, LanguageVersionToken, Scanner;
+
+import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'
+ show Utf8BytesScanner;
+
+import '../../fasta/source/directive_listener.dart' show DirectiveListener;
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+
+String textualOutline(List<int> rawBytes) {
+ // TODO(jensj): We need to specify the scanner settings to match that of the
+ // compiler!
+ Uint8List bytes = new Uint8List(rawBytes.length + 1);
+ bytes.setRange(0, rawBytes.length, rawBytes);
+
+ StringBuffer sb = new StringBuffer();
+
+ Utf8BytesScanner scanner = new Utf8BytesScanner(bytes, includeComments: false,
+ languageVersionChanged:
+ (Scanner scanner, LanguageVersionToken languageVersion) {
+ sb.writeln("// @dart = ${languageVersion.major}.${languageVersion.minor}");
+ });
+ Token firstToken = scanner.tokenize();
+ if (firstToken == null) return null;
+ List<int> lineStarts = scanner.lineStarts;
+ int lineStartsIteratorLine = 1;
+ Iterator<int> lineStartsIterator = lineStarts.iterator;
+ lineStartsIterator.moveNext();
+ lineStartsIterator.moveNext();
+ lineStartsIteratorLine++;
+ Token token = firstToken;
+
+ EndOffsetListener listener = new EndOffsetListener();
+ ClassMemberParser classMemberParser = new ClassMemberParser(listener);
+ classMemberParser.parseUnit(firstToken);
+
+ bool printed = false;
+ int endOfLast = -1;
+ while (token != null) {
+ if (token is ErrorToken) {
+ return null;
+ }
+ int prevLine = lineStartsIteratorLine;
+ while (token.offset >= lineStartsIterator.current &&
+ lineStartsIterator.moveNext()) {
+ lineStartsIteratorLine++;
+ }
+ if (prevLine < lineStartsIteratorLine) {
+ sb.write("\n");
+ prevLine++;
+ if (prevLine < lineStartsIteratorLine) {
+ sb.write("\n");
+ }
+ } else if (printed && token.offset > endOfLast) {
+ sb.write(" ");
+ }
+
+ sb.write(token.lexeme);
+ printed = true;
+ endOfLast = token.end;
+
+ if (token.isEof) break;
+
+ if (token.endGroup != null &&
+ listener.endOffsets.contains(token.endGroup.offset)) {
+ token = token.endGroup;
+ } else {
+ token = token.next;
+ }
+ }
+
+ return sb.toString();
+}
+
+main(List<String> args) {
+ File f = new File(args[0]);
+ print(textualOutline(f.readAsBytesSync()));
+}
+
+class EndOffsetListener extends DirectiveListener {
+ Set<int> endOffsets = new Set<int>();
+
+ @override
+ void endClassMethod(Token getOrSet, Token beginToken, Token beginParam,
+ Token beginInitializers, Token endToken) {
+ endOffsets.add(endToken.offset);
+ }
+
+ @override
+ void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+ endOffsets.add(endToken.offset);
+ }
+
+ @override
+ void handleNativeFunctionBodySkipped(Token nativeToken, Token semicolon) {
+ // Allow native functions.
+ }
+}
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index d69c809..4f0fbf1 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -9,7 +9,7 @@
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
-import 'package:kernel/kernel.dart' show Component, CanonicalName;
+import 'package:kernel/kernel.dart' show CanonicalName, Component;
import 'base/processed_options.dart' show ProcessedOptions;
@@ -81,6 +81,8 @@
.toSet();
}
+ List<Component> loadedComponents = new List<Component>();
+
Component sdkSummary = await options.loadSdkSummary(null);
// By using the nameRoot of the the summary, we enable sharing the
// sdkSummary between multiple invocations.
@@ -95,6 +97,7 @@
// linked dependencies were listed out of order (or provide mechanism to
// sort them).
for (Component inputSummary in await options.loadInputSummaries(nameRoot)) {
+ loadedComponents.add(inputSummary);
Set<Uri> excluded = externalLibs(inputSummary);
dillTarget.loader.appendLibraries(inputSummary,
filter: (uri) => !excluded.contains(uri));
@@ -110,6 +113,7 @@
// Linked dependencies are meant to be part of the component so they are not
// marked external.
for (Component dependency in await options.loadLinkDependencies(nameRoot)) {
+ loadedComponents.add(dependency);
Set<Uri> excluded = externalLibs(dependency);
dillTarget.loader.appendLibraries(dependency,
filter: (uri) => !excluded.contains(uri));
@@ -174,6 +178,8 @@
return new InternalCompilerResult(
summary: summary,
component: component,
+ sdkComponent: sdkSummary,
+ loadedComponents: loadedComponents,
classHierarchy:
includeHierarchyAndCoreTypes ? kernelTarget.loader.hierarchy : null,
coreTypes:
@@ -191,6 +197,10 @@
/// The generated component, if it was requested.
final Component component;
+ final Component sdkComponent;
+
+ final List<Component> loadedComponents;
+
/// Dependencies traversed by the compiler. Used only for generating
/// dependency .GN files in the dart-sdk build system.
/// Note this might be removed when we switch to compute dependencies without
@@ -209,6 +219,8 @@
InternalCompilerResult(
{this.summary,
this.component,
+ this.sdkComponent,
+ this.loadedComponents,
this.deps,
this.classHierarchy,
this.coreTypes,
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 9901425..e420f29 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -327,7 +327,6 @@
InterfaceCheck/analyzerCode: Fail
InterfaceCheck/example: Fail
InterpolationInUri/example: Fail
-IntersectionTypeAsTypeArgument/analyzerCode: Fail # Analyzer doesn't catch this error.
InvalidBreakTarget/analyzerCode: Fail
InvalidBreakTarget/example: Fail
InvalidCastFunctionExpr/example: Fail
@@ -537,6 +536,7 @@
TypeVariableInStaticContext/part_wrapped_declaration4: Fail
TypeVariableSameNameAsEnclosing/example: Fail
TypedefNotFunction/example: Fail
+TypedefNotType/example: Fail # Feature not yet enabled by default.
UnexpectedToken/part_wrapped_script1: Fail
UnexpectedToken/script1: Fail
UnmatchedToken/part_wrapped_script1: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 670a401..e8794be 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1298,8 +1298,10 @@
- "class C { int C() {} }"
ConstructorWithTypeParameters:
+ index: 99
template: "Constructors can't have type parameters."
- analyzerCode: TYPE_PARAMETER_ON_CONSTRUCTOR
+ analyzerCode: ParserErrorCode.TYPE_PARAMETER_ON_CONSTRUCTOR
+ tip: "Try removing the type parameters."
script:
- "class C { C<T>() {} }"
- "class C { C.foo<T>() {} }"
@@ -2117,6 +2119,10 @@
template: "Can't create typedef from non-function type."
analyzerCode: INVALID_GENERIC_FUNCTION_TYPE
+TypedefNotType:
+ template: "Can't create typedef from non-type."
+ analyzerCode: INVALID_TYPE_IN_TYPEDEF
+
LibraryDirectiveNotFirst:
index: 37
template: "The library directive must appear before all other directives."
@@ -3371,15 +3377,6 @@
template: "This is the type variable whose bound isn't conformed to."
severity: CONTEXT
-IntersectionTypeAsTypeArgument:
- template: "Can't infer a type for '#name', it can be either '#type' or '#type2'."
- tip: "Try adding a type argument selecting one of the options."
- script: |
- class A {}
- class B extends A {}
- f<T>(T t) => null;
- g<S>(S t) => t is B ? f(t) : null;
-
InferredPackageUri:
template: "Interpreting this as package URI, '#uri'."
severity: WARNING
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect
index 2199837..3c0cebd 100644
--- a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect
@@ -1,18 +1,18 @@
Problems reported:
-parser_test/error_recovery/empty_await_for:2:14: Expected an identifier, but got ')'.
+parser/error_recovery/empty_await_for:2:14: Expected an identifier, but got ')'.
await for () {}
^
-parser_test/error_recovery/empty_await_for:2:14: Expected 'in' before this.
+parser/error_recovery/empty_await_for:2:14: Expected 'in' before this.
await for () {}
^
-parser_test/error_recovery/empty_await_for:2:14: Expected an identifier, but got ')'.
+parser/error_recovery/empty_await_for:2:14: Expected an identifier, but got ')'.
await for () {}
^
-parser_test/error_recovery/empty_await_for:2:14: Expected an identifier, but got ')'.
+parser/error_recovery/empty_await_for:2:14: Expected an identifier, but got ')'.
await for () {}
^
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect
index 63dc838..83797a0 100644
--- a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect
@@ -1,18 +1,18 @@
Problems reported:
-parser_test/error_recovery/empty_for:2:8: Expected an identifier, but got ')'.
+parser/error_recovery/empty_for:2:8: Expected an identifier, but got ')'.
for () {}
^
-parser_test/error_recovery/empty_for:2:8: Expected ';' after this.
+parser/error_recovery/empty_for:2:8: Expected ';' after this.
for () {}
^
-parser_test/error_recovery/empty_for:2:8: Expected an identifier, but got ')'.
+parser/error_recovery/empty_for:2:8: Expected an identifier, but got ')'.
for () {}
^
-parser_test/error_recovery/empty_for:2:8: Expected ';' after this.
+parser/error_recovery/empty_for:2:8: Expected ';' after this.
for () {}
^
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect
index 3f943f9..4263813 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_38415.crash_dart.expect
@@ -1,10 +1,10 @@
Problems reported:
-parser_test/error_recovery/issue_38415.crash:1:15: Expected '[' before this.
+parser/error_recovery/issue_38415.crash:1:15: Expected '[' before this.
f() { m(T<R(<Z
^...
-parser_test/error_recovery/issue_38415.crash:1:15: Expected ';' after this.
+parser/error_recovery/issue_38415.crash:1:15: Expected ';' after this.
f() { m(T<R(<Z
^...
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
index 8edc8ca..b06508d 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
@@ -1,18 +1,18 @@
Problems reported:
-parser_test/error_recovery/issue_39024.crash:1:3: Expected '>' after this.
+parser/error_recovery/issue_39024.crash:1:3: Expected '>' after this.
n<S e(
^
-parser_test/error_recovery/issue_39024.crash:1:7: Expected an identifier, but got ''.
+parser/error_recovery/issue_39024.crash:1:7: Expected an identifier, but got ''.
n<S e(
^...
-parser_test/error_recovery/issue_39024.crash:1:7: A function declaration needs an explicit list of parameters.
+parser/error_recovery/issue_39024.crash:1:7: A function declaration needs an explicit list of parameters.
n<S e(
^...
-parser_test/error_recovery/issue_39024.crash:1:7: Expected a function body, but got ''.
+parser/error_recovery/issue_39024.crash:1:7: Expected a function body, but got ''.
n<S e(
^...
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.expect
index 01f26fa..0f4b8c9 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026.crash_dart.expect
@@ -1,10 +1,10 @@
Problems reported:
-parser_test/error_recovery/issue_39026.crash:2:8: Operator declarations must be preceded by the keyword 'operator'.
+parser/error_recovery/issue_39026.crash:2:8: Operator declarations must be preceded by the keyword 'operator'.
co <{
^
-parser_test/error_recovery/issue_39026.crash:2:8: A method declaration needs an explicit list of parameters.
+parser/error_recovery/issue_39026.crash:2:8: A method declaration needs an explicit list of parameters.
co <{
^
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.expect
index 93a5c86..ada43dbc 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39026_prime.crash_dart.expect
@@ -1,6 +1,6 @@
Problems reported:
-parser_test/error_recovery/issue_39026_prime.crash:2:17: A method declaration needs an explicit list of parameters.
+parser/error_recovery/issue_39026_prime.crash:2:17: A method declaration needs an explicit list of parameters.
co operator <{
^
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect
index 456c08a..852c662 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39033.crash_dart.expect
@@ -1,14 +1,14 @@
Problems reported:
-parser_test/error_recovery/issue_39033.crash:1:11: Expected '>' after this.
+parser/error_recovery/issue_39033.crash:1:11: Expected '>' after this.
typedef F<Glib.=
^^^^
-parser_test/error_recovery/issue_39033.crash:1:17: Expected a type, but got ''.
+parser/error_recovery/issue_39033.crash:1:17: Expected a type, but got ''.
typedef F<Glib.=
^...
-parser_test/error_recovery/issue_39033.crash:1:17: Expected ';' after this.
+parser/error_recovery/issue_39033.crash:1:17: Expected ';' after this.
typedef F<Glib.=
^...
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.expect
index c326fd9..c60bbb7 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058.crash_dart.expect
@@ -1,6 +1,6 @@
Problems reported:
-parser_test/error_recovery/issue_39058.crash:1:1: Expected a declaration, but got '{'.
+parser/error_recovery/issue_39058.crash:1:1: Expected a declaration, but got '{'.
{<[](
^
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.expect
index fdabfa1..b249f5c 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39058_prime.crash_dart.expect
@@ -1,6 +1,6 @@
Problems reported:
-parser_test/error_recovery/issue_39058_prime.crash:1:1: Expected a declaration, but got '{'.
+parser/error_recovery/issue_39058_prime.crash:1:1: Expected a declaration, but got '{'.
{<[]()>}
^
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.expect
index e6e34e2..a94d802 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39060.dart.expect
@@ -1,18 +1,18 @@
Problems reported:
-parser_test/error_recovery/issue_39060:2:6: Expected ';' after this.
+parser/error_recovery/issue_39060:2:6: Expected ';' after this.
{s A<}>
^
-parser_test/error_recovery/issue_39060:2:8: Expected a type, but got '}'.
+parser/error_recovery/issue_39060:2:8: Expected a type, but got '}'.
{s A<}>
^
-parser_test/error_recovery/issue_39060:3:1: Expected '[' before this.
+parser/error_recovery/issue_39060:3:1: Expected '[' before this.
}
^
-parser_test/error_recovery/issue_39060:3:1: Expected ';' after this.
+parser/error_recovery/issue_39060:3:1: Expected ';' after this.
}
^
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
index a38a1ad..1f51f02 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
@@ -1,30 +1,30 @@
Problems reported:
-parser_test/error_recovery/issue_39202.crash:1:1: Expected a declaration, but got '('.
+parser/error_recovery/issue_39202.crash:1:1: Expected a declaration, but got '('.
() async => a b < c $? >
^
-parser_test/error_recovery/issue_39202.crash:1:2: Expected a declaration, but got ')'.
+parser/error_recovery/issue_39202.crash:1:2: Expected a declaration, but got ')'.
() async => a b < c $? >
^
-parser_test/error_recovery/issue_39202.crash:1:4: A function declaration needs an explicit list of parameters.
+parser/error_recovery/issue_39202.crash:1:4: A function declaration needs an explicit list of parameters.
() async => a b < c $? >
^^^^^
-parser_test/error_recovery/issue_39202.crash:1:13: Expected ';' after this.
+parser/error_recovery/issue_39202.crash:1:13: Expected ';' after this.
() async => a b < c $? >
^
-parser_test/error_recovery/issue_39202.crash:1:19: Expected '>' after this.
+parser/error_recovery/issue_39202.crash:1:19: Expected '>' after this.
() async => a b < c $? >
^
-parser_test/error_recovery/issue_39202.crash:1:25: Expected an identifier, but got ''.
+parser/error_recovery/issue_39202.crash:1:25: Expected an identifier, but got ''.
() async => a b < c $? >
^...
-parser_test/error_recovery/issue_39202.crash:1:25: Expected ';' after this.
+parser/error_recovery/issue_39202.crash:1:25: Expected ';' after this.
() async => a b < c $? >
^...
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect
index 4d40dc0..eabc61b 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39230.crash_dart.expect
@@ -1,14 +1,14 @@
Problems reported:
-parser_test/error_recovery/issue_39230.crash:3:5: Expected a function body, but got '/'.
+parser/error_recovery/issue_39230.crash:3:5: Expected a function body, but got '/'.
/
^
-parser_test/error_recovery/issue_39230.crash:3:5: Operator declarations must be preceded by the keyword 'operator'.
+parser/error_recovery/issue_39230.crash:3:5: Operator declarations must be preceded by the keyword 'operator'.
/
^
-parser_test/error_recovery/issue_39230.crash:3:5: A method declaration needs an explicit list of parameters.
+parser/error_recovery/issue_39230.crash:3:5: A method declaration needs an explicit list of parameters.
/
^
diff --git a/pkg/front_end/parser_testcases/extensions/covariant.dart.expect b/pkg/front_end/parser_testcases/extensions/covariant.dart.expect
index a565916..c797564 100644
--- a/pkg/front_end/parser_testcases/extensions/covariant.dart.expect
+++ b/pkg/front_end/parser_testcases/extensions/covariant.dart.expect
@@ -1,6 +1,6 @@
Problems reported:
-parser_test/extensions/covariant:6:12: Can't have modifier 'covariant' in an extension.
+parser/extensions/covariant:6:12: Can't have modifier 'covariant' in an extension.
addChild(covariant A child) {}
^^^^^^^^^
diff --git a/pkg/front_end/parser_testcases/extensions/static_covariant.dart.expect b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.expect
index 02f803f..1468b4e 100644
--- a/pkg/front_end/parser_testcases/extensions/static_covariant.dart.expect
+++ b/pkg/front_end/parser_testcases/extensions/static_covariant.dart.expect
@@ -1,6 +1,6 @@
Problems reported:
-parser_test/extensions/static_covariant:6:19: Can't have modifier 'covariant' in an extension.
+parser/extensions/static_covariant:6:19: Can't have modifier 'covariant' in an extension.
static addChild(covariant A child) {}
^^^^^^^^^
diff --git a/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.expect b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.expect
index c341804..448f507 100644
--- a/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/general/operator_hat_class.crash_dart.expect
@@ -1,6 +1,6 @@
Problems reported:
-parser_test/general/operator_hat_class.crash:1:7: Can't use 'operator' as a name here.
+parser/general/operator_hat_class.crash:1:7: Can't use 'operator' as a name here.
class operator {
^^^^^^^^
diff --git a/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart b/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart
new file mode 100644
index 0000000..66d340e
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, 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.
+
+class Class1 {
+ int operator [](int index) => index;
+ void operator []=(int index, int value) {}
+}
+
+main() {
+ Class1? c1;
+ c1?.[0];
+ c1?.[0] = 1;
+}
diff --git a/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.expect b/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.expect
new file mode 100644
index 0000000..6e54c69
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.expect
@@ -0,0 +1,120 @@
+beginCompilationUnit(class)
+ beginMetadataStar(class)
+ endMetadataStar(0)
+ beginClassOrNamedMixinApplicationPrelude(class)
+ handleIdentifier(Class1, classOrMixinDeclaration)
+ handleNoTypeVariables({)
+ beginClassDeclaration(class, null, Class1)
+ handleNoType(Class1)
+ handleClassExtends(null)
+ handleClassNoWithClause()
+ handleClassOrMixinImplements(null, 0)
+ handleClassHeader(class, class, null)
+ beginClassOrMixinBody(DeclarationKind.Class, {)
+ beginMetadataStar(int)
+ endMetadataStar(0)
+ beginMember()
+ beginMethod(null, null, null, null, null, operator)
+ handleIdentifier(int, typeReference)
+ handleNoTypeArguments(operator)
+ handleType(int, null)
+ handleOperatorName(operator, [])
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.NonStaticMethod)
+ beginMetadataStar(int)
+ endMetadataStar(0)
+ beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+ handleIdentifier(int, typeReference)
+ handleNoTypeArguments(index)
+ handleType(int, null)
+ handleIdentifier(index, formalParameterDeclaration)
+ handleFormalParameterWithoutValue())
+ endFormalParameter(null, null, index, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ endFormalParameters(1, (, ), MemberKind.NonStaticMethod)
+ handleNoInitializers()
+ handleAsyncModifier(null, null)
+ handleIdentifier(index, expression)
+ handleNoTypeArguments(;)
+ handleNoArguments(;)
+ handleSend(index, ;)
+ handleExpressionFunctionBody(=>, ;)
+ endClassMethod(null, int, (, null, ;)
+ endMember()
+ beginMetadataStar(void)
+ endMetadataStar(0)
+ beginMember()
+ beginMethod(null, null, null, null, null, operator)
+ handleVoidKeyword(void)
+ handleOperatorName(operator, []=)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.NonStaticMethod)
+ beginMetadataStar(int)
+ endMetadataStar(0)
+ beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+ handleIdentifier(int, typeReference)
+ handleNoTypeArguments(index)
+ handleType(int, null)
+ handleIdentifier(index, formalParameterDeclaration)
+ handleFormalParameterWithoutValue(,)
+ endFormalParameter(null, null, index, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ beginMetadataStar(int)
+ endMetadataStar(0)
+ beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+ handleIdentifier(int, typeReference)
+ handleNoTypeArguments(value)
+ handleType(int, null)
+ handleIdentifier(value, formalParameterDeclaration)
+ handleFormalParameterWithoutValue())
+ endFormalParameter(null, null, value, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+ handleNoInitializers()
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ endBlockFunctionBody(0, {, })
+ endClassMethod(null, void, (, null, })
+ endMember()
+ endClassOrMixinBody(DeclarationKind.Class, 2, {, })
+ endClassDeclaration(class, })
+ endTopLevelDeclaration(main)
+ beginMetadataStar(main)
+ endMetadataStar(0)
+ beginTopLevelMember(main)
+ beginTopLevelMethod(}, null)
+ handleNoType(})
+ handleIdentifier(main, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ beginMetadataStar(Class1)
+ endMetadataStar(0)
+ handleIdentifier(Class1, typeReference)
+ handleNoTypeArguments(?)
+ handleType(Class1, ?)
+ beginVariablesDeclaration(c1, null, null)
+ handleIdentifier(c1, localVariableDeclaration)
+ beginInitializedIdentifier(c1)
+ handleNoVariableInitializer(;)
+ endInitializedIdentifier(c1)
+ endVariablesDeclaration(1, ;)
+ handleIdentifier(c1, expression)
+ handleNoTypeArguments(?.[)
+ handleNoArguments(?.[)
+ handleSend(c1, ?.[)
+ handleLiteralInt(0)
+ handleIndexedExpression(?.[, ])
+ handleExpressionStatement(;)
+ handleIdentifier(c1, expression)
+ handleNoTypeArguments(?.[)
+ handleNoArguments(?.[)
+ handleSend(c1, ?.[)
+ handleLiteralInt(0)
+ handleIndexedExpression(?.[, ])
+ handleLiteralInt(1)
+ handleAssignmentExpression(=)
+ handleExpressionStatement(;)
+ endBlockFunctionBody(3, {, })
+ endTopLevelMethod(main, null, })
+ endTopLevelDeclaration()
+endCompilationUnit(2, )
diff --git a/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.intertwined.expect
new file mode 100644
index 0000000..b22c287
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.intertwined.expect
@@ -0,0 +1,255 @@
+parseUnit(class)
+ skipErrorTokens(class)
+ listener: beginCompilationUnit(class)
+ syntheticPreviousToken(class)
+ parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+ parseMetadataStar()
+ listener: beginMetadataStar(class)
+ listener: endMetadataStar(0)
+ parseTopLevelKeywordDeclaration(, class, Instance of 'DirectiveContext')
+ parseClassDeclarationModifiers(, class)
+ parseClassOrNamedMixinApplication(null, class)
+ listener: beginClassOrNamedMixinApplicationPrelude(class)
+ ensureIdentifier(class, classOrMixinDeclaration)
+ listener: handleIdentifier(Class1, classOrMixinDeclaration)
+ listener: handleNoTypeVariables({)
+ listener: beginClassDeclaration(class, null, Class1)
+ parseClass(Class1, class, class, Class1)
+ parseClassHeaderOpt(Class1, class, class)
+ parseClassExtendsOpt(Class1)
+ listener: handleNoType(Class1)
+ listener: handleClassExtends(null)
+ parseWithClauseOpt(Class1)
+ listener: handleClassNoWithClause()
+ parseClassOrMixinImplementsOpt(Class1)
+ listener: handleClassOrMixinImplements(null, 0)
+ listener: handleClassHeader(class, class, null)
+ parseClassOrMixinOrExtensionBody(Class1, DeclarationKind.Class, Class1)
+ listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+ notEofOrValue(}, int)
+ parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, Class1)
+ parseMetadataStar({)
+ listener: beginMetadataStar(int)
+ listener: endMetadataStar(0)
+ listener: beginMember()
+ parseMethod({, null, null, null, null, null, {, Instance of 'SimpleType', null, operator, DeclarationKind.Class, Class1)
+ listener: beginMethod(null, null, null, null, null, operator)
+ listener: handleIdentifier(int, typeReference)
+ listener: handleNoTypeArguments(operator)
+ listener: handleType(int, null)
+ parseOperatorName(int)
+ listener: handleOperatorName(operator, [])
+ parseMethodTypeVar([])
+ listener: handleNoTypeVariables(()
+ parseGetterOrFormalParameters([], operator, false, MemberKind.NonStaticMethod)
+ parseFormalParameters([], MemberKind.NonStaticMethod)
+ parseFormalParametersRest((, MemberKind.NonStaticMethod)
+ listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+ parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ parseMetadataStar(()
+ listener: beginMetadataStar(int)
+ listener: endMetadataStar(0)
+ listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+ listener: handleIdentifier(int, typeReference)
+ listener: handleNoTypeArguments(index)
+ listener: handleType(int, null)
+ ensureIdentifier(int, formalParameterDeclaration)
+ listener: handleIdentifier(index, formalParameterDeclaration)
+ listener: handleFormalParameterWithoutValue())
+ listener: endFormalParameter(null, null, index, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod)
+ parseInitializersOpt())
+ listener: handleNoInitializers()
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ inPlainSync()
+ parseFunctionBody(), false, true)
+ parseExpressionFunctionBody(=>, false)
+ parseExpression(=>)
+ parsePrecedenceExpression(=>, 1, true)
+ parseUnaryExpression(=>, true)
+ parsePrimary(=>, expression)
+ parseSendOrFunctionLiteral(=>, expression)
+ parseSend(=>, expression)
+ ensureIdentifier(=>, expression)
+ listener: handleIdentifier(index, expression)
+ listener: handleNoTypeArguments(;)
+ parseArgumentsOpt(index)
+ listener: handleNoArguments(;)
+ listener: handleSend(index, ;)
+ ensureSemicolon(index)
+ listener: handleExpressionFunctionBody(=>, ;)
+ inGenerator()
+ listener: endClassMethod(null, int, (, null, ;)
+ listener: endMember()
+ notEofOrValue(}, void)
+ parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Class1)
+ parseMetadataStar(;)
+ listener: beginMetadataStar(void)
+ listener: endMetadataStar(0)
+ listener: beginMember()
+ parseMethod(;, null, null, null, null, null, ;, Instance of 'VoidType', null, operator, DeclarationKind.Class, Class1)
+ listener: beginMethod(null, null, null, null, null, operator)
+ listener: handleVoidKeyword(void)
+ parseOperatorName(void)
+ listener: handleOperatorName(operator, []=)
+ parseMethodTypeVar([]=)
+ listener: handleNoTypeVariables(()
+ parseGetterOrFormalParameters([]=, operator, false, MemberKind.NonStaticMethod)
+ parseFormalParameters([]=, MemberKind.NonStaticMethod)
+ parseFormalParametersRest((, MemberKind.NonStaticMethod)
+ listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+ parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ parseMetadataStar(()
+ listener: beginMetadataStar(int)
+ listener: endMetadataStar(0)
+ listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+ listener: handleIdentifier(int, typeReference)
+ listener: handleNoTypeArguments(index)
+ listener: handleType(int, null)
+ ensureIdentifier(int, formalParameterDeclaration)
+ listener: handleIdentifier(index, formalParameterDeclaration)
+ listener: handleFormalParameterWithoutValue(,)
+ listener: endFormalParameter(null, null, index, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ parseMetadataStar(,)
+ listener: beginMetadataStar(int)
+ listener: endMetadataStar(0)
+ listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+ listener: handleIdentifier(int, typeReference)
+ listener: handleNoTypeArguments(value)
+ listener: handleType(int, null)
+ ensureIdentifier(int, formalParameterDeclaration)
+ listener: handleIdentifier(value, formalParameterDeclaration)
+ listener: handleFormalParameterWithoutValue())
+ listener: endFormalParameter(null, null, value, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+ parseInitializersOpt())
+ listener: handleNoInitializers()
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ inPlainSync()
+ parseFunctionBody(), false, true)
+ listener: beginBlockFunctionBody({)
+ notEofOrValue(}, })
+ listener: endBlockFunctionBody(0, {, })
+ listener: endClassMethod(null, void, (, null, })
+ listener: endMember()
+ notEofOrValue(}, })
+ listener: endClassOrMixinBody(DeclarationKind.Class, 2, {, })
+ listener: endClassDeclaration(class, })
+ listener: endTopLevelDeclaration(main)
+ parseTopLevelDeclarationImpl(}, Instance of 'DirectiveContext')
+ parseMetadataStar(})
+ listener: beginMetadataStar(main)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(})
+ listener: beginTopLevelMember(main)
+ parseTopLevelMethod(}, null, }, Instance of 'NoType', null, main)
+ listener: beginTopLevelMethod(}, null)
+ listener: handleNoType(})
+ ensureIdentifier(}, topLevelFunctionDeclaration)
+ listener: handleIdentifier(main, topLevelFunctionDeclaration)
+ parseMethodTypeVar(main)
+ listener: handleNoTypeVariables(()
+ parseGetterOrFormalParameters(main, main, false, MemberKind.TopLevelMethod)
+ parseFormalParameters(main, MemberKind.TopLevelMethod)
+ parseFormalParametersRest((, MemberKind.TopLevelMethod)
+ listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+ listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ parseFunctionBody(), false, false)
+ listener: beginBlockFunctionBody({)
+ notEofOrValue(}, Class1)
+ parseStatement({)
+ parseStatementX({)
+ parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+ looksLikeLocalFunction(c1)
+ listener: beginMetadataStar(Class1)
+ listener: endMetadataStar(0)
+ listener: handleIdentifier(Class1, typeReference)
+ listener: handleNoTypeArguments(?)
+ listener: handleType(Class1, ?)
+ listener: beginVariablesDeclaration(c1, null, null)
+ parseVariablesDeclarationRest(?, true)
+ parseOptionallyInitializedIdentifier(?)
+ ensureIdentifier(?, localVariableDeclaration)
+ listener: handleIdentifier(c1, localVariableDeclaration)
+ listener: beginInitializedIdentifier(c1)
+ parseVariableInitializerOpt(c1)
+ listener: handleNoVariableInitializer(;)
+ listener: endInitializedIdentifier(c1)
+ ensureSemicolon(c1)
+ listener: endVariablesDeclaration(1, ;)
+ notEofOrValue(}, c1)
+ parseStatement(;)
+ parseStatementX(;)
+ parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+ looksLikeLocalFunction(c1)
+ parseExpressionStatement(;)
+ parseExpression(;)
+ parsePrecedenceExpression(;, 1, true)
+ parseUnaryExpression(;, true)
+ parsePrimary(;, expression)
+ parseSendOrFunctionLiteral(;, expression)
+ parseSend(;, expression)
+ ensureIdentifier(;, expression)
+ listener: handleIdentifier(c1, expression)
+ listener: handleNoTypeArguments(?.[)
+ parseArgumentsOpt(c1)
+ listener: handleNoArguments(?.[)
+ listener: handleSend(c1, ?.[)
+ parseArgumentOrIndexStar(c1, Instance of 'NoTypeParamOrArg')
+ parseExpression(?.[)
+ parsePrecedenceExpression(?.[, 1, true)
+ parseUnaryExpression(?.[, true)
+ parsePrimary(?.[, expression)
+ parseLiteralInt(?.[)
+ listener: handleLiteralInt(0)
+ listener: handleIndexedExpression(?.[, ])
+ ensureSemicolon(])
+ listener: handleExpressionStatement(;)
+ notEofOrValue(}, c1)
+ parseStatement(;)
+ parseStatementX(;)
+ parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+ looksLikeLocalFunction(c1)
+ parseExpressionStatement(;)
+ parseExpression(;)
+ parsePrecedenceExpression(;, 1, true)
+ parseUnaryExpression(;, true)
+ parsePrimary(;, expression)
+ parseSendOrFunctionLiteral(;, expression)
+ parseSend(;, expression)
+ ensureIdentifier(;, expression)
+ listener: handleIdentifier(c1, expression)
+ listener: handleNoTypeArguments(?.[)
+ parseArgumentsOpt(c1)
+ listener: handleNoArguments(?.[)
+ listener: handleSend(c1, ?.[)
+ parseArgumentOrIndexStar(c1, Instance of 'NoTypeParamOrArg')
+ parseExpression(?.[)
+ parsePrecedenceExpression(?.[, 1, true)
+ parseUnaryExpression(?.[, true)
+ parsePrimary(?.[, expression)
+ parseLiteralInt(?.[)
+ listener: handleLiteralInt(0)
+ listener: handleIndexedExpression(?.[, ])
+ parsePrecedenceExpression(=, 1, true)
+ parseUnaryExpression(=, true)
+ parsePrimary(=, expression)
+ parseLiteralInt(=)
+ listener: handleLiteralInt(1)
+ listener: handleAssignmentExpression(=)
+ ensureSemicolon(1)
+ listener: handleExpressionStatement(;)
+ notEofOrValue(}, })
+ listener: endBlockFunctionBody(3, {, })
+ listener: endTopLevelMethod(main, null, })
+ listener: endTopLevelDeclaration()
+ reportAllErrorTokens(class)
+ listener: endCompilationUnit(2, )
diff --git a/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.parser.expect
new file mode 100644
index 0000000..9dc7175
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.parser.expect
@@ -0,0 +1,23 @@
+class Class1 {
+int operator [](int index) => index;
+void operator []=(int index, int value) {}
+}
+
+main() {
+Class1? c1;
+c1?.[0];
+c1?.[0] = 1;
+}
+
+
+class[KeywordToken] Class1[StringToken] {[BeginToken]
+int[StringToken] operator[KeywordToken] [][SimpleToken]([BeginToken]int[StringToken] index[StringToken])[SimpleToken] =>[SimpleToken] index[StringToken];[SimpleToken]
+void[KeywordToken] operator[KeywordToken] []=[SimpleToken]([BeginToken]int[StringToken] index[StringToken],[SimpleToken] int[StringToken] value[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+Class1[StringToken]?[SimpleToken] c1[StringToken];[SimpleToken]
+c1[StringToken]?.[[BeginToken]0[StringToken]][SimpleToken];[SimpleToken]
+c1[StringToken]?.[[BeginToken]0[StringToken]][SimpleToken] =[SimpleToken] 1[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.scanner.expect
new file mode 100644
index 0000000..9dc7175
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/null_shorting_index.dart.scanner.expect
@@ -0,0 +1,23 @@
+class Class1 {
+int operator [](int index) => index;
+void operator []=(int index, int value) {}
+}
+
+main() {
+Class1? c1;
+c1?.[0];
+c1?.[0] = 1;
+}
+
+
+class[KeywordToken] Class1[StringToken] {[BeginToken]
+int[StringToken] operator[KeywordToken] [][SimpleToken]([BeginToken]int[StringToken] index[StringToken])[SimpleToken] =>[SimpleToken] index[StringToken];[SimpleToken]
+void[KeywordToken] operator[KeywordToken] []=[SimpleToken]([BeginToken]int[StringToken] index[StringToken],[SimpleToken] int[StringToken] value[StringToken])[SimpleToken] {[BeginToken]}[SimpleToken]
+}[SimpleToken]
+
+main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+Class1[StringToken]?[SimpleToken] c1[StringToken];[SimpleToken]
+c1[StringToken]?.[[BeginToken]0[StringToken]][SimpleToken];[SimpleToken]
+c1[StringToken]?.[[BeginToken]0[StringToken]][SimpleToken] =[SimpleToken] 1[StringToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/test/fasta/fast_strong_suite.dart b/pkg/front_end/test/fasta/fast_strong_suite.dart
index 26c0875..8269eb9 100644
--- a/pkg/front_end/test/fasta/fast_strong_suite.dart
+++ b/pkg/front_end/test/fasta/fast_strong_suite.dart
@@ -14,6 +14,7 @@
Chain suite, Map<String, String> environment) {
environment[ENABLE_FULL_COMPILE] = "";
environment["skipVm"] = "true";
+ environment["verify"] = "false";
return FastaContext.create(suite, environment);
}
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index 20fe91b..22b941b 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -118,11 +118,8 @@
" assignmentOperator: +=)",
new DelayedAssignment(
helper, token, generator, expression, assignmentOperator));
- check(
- "DelayedPostfixIncrement(offset: 4, binaryOperator: +,"
- " interfaceTarget: $uri::#class1::myInterfaceTarget)",
- new DelayedPostfixIncrement(
- helper, token, generator, binaryOperator, interfaceTarget));
+ check("DelayedPostfixIncrement(offset: 4, binaryOperator: +)",
+ new DelayedPostfixIncrement(helper, token, generator, binaryOperator));
check(
"VariableUseGenerator(offset: 4, variable: dynamic #t1;\n,"
" promotedType: void)",
@@ -143,8 +140,10 @@
" getter: $uri::myGetter, setter: $uri::mySetter)",
new SuperPropertyAccessGenerator(helper, token, name, getter, setter));
check(
- "IndexedAccessGenerator(offset: 4, receiver: expression, index: index)",
- new IndexedAccessGenerator(helper, token, expression, index));
+ "IndexedAccessGenerator(offset: 4, receiver: expression, index: index,"
+ " isNullAware: false)",
+ new IndexedAccessGenerator(helper, token, expression, index,
+ isNullAware: false));
check("ThisIndexedAccessGenerator(offset: 4, index: index)",
new ThisIndexedAccessGenerator(helper, token, index));
check(
diff --git a/pkg/front_end/test/fasta/parser/parser.status b/pkg/front_end/test/fasta/parser/parser.status
index c43b22f..94d326c3 100644
--- a/pkg/front_end/test/fasta/parser/parser.status
+++ b/pkg/front_end/test/fasta/parser/parser.status
@@ -1966,7 +1966,6 @@
tests/lib_strong/mirrors/other_declarations_location_test: Fail
tests/lib_strong/mirrors/syntax_error_test: Fail
tests/lib_strong/mirrors/typevariable_mirror_metadata_test: Fail
-tests/standalone/io/process_exit_negative_test: Fail
tests/standalone/io/snapshot_fail_script: Fail
tests/standalone/io/test_extension: Fail
tests/standalone/io/test_relative_extension: Fail
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 2265921..2972102 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -141,8 +141,17 @@
class TestOptions {
final Map<ExperimentalFlag, bool> experimentalFlags;
+ final bool forceLateLowering;
- TestOptions(this.experimentalFlags);
+ TestOptions(this.experimentalFlags, {this.forceLateLowering})
+ : assert(forceLateLowering != null);
+
+ Map<ExperimentalFlag, bool> computeExperimentalFlags(
+ Map<ExperimentalFlag, bool> forcedExperimentalFlags) {
+ Map<ExperimentalFlag, bool> flags = new Map.from(experimentalFlags);
+ flags.addAll(forcedExperimentalFlags);
+ return flags;
+ }
}
class FastaContext extends ChainContext with MatchContext {
@@ -152,6 +161,7 @@
final bool onlyCrashes;
final Map<ExperimentalFlag, bool> experimentalFlags;
final bool skipVm;
+ final bool verify;
final Map<Component, KernelTarget> componentToTarget =
<Component, KernelTarget>{};
final Map<Component, StringBuffer> componentToDiagnostics =
@@ -181,7 +191,8 @@
this.skipVm,
bool kernelTextSerialization,
this.uriTranslator,
- bool fullCompile)
+ bool fullCompile,
+ this.verify)
: steps = <Step>[
new Outline(fullCompile, updateComments: updateComments),
const Print(),
@@ -226,35 +237,37 @@
///
/// [forcedExperimentalFlags] is used to override the default flags for
/// [description].
- Map<ExperimentalFlag, bool> computeExperimentalFlags(
- TestDescription description,
- Map<ExperimentalFlag, bool> forcedExperimentalFlags) {
+ TestOptions computeTestOptions(TestDescription description) {
Directory directory = new File.fromUri(description.uri).parent;
// TODO(johnniwinther): Support nested test folders?
TestOptions testOptions = _testOptions[directory.uri];
if (testOptions == null) {
+ bool forceLateLowering = false;
List<String> experimentalFlagsArguments = [];
File optionsFile =
new File.fromUri(directory.uri.resolve('test.options'));
if (optionsFile.existsSync()) {
for (String line in optionsFile.readAsStringSync().split('\n')) {
- // TODO(johnniwinther): Support more options if need.
+ line = line.trim();
if (line.startsWith(experimentalFlagOptions)) {
experimentalFlagsArguments =
line.substring(experimentalFlagOptions.length).split('\n');
+ } else if (line.startsWith('--force-late-lowering')) {
+ forceLateLowering = true;
+ } else if (line.isNotEmpty) {
+ throw new UnsupportedError("Unsupported test option '$line'");
}
}
}
- testOptions = new TestOptions(parseExperimentalFlags(
- parseExperimentalArguments(experimentalFlagsArguments),
- onError: (String message) => throw new ArgumentError(message),
- onWarning: (String message) => throw new ArgumentError(message)));
+ testOptions = new TestOptions(
+ parseExperimentalFlags(
+ parseExperimentalArguments(experimentalFlagsArguments),
+ onError: (String message) => throw new ArgumentError(message),
+ onWarning: (String message) => throw new ArgumentError(message)),
+ forceLateLowering: forceLateLowering);
_testOptions[directory.uri] = testOptions;
}
- Map<ExperimentalFlag, bool> flags =
- new Map.from(testOptions.experimentalFlags);
- flags.addAll(forcedExperimentalFlags);
- return flags;
+ return testOptions;
}
Expectation get verificationError => expectationSet["VerificationError"];
@@ -329,6 +342,7 @@
bool updateExpectations = environment["updateExpectations"] == "true";
bool updateComments = environment["updateComments"] == "true";
bool skipVm = environment["skipVm"] == "true";
+ bool verify = environment["verify"] != "false";
bool kernelTextSerialization =
environment.containsKey(KERNEL_TEXT_SERIALIZATION);
String platformBinaries = environment["platformBinaries"];
@@ -348,7 +362,8 @@
skipVm,
kernelTextSerialization,
uriTranslator,
- environment.containsKey(ENABLE_FULL_COMPILE));
+ environment.containsKey(ENABLE_FULL_COMPILE),
+ verify);
}
}
@@ -395,6 +410,7 @@
Future<Result<Component>> run(
TestDescription description, FastaContext context) async {
StringBuffer errors = new StringBuffer();
+ TestOptions testOptions = context.computeTestOptions(description);
ProcessedOptions options = new ProcessedOptions(
options: new CompilerOptions()
..onDiagnostic = (DiagnosticMessage message) {
@@ -404,8 +420,8 @@
errors.writeAll(message.plainTextFormatted, "\n");
}
..environmentDefines = {}
- ..experimentalFlags = context.computeExperimentalFlags(
- description, context.experimentalFlags),
+ ..experimentalFlags =
+ testOptions.computeExperimentalFlags(context.experimentalFlags),
inputs: <Uri>[description.uri]);
return await CompilerContext.runWithOptions(options, (_) async {
// Disable colors to ensure that expectation files are the same across
@@ -414,7 +430,11 @@
Component platform = await context.loadPlatform();
Ticker ticker = new Ticker();
DillTarget dillTarget = new DillTarget(
- ticker, context.uriTranslator, new TestVmTarget(new TargetFlags()));
+ ticker,
+ context.uriTranslator,
+ new TestVmTarget(new TargetFlags(
+ forceLateLoweringForTesting: testOptions.forceLateLowering)),
+ );
dillTarget.loader.appendLibraries(platform);
// We create a new URI translator to avoid reading platform libraries from
// file system.
@@ -436,7 +456,7 @@
context.componentToDiagnostics.clear();
context.componentToDiagnostics[p] = errors;
if (fullCompile) {
- p = await sourceTarget.buildComponent();
+ p = await sourceTarget.buildComponent(verify: context.verify);
instrumentation?.finish();
if (instrumentation != null && instrumentation.hasProblems) {
if (updateComments) {
@@ -559,8 +579,7 @@
ClassHierarchyBuilder hierarchy = target.loader.builderHierarchy;
StringBuffer sb = new StringBuffer();
for (ClassHierarchyNode node in hierarchy.nodes.values) {
- node.toString(sb);
- sb.writeln();
+ sb.writeln(node);
}
return context.match<Component>(".hierarchy.expect", "$sb", uri, component);
}
diff --git a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
index 53b52a9c..4e948de 100644
--- a/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_constraint_gatherer_test.dart
@@ -232,7 +232,7 @@
var typeSchemaEnvironment =
new TypeSchemaEnvironment(coreTypes, new ClassHierarchy(component));
var typeConstraintGatherer = new TypeConstraintGatherer(
- typeSchemaEnvironment, [T1.parameter, T2.parameter]);
+ typeSchemaEnvironment, [T1.parameter, T2.parameter], testLib);
var constraints = typeConstraintGatherer.trySubtypeMatch(a, b)
? typeConstraintGatherer.computeConstraints()
: null;
diff --git a/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart b/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
index 95452ab..a804319 100644
--- a/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_inference_engine_test.dart
@@ -224,7 +224,8 @@
isFalse);
}
- TypeParameterType tpt(TypeParameter param, {int variance = null}) =>
- new TypeParameterType(param, Nullability.legacy)
- ..parameter.variance = variance;
+ TypeParameterType tpt(TypeParameter param, {int variance = null}) {
+ return new TypeParameterType(param, Nullability.legacy)
+ ..parameter.variance = variance;
+ }
}
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
index 3d9d3b1..fb49702 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
@@ -276,30 +276,32 @@
void test_inferGenericFunctionOrType() {
var env = _makeEnv();
+ InterfaceType listClassThisType =
+ coreTypes.thisInterfaceType(listClass, testLib.nonNullable);
{
// Test an instantiation of [1, 2.0] with no context. This should infer
// as List<?> during downwards inference.
var inferredTypes = <DartType>[unknownType];
- TypeParameterType T = listClass.thisType.typeArguments[0];
- env.inferGenericFunctionOrType(
- listClass.thisType, [T.parameter], null, null, null, inferredTypes);
+ TypeParameterType T = listClassThisType.typeArguments[0];
+ env.inferGenericFunctionOrType(listClassThisType, [T.parameter], null,
+ null, null, inferredTypes, testLib);
expect(inferredTypes[0], unknownType);
// And upwards inference should refine it to List<num>.
- env.inferGenericFunctionOrType(listClass.thisType, [T.parameter], [T, T],
- [intType, doubleType], null, inferredTypes);
+ env.inferGenericFunctionOrType(listClassThisType, [T.parameter], [T, T],
+ [intType, doubleType], null, inferredTypes, testLib);
expect(inferredTypes[0], numType);
}
{
// Test an instantiation of [1, 2.0] with a context of List<Object>. This
// should infer as List<Object> during downwards inference.
var inferredTypes = <DartType>[unknownType];
- TypeParameterType T = listClass.thisType.typeArguments[0];
- env.inferGenericFunctionOrType(listClass.thisType, [T.parameter], null,
- null, _list(objectType), inferredTypes);
+ TypeParameterType T = listClassThisType.typeArguments[0];
+ env.inferGenericFunctionOrType(listClassThisType, [T.parameter], null,
+ null, _list(objectType), inferredTypes, testLib);
expect(inferredTypes[0], objectType);
// And upwards inference should preserve the type.
- env.inferGenericFunctionOrType(listClass.thisType, [T.parameter], [T, T],
- [intType, doubleType], _list(objectType), inferredTypes);
+ env.inferGenericFunctionOrType(listClassThisType, [T.parameter], [T, T],
+ [intType, doubleType], _list(objectType), inferredTypes, testLib);
expect(inferredTypes[0], objectType);
}
}
@@ -307,7 +309,8 @@
void test_inferTypeFromConstraints_applyBound() {
// class A<T extends num> {}
var T = new TypeParameter('T', numType);
- _addClass(_class('A', typeParameters: [T])).thisType;
+ coreTypes.thisInterfaceType(
+ _addClass(_class('A', typeParameters: [T])), testLib.nonNullable);
var env = _makeEnv();
{
// With no constraints:
diff --git a/pkg/front_end/test/fasta/types/hashcode_test.dart b/pkg/front_end/test/fasta/types/hashcode_test.dart
new file mode 100644
index 0000000..404d446
--- /dev/null
+++ b/pkg/front_end/test/fasta/types/hashcode_test.dart
@@ -0,0 +1,60 @@
+import 'package:expect/expect.dart';
+import 'package:kernel/kernel.dart';
+
+FunctionType createVoidToR() {
+ TypeParameter R = TypeParameter("R", const DynamicType());
+ return new FunctionType(
+ [], new TypeParameterType(R, Nullability.legacy), Nullability.legacy,
+ typeParameters: [R]);
+}
+
+FunctionType createTTo_VoidToR() {
+ TypeParameter T = new TypeParameter("T", const DynamicType());
+ return new FunctionType([new TypeParameterType(T, Nullability.legacy)],
+ createVoidToR(), Nullability.legacy,
+ typeParameters: [T]);
+}
+
+test1() {
+ DartType voidToR1 = createVoidToR();
+ DartType voidToR2 = createVoidToR();
+ DartType voidToR3 = createTTo_VoidToR().returnType;
+ Expect.equals(voidToR1.hashCode, voidToR2.hashCode,
+ "Hash code mismatch for voidToR1 vs voidToR2."); // true
+ Expect.equals(voidToR3, voidToR2); // true
+ Expect.equals(voidToR2.hashCode, voidToR3.hashCode,
+ "Hash code mismatch for voidToR2 vs voidToR3."); // true, good!
+
+ // Get hash code first to force computing and caching the hashCode recursively
+ DartType voidToR4 = (createTTo_VoidToR()..hashCode).returnType;
+ Expect.equals(voidToR4, voidToR2); // true
+ Expect.equals(voidToR2.hashCode, voidToR4.hashCode,
+ "Hash code mismatch for voidToR2 vs voidToR4."); // false, oh no!
+}
+
+FunctionType createVoidTo_VoidToR() {
+ TypeParameter R = new TypeParameter("R", const DynamicType());
+ return new FunctionType(
+ [],
+ new FunctionType(
+ [], new TypeParameterType(R, Nullability.legacy), Nullability.legacy),
+ Nullability.legacy,
+ typeParameters: [R]);
+}
+
+test2() {
+ FunctionType outer1 = createVoidTo_VoidToR();
+ FunctionType outer2 = createVoidTo_VoidToR();
+ DartType voidToR1 = outer1.returnType;
+ DartType voidToR2 = outer2.returnType;
+ outer2.hashCode; // Trigger hashCode caching
+ Expect.equals(outer1, outer2); // true
+ Expect.equals(voidToR1.hashCode, voidToR2.hashCode,
+ "Hash code mismatch for voidToR1 vs voidToR2."); // false, OK
+ Expect.equals(outer1.hashCode, outer2.hashCode,
+ "Hash code mismatch for outer1 vs outer2."); // false, on no!
+}
+
+main() {
+ test2();
+}
diff --git a/pkg/front_end/test/fasta/types/kernel_type_parser.dart b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
index d9e5d85..520d0a3 100644
--- a/pkg/front_end/test/fasta/types/kernel_type_parser.dart
+++ b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
@@ -260,7 +260,13 @@
namedParameters: f.namedParameters,
typeParameters: f.typeParameters,
requiredParameterCount: f.requiredParameterCount,
- typedefType: def.thisType);
+ typedefType: new TypedefType(
+ def,
+ Nullability.nonNullable,
+ def.typeParameters
+ .map((p) => new TypeParameterType(
+ p, TypeParameterType.computeNullabilityFromBound(p)))
+ .toList()));
}
}
return def..type = type;
@@ -315,7 +321,8 @@
TypeParameterType type =
node.a.accept<Node, KernelEnvironment>(this, environment);
DartType bound = node.b.accept<Node, KernelEnvironment>(this, environment);
- return new TypeParameterType(type.parameter, type.nullability, bound);
+ return new TypeParameterType.intersection(
+ type.parameter, type.nullability, bound);
}
Supertype toSupertype(InterfaceType type) {
diff --git a/pkg/front_end/test/flow_analysis/assigned_variables/assigned_variables_test.dart b/pkg/front_end/test/id_tests/assigned_variables_test.dart
similarity index 98%
rename from pkg/front_end/test/flow_analysis/assigned_variables/assigned_variables_test.dart
rename to pkg/front_end/test/id_tests/assigned_variables_test.dart
index 2bdb277..412b439 100644
--- a/pkg/front_end/test/flow_analysis/assigned_variables/assigned_variables_test.dart
+++ b/pkg/front_end/test/id_tests/assigned_variables_test.dart
@@ -19,7 +19,7 @@
main(List<String> args) async {
Directory dataDir = new Directory.fromUri(Platform.script.resolve(
- '../../../../_fe_analyzer_shared/test/flow_analysis/assigned_variables/'
+ '../../../_fe_analyzer_shared/test/flow_analysis/assigned_variables/'
'data'));
await runTests(dataDir,
args: args,
diff --git a/pkg/front_end/test/constants/constant_test.dart b/pkg/front_end/test/id_tests/constant_test.dart
similarity index 100%
rename from pkg/front_end/test/constants/constant_test.dart
rename to pkg/front_end/test/id_tests/constant_test.dart
diff --git a/pkg/front_end/test/flow_analysis/definite_assignment/definite_assignment_test.dart b/pkg/front_end/test/id_tests/definite_assignment_test.dart
similarity index 96%
rename from pkg/front_end/test/flow_analysis/definite_assignment/definite_assignment_test.dart
rename to pkg/front_end/test/id_tests/definite_assignment_test.dart
index 7fa9e26..69be70e 100644
--- a/pkg/front_end/test/flow_analysis/definite_assignment/definite_assignment_test.dart
+++ b/pkg/front_end/test/id_tests/definite_assignment_test.dart
@@ -15,7 +15,7 @@
main(List<String> args) async {
Directory dataDir = new Directory.fromUri(Platform.script.resolve(
- '../../../../_fe_analyzer_shared/test/flow_analysis/definite_assignment/'
+ '../../../_fe_analyzer_shared/test/flow_analysis/definite_assignment/'
'data'));
await runTests(dataDir,
args: args,
diff --git a/pkg/front_end/test/flow_analysis/nullability/nullability_test.dart b/pkg/front_end/test/id_tests/nullability_test.dart
similarity index 96%
rename from pkg/front_end/test/flow_analysis/nullability/nullability_test.dart
rename to pkg/front_end/test/id_tests/nullability_test.dart
index c5473b0..2ff1bca 100644
--- a/pkg/front_end/test/flow_analysis/nullability/nullability_test.dart
+++ b/pkg/front_end/test/id_tests/nullability_test.dart
@@ -12,7 +12,7 @@
main(List<String> args) async {
Directory dataDir = new Directory.fromUri(Platform.script.resolve(
- '../../../../_fe_analyzer_shared/test/flow_analysis/nullability/data'));
+ '../../../_fe_analyzer_shared/test/flow_analysis/nullability/data'));
await runTests(dataDir,
args: args,
supportedMarkers: sharedMarkers,
diff --git a/pkg/front_end/test/flow_analysis/reachability/reachability_test.dart b/pkg/front_end/test/id_tests/reachability_test.dart
similarity index 98%
rename from pkg/front_end/test/flow_analysis/reachability/reachability_test.dart
rename to pkg/front_end/test/id_tests/reachability_test.dart
index 634b4df..2697b7e 100644
--- a/pkg/front_end/test/flow_analysis/reachability/reachability_test.dart
+++ b/pkg/front_end/test/id_tests/reachability_test.dart
@@ -15,7 +15,7 @@
main(List<String> args) async {
Directory dataDir = new Directory.fromUri(Platform.script.resolve(
- '../../../../_fe_analyzer_shared/test/flow_analysis/reachability/data'));
+ '../../../_fe_analyzer_shared/test/flow_analysis/reachability/data'));
await runTests(dataDir,
args: args,
supportedMarkers: sharedMarkers,
diff --git a/pkg/front_end/test/flow_analysis/type_promotion/type_promotion_test.dart b/pkg/front_end/test/id_tests/type_promotion_test.dart
similarity index 94%
rename from pkg/front_end/test/flow_analysis/type_promotion/type_promotion_test.dart
rename to pkg/front_end/test/id_tests/type_promotion_test.dart
index cfaf1e5..03f1e5b 100644
--- a/pkg/front_end/test/flow_analysis/type_promotion/type_promotion_test.dart
+++ b/pkg/front_end/test/id_tests/type_promotion_test.dart
@@ -12,9 +12,9 @@
import 'package:kernel/ast.dart' hide Variance;
main(List<String> args) async {
- Directory dataDir = new Directory.fromUri(Platform.script.resolve(
- '../../../../_fe_analyzer_shared/test/flow_analysis/type_promotion/'
- 'data'));
+ Directory dataDir = new Directory.fromUri(Platform.script
+ .resolve('../../../_fe_analyzer_shared/test/flow_analysis/type_promotion/'
+ 'data'));
await runTests(dataDir,
args: args,
supportedMarkers: sharedMarkers,
diff --git a/pkg/front_end/test/incremental_dart2js_tester.dart b/pkg/front_end/test/incremental_dart2js_tester.dart
new file mode 100644
index 0000000..7bdcdef
--- /dev/null
+++ b/pkg/front_end/test/incremental_dart2js_tester.dart
@@ -0,0 +1,171 @@
+// Copyright (c) 2019, 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.
+
+import 'dart:io' show Platform;
+
+import 'package:front_end/src/api_prototype/compiler_options.dart';
+import 'package:front_end/src/api_unstable/bazel_worker.dart';
+
+import 'package:kernel/kernel.dart'
+ show Component, Library, LibraryPart, Reference;
+
+import 'incremental_load_from_dill_suite.dart' as helper;
+
+import "incremental_utils.dart" as util;
+
+main(List<String> args) async {
+ bool fast = false;
+ bool useExperimentalInvalidation = false;
+ for (String arg in args) {
+ if (arg == "--fast") {
+ fast = true;
+ } else if (arg == "--experimental") {
+ useExperimentalInvalidation = true;
+ } else {
+ throw "Unsupported argument: $arg";
+ }
+ }
+
+ Stopwatch stopwatch = new Stopwatch()..start();
+ Uri input = Platform.script.resolve("../../compiler/bin/dart2js.dart");
+ CompilerOptions options = helper.getOptions(targetName: "None");
+ helper.TestIncrementalCompiler compiler =
+ new helper.TestIncrementalCompiler(options, input);
+ compiler.useExperimentalInvalidation = useExperimentalInvalidation;
+ Component c = await compiler.computeDelta();
+ print("Compiled dart2js to Component with ${c.libraries.length} libraries "
+ "in ${stopwatch.elapsedMilliseconds} ms.");
+ stopwatch.reset();
+ List<int> firstCompileData;
+ Map<Uri, List<int>> libToData;
+ if (fast) {
+ libToData = {};
+ c.libraries.sort((l1, l2) {
+ return "${l1.fileUri}".compareTo("${l2.fileUri}");
+ });
+
+ c.problemsAsJson?.sort();
+
+ c.computeCanonicalNames();
+
+ for (Library library in c.libraries) {
+ library.additionalExports.sort((Reference r1, Reference r2) {
+ return "${r1.canonicalName}".compareTo("${r2.canonicalName}");
+ });
+ library.problemsAsJson?.sort();
+
+ List<int> libSerialized =
+ serializeComponent(c, filter: (l) => l == library);
+ libToData[library.importUri] = libSerialized;
+ }
+ } else {
+ firstCompileData = util.postProcess(c);
+ }
+ print("Serialized in ${stopwatch.elapsedMilliseconds} ms");
+ stopwatch.reset();
+
+ List<Uri> uris = c.uriToSource.values
+ .map((s) => s != null ? s.importUri : null)
+ .where((u) => u != null && u.scheme != "dart")
+ .toSet()
+ .toList();
+
+ c = null;
+
+ List<Uri> diffs = new List<Uri>();
+
+ Stopwatch localStopwatch = new Stopwatch()..start();
+ for (int i = 0; i < uris.length; i++) {
+ Uri uri = uris[i];
+ print("Invalidating $uri ($i)");
+ compiler.invalidate(uri);
+ localStopwatch.reset();
+ Component c2 = await compiler.computeDelta(fullComponent: true);
+ print("Recompiled in ${localStopwatch.elapsedMilliseconds} ms");
+ print("invalidatedImportUrisForTesting: "
+ "${compiler.invalidatedImportUrisForTesting}");
+ print("rebuildBodiesCount: ${compiler.rebuildBodiesCount}");
+ localStopwatch.reset();
+
+ if (fast) {
+ c2.libraries.sort((l1, l2) {
+ return "${l1.fileUri}".compareTo("${l2.fileUri}");
+ });
+
+ c2.problemsAsJson?.sort();
+
+ c2.computeCanonicalNames();
+
+ int foundCount = 0;
+ for (Library library in c2.libraries) {
+ Set<Uri> uris = new Set<Uri>();
+ uris.add(library.importUri);
+ for (LibraryPart part in library.parts) {
+ Uri uri = library.importUri.resolve(part.partUri);
+ uris.add(uri);
+ }
+ if (!uris.contains(uri)) continue;
+ foundCount++;
+ library.additionalExports.sort((Reference r1, Reference r2) {
+ return "${r1.canonicalName}".compareTo("${r2.canonicalName}");
+ });
+ library.problemsAsJson?.sort();
+
+ List<int> libSerialized =
+ serializeComponent(c2, filter: (l) => l == library);
+ if (!isEqual(libToData[library.importUri], libSerialized)) {
+ print("=====");
+ print("=====");
+ print("=====");
+ print("Notice diff on $uri ($i)!");
+ libToData[library.importUri] = libSerialized;
+ diffs.add(uri);
+ print("=====");
+ print("=====");
+ print("=====");
+ }
+ }
+ if (foundCount != 1) {
+ throw "Expected to find $uri, but it $foundCount times.";
+ }
+ print("Serialized library in ${localStopwatch.elapsedMilliseconds} ms");
+ } else {
+ List<int> thisCompileData = util.postProcess(c2);
+ print("Serialized in ${localStopwatch.elapsedMilliseconds} ms");
+ if (!isEqual(firstCompileData, thisCompileData)) {
+ print("=====");
+ print("=====");
+ print("=====");
+ print("Notice diff on $uri ($i)!");
+ firstCompileData = thisCompileData;
+ diffs.add(uri);
+ print("=====");
+ print("=====");
+ print("=====");
+ }
+ }
+ print("-----");
+ }
+
+ print("A total of ${diffs.length} diffs:");
+ for (Uri uri in diffs) {
+ print(" - $uri");
+ }
+
+ print("Done after ${uris.length} recompiles in "
+ "${stopwatch.elapsedMilliseconds} ms");
+}
+
+bool isEqual(List<int> a, List<int> b) {
+ int length = a.length;
+ if (b.length != length) {
+ return false;
+ }
+ for (int i = 0; i < length; ++i) {
+ if (a[i] != b[i]) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/pkg/front_end/test/incremental_load_from_dill_suite.dart b/pkg/front_end/test/incremental_load_from_dill_suite.dart
index 48a4d48..c6f326d 100644
--- a/pkg/front_end/test/incremental_load_from_dill_suite.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_suite.dart
@@ -9,6 +9,8 @@
import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
show DiagnosticMessage, getMessageCodeObject;
+import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;
+
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
import 'package:expect/expect.dart' show Expect;
@@ -77,6 +79,9 @@
Future<Context> createContext(
Chain suite, Map<String, String> environment) async {
+ // Disable colors to ensure that expectation files are the same across
+ // platforms and independent of stdin/stderr.
+ colors.enableColors = false;
return new Context(environment["updateExpectations"] == "true");
}
@@ -483,6 +488,11 @@
}
}
+ compiler.useExperimentalInvalidation = false;
+ if (world["useExperimentalInvalidation"] == true) {
+ compiler.useExperimentalInvalidation = true;
+ }
+
List<Uri> invalidated = new List<Uri>();
if (world["invalidate"] != null) {
for (String filename in world["invalidate"]) {
@@ -592,7 +602,9 @@
if (context.updateExpectations) {
file.writeAsStringSync(actualSerialized);
} else if (expected != actualSerialized) {
- throw "Unexpected serialized representation. "
+ String extra = "";
+ if (expected == null) extra = "Expect file did not exist.\n";
+ throw "${extra}Unexpected serialized representation. "
"Fix or update $uri to contain the below:\n\n"
"$actualSerialized";
}
@@ -629,6 +641,12 @@
}
}
+ if (world["expectsRebuildBodiesOnly"] != null) {
+ bool didRebuildBodiesOnly = compiler.rebuildBodiesCount > 0;
+ Expect.equals(world["expectsRebuildBodiesOnly"], didRebuildBodiesOnly,
+ "Whether we expected to rebuild bodies only.");
+ }
+
if (!noFullComponent) {
List<Library> entryLib = component.libraries
.where((Library lib) =>
@@ -1231,6 +1249,7 @@
class TestIncrementalCompiler extends IncrementalCompiler {
Set<Uri> invalidatedImportUrisForTesting;
+ int rebuildBodiesCount;
final Uri entryPoint;
/// Filter out the automatically added entryPoint, unless it's explicitly
@@ -1292,6 +1311,11 @@
}
@override
+ void recordRebuildBodiesCountForTesting(int count) {
+ rebuildBodiesCount = count;
+ }
+
+ @override
Future<Component> computeDelta(
{List<Uri> entryPoints,
bool fullComponent = false,
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 5f05c67..ac01f71 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -141,6 +141,7 @@
clazz
cls
cn
+cnt
co
codebase
codec
@@ -320,6 +321,8 @@
fffff
ffffffff
ffi
+field1
+field2
file's
filenames
finv
@@ -423,6 +426,7 @@
insertion
inspector
inspired
+inst
instanceof
instantiator
intentionally
@@ -454,6 +458,7 @@
juxtaposition
juxtapositions
k
+k’s
kallentu
kernel's
kernel2kernel
@@ -461,7 +466,6 @@
kmillikin
kustermann
kv
-k’s
l
lacks
lang
@@ -639,13 +643,13 @@
quick
quoted
r
-r'$creation
r'\f
r'\r
r'\s
r'\t
r'\u
r'\v
+r'$creation
ra
radix
raises
@@ -663,6 +667,7 @@
reassigned
rebind
rebuild
+rebuilds
recalculating
recalculation
recall
@@ -705,6 +710,7 @@
respond
restriction
resumed
+ret
rewrites
rewrote
rf
@@ -1021,6 +1027,8 @@
xm
xn
xor
+xs
+xss
xterm
xx
xxxx
@@ -1032,6 +1040,8 @@
yet
yielding
yields
+ys
+yss
z
zi
zip
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 301934c..474a457 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -53,6 +53,7 @@
acyclic
ad
adapt
+adapted
add
added
adding
@@ -73,6 +74,7 @@
advancing
advice
affect
+affected
affects
after
again
@@ -84,6 +86,8 @@
algorithm
algorithms
alias
+aliased
+aliases
alignment
all
allocated
@@ -105,6 +109,7 @@
alternatively
alternatives
although
+altogether
always
ambiguous
among
@@ -217,6 +222,7 @@
average
avoid
avoided
+avoiding
avoids
await
awaiter
@@ -528,6 +534,7 @@
concurrent
condition
conditional
+conditionals
conditionally
conditions
configurable
@@ -611,6 +618,7 @@
converting
converts
cookie
+coordinate
cope
copied
copier
@@ -728,6 +736,7 @@
delimiter
delimiters
delta
+demote
demoted
demoting
demotion
@@ -762,6 +771,7 @@
deserialize
deserialized
designed
+desired
desugar
desugared
desugaring
@@ -916,6 +926,7 @@
encoder
encodes
encoding
+encodings
encounter
encountered
encountering
@@ -1073,6 +1084,7 @@
failures
fake
fall
+fallback
falls
false
far
@@ -1085,6 +1097,7 @@
features
feed
feel
+fetch
few
fewer
field
@@ -1665,6 +1678,7 @@
lowercase
lowered
lowering
+lowerings
machine
made
magenta
@@ -1849,6 +1863,7 @@
nodes
non
none
+nonfunction
nor
normal
normalize
@@ -2297,6 +2312,7 @@
regress
regression
regular
+reinsert
reissue
rejected
rejects
@@ -2410,6 +2426,8 @@
reusing
reverse
reversed
+revert
+reverts
review
revise
revision
@@ -2444,6 +2462,8 @@
said
sake
same
+sample
+samples
sanity
satisfied
satisfies
@@ -2515,6 +2535,7 @@
setter
setters
setting
+settings
settled
setup
several
@@ -2636,6 +2657,7 @@
squiggly
stable
stack
+stacked
stage
stamps
standalone
@@ -2649,6 +2671,7 @@
starts
startup
state
+stateful
statement
statement's
statements
@@ -2716,6 +2739,7 @@
success
successful
successfully
+successively
succinct
such
suffice
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index ff871b9..ebb6a1d 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -285,6 +285,7 @@
reachability
reality
recompile
+recompiles
redir
redirections
reducer
diff --git a/pkg/front_end/test/static_types/data/class_call.dart b/pkg/front_end/test/static_types/data/class_call.dart
new file mode 100644
index 0000000..9aa0258
--- /dev/null
+++ b/pkg/front_end/test/static_types/data/class_call.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2019, 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.
+
+/*cfe|dart2js.library: nnbd=false*/
+/*cfe:nnbd.library: nnbd=true*/
+
+abstract class ClassWithCall {
+ ClassWithCall call();
+ int method();
+}
+
+class Class {
+ ClassWithCall classWithCall;
+
+ int method() =>
+ /*cfe|dart2js.invoke: ClassWithCall*/
+ /*cfe:nnbd.invoke: ClassWithCall!*/
+ classWithCall()
+ . /*cfe|dart2js.invoke: int*/
+ /*cfe:nnbd.invoke: int!*/
+ method();
+}
+
+abstract class GenericClassWithCall<T> {
+ T call();
+ T method();
+}
+
+class GenericClass<S, T extends GenericClassWithCall<S>> {
+ GenericClassWithCall<T> classWithCall;
+
+ S method() =>
+ /*cfe|dart2js.invoke: T*/ /*cfe:nnbd.invoke: T!*/ classWithCall()
+ . /*cfe|dart2js.invoke: S*/ /*cfe:nnbd.invoke: S%*/ method();
+}
+
+main() {
+ new /*cfe|dart2js.GenericClass<String,GenericClassWithCall<String>>*/
+ /*cfe:nnbd.GenericClass<String!,GenericClassWithCall<String!>!>!*/
+ GenericClass<String, GenericClassWithCall<String>>
+ /*cfe|dart2js.<String,GenericClassWithCall<String>>*/
+ /*cfe:nnbd.<String!,GenericClassWithCall<String!>!>*/ ()
+ . /*cfe|dart2js.invoke: GenericClassWithCall<String>*/
+ /*cfe:nnbd.invoke: GenericClassWithCall<String!>!*/
+ classWithCall()
+ . /*cfe|dart2js.invoke: String*/ /*cfe:nnbd.invoke: String!*/ method();
+}
diff --git a/pkg/front_end/test/static_types/data/constraint_gatherer_for_future_or.dart b/pkg/front_end/test/static_types/data/constraint_gatherer_for_future_or.dart
index 33e0785..2bce49c 100644
--- a/pkg/front_end/test/static_types/data/constraint_gatherer_for_future_or.dart
+++ b/pkg/front_end/test/static_types/data/constraint_gatherer_for_future_or.dart
@@ -51,7 +51,8 @@
void func5() {
void foo<S>(FutureOr<S> bar) {}
- /*invoke: void*/ foo /*cfe|dart2js.<int>*/ /*cfe:nnbd.<int!>*/ (/*int*/ 42);
+ /*invoke: void*/ foo /*cfe|dart2js.<int>*/ /*cfe:nnbd.<int!>*/ (
+ /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 42);
}
// -----------------------------------------------------------------------------
@@ -60,7 +61,8 @@
void func6() {
void foo<S>(S bar) {}
- /*invoke: void*/ foo /*cfe|dart2js.<int>*/ /*cfe:nnbd.<int!>*/ (/*int*/ 42);
+ /*invoke: void*/ foo /*cfe|dart2js.<int>*/ /*cfe:nnbd.<int!>*/ (
+ /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 42);
}
// -----------------------------------------------------------------------------
@@ -68,7 +70,8 @@
void func7() {
void foo<S>(FutureOr<FutureOr<S>> bar) {}
- /*invoke: void*/ foo /*cfe|dart2js.<int>*/ /*cfe:nnbd.<int!>*/ (/*int*/ 42);
+ /*invoke: void*/ foo /*cfe|dart2js.<int>*/ /*cfe:nnbd.<int!>*/ (
+ /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 42);
}
// -----------------------------------------------------------------------------
diff --git a/pkg/front_end/test/static_types/data/greatest_lower_bound_for_future_or.dart b/pkg/front_end/test/static_types/data/greatest_lower_bound_for_future_or.dart
index 6c3c239..e2783e6 100644
--- a/pkg/front_end/test/static_types/data/greatest_lower_bound_for_future_or.dart
+++ b/pkg/front_end/test/static_types/data/greatest_lower_bound_for_future_or.dart
@@ -26,7 +26,7 @@
// Type of the expression is GLB(FutureOr<T>, Foo) = T.
/*invoke: void*/ context(
- /*invoke: T*/ expr
+ /*cfe|dart2js.invoke: T*/ /*cfe:nnbd.invoke: T!*/ expr
/*cfe|dart2js.<T>*/
/*cfe:nnbd.<T!>*/ ());
}
@@ -41,9 +41,9 @@
// Type of the expression is GLB(FutureOr<T>, Future<Foo>) = Future<T>.
/*invoke: void*/ context(
/*cfe|dart2js.invoke: Future<T>*/
- /*cfe:nnbd.invoke: Future<T!>*/ expr
+ /*cfe:nnbd.invoke: Future<T!>!*/ expr
/*cfe|dart2js.<Future<T>>*/
- /*cfe:nnbd.<Future<T!>>*/ ());
+ /*cfe:nnbd.<Future<T!>!>*/ ());
}
// -----------------------------------------------------------------------------
@@ -55,7 +55,7 @@
// Type of the expression is GLB(T, FutureOr<Foo>) = T.
/*invoke: void*/ context(
- /*invoke: T*/ expr
+ /*cfe|dart2js.invoke: T*/ /*cfe:nnbd.invoke: T!*/ expr
/*cfe|dart2js.<T>*/
/*cfe:nnbd.<T!>*/ ());
}
@@ -70,7 +70,7 @@
// Type of the expression is GLB(Future<T>, FutureOr<Foo>) = Future<T>.
/*invoke: void*/ context(
/*cfe|dart2js.invoke: Future<T>*/
- /*cfe:nnbd.invoke: Future<T!>*/ expr
+ /*cfe:nnbd.invoke: Future<T!>!*/ expr
/*cfe|dart2js.<Future<T>>*/
/*cfe:nnbd.<Future<T!>!>*/ ());
}
@@ -87,9 +87,9 @@
// = FutureOr<Future<T>>.
/*invoke: void*/ context(
/*cfe|dart2js.invoke: FutureOr<Future<T>>*/
- /*cfe:nnbd.invoke: FutureOr<Future<T!>>*/ expr
+ /*cfe:nnbd.invoke: FutureOr<Future<T!>!>!*/ expr
/*cfe|dart2js.<FutureOr<Future<T>>>*/
- /*cfe:nnbd.<FutureOr<Future<T!>>>*/ ());
+ /*cfe:nnbd.<FutureOr<Future<T!>!>!>*/ ());
}
// -----------------------------------------------------------------------------
diff --git a/pkg/front_end/test/static_types/data/list_literals.dart b/pkg/front_end/test/static_types/data/list_literals.dart
index c8fb05d..8cb149c 100644
--- a/pkg/front_end/test/static_types/data/list_literals.dart
+++ b/pkg/front_end/test/static_types/data/list_literals.dart
@@ -6,13 +6,25 @@
/*cfe:nnbd.library: nnbd=true*/
main() {
- /*List<dynamic>*/ [];
+ /*cfe|dart2js.List<dynamic>*/
+ /*cfe:nnbd.List<dynamic>!*/
+ [];
/*cfe|dart2js.List<int>*/
- /*cfe:nnbd.List<int!>*/
- [/*int*/ 0];
+ /*cfe:nnbd.List<int!>!*/
+ [/*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0];
- /*List<num>*/ [/*int*/ 0, /*double*/ 0.5];
+ /*cfe|dart2js.List<num>*/
+ /*cfe:nnbd.List<num>!*/
+ [
+ /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0,
+ /*cfe|dart2js.double*/ /*cfe:nnbd.double!*/ 0.5
+ ];
- /*List<Object>*/ [/*int*/ 0, /*String*/ ''];
+ /*cfe|dart2js.List<Object>*/
+ /*cfe:nnbd.List<Object>!*/
+ [
+ /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0,
+ /*cfe|dart2js.String*/ /*cfe:nnbd.String!*/ ''
+ ];
}
diff --git a/pkg/front_end/test/static_types/data/literals.dart b/pkg/front_end/test/static_types/data/literals.dart
index 52c32a1..9d985bb 100644
--- a/pkg/front_end/test/static_types/data/literals.dart
+++ b/pkg/front_end/test/static_types/data/literals.dart
@@ -7,10 +7,10 @@
main() {
/*Null*/ null;
- /*bool*/ true;
- /*bool*/ false;
- /*String*/ 'foo';
- /*int*/ 42;
- /*double*/ 0.5;
- /*Symbol*/ #main;
+ /*cfe|dart2js.bool*/ /*cfe:nnbd.bool!*/ true;
+ /*cfe|dart2js.bool*/ /*cfe:nnbd.bool!*/ false;
+ /*cfe|dart2js.String*/ /*cfe:nnbd.String!*/ 'foo';
+ /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 42;
+ /*cfe|dart2js.double*/ /*cfe:nnbd.double!*/ 0.5;
+ /*cfe|dart2js.Symbol*/ /*cfe:nnbd.Symbol!*/ #main;
}
diff --git a/pkg/front_end/test/static_types/data/map_literals.dart b/pkg/front_end/test/static_types/data/map_literals.dart
index ce2e5fb..c83e20c 100644
--- a/pkg/front_end/test/static_types/data/map_literals.dart
+++ b/pkg/front_end/test/static_types/data/map_literals.dart
@@ -7,65 +7,148 @@
main() {
// ignore: unused_local_variable
- var a0 = /*Map<dynamic,dynamic>*/ {};
+ var a0 =
+ /*cfe|dart2js.Map<dynamic,dynamic>*/
+ /*cfe:nnbd.Map<dynamic,dynamic>!*/
+ {};
// ignore: unused_local_variable
var a1 =
/*cfe|dart2js.Map<int,double>*/
- /*cfe:nnbd.Map<int!,double!>*/
- {/*int*/ 0: /*double*/ 0.5 };
+ /*cfe:nnbd.Map<int!,double!>!*/
+ {
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0:
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5
+ };
// ignore: unused_local_variable
var a2 =
/*cfe|dart2js.Map<double,int>*/
- /*cfe:nnbd.Map<double!,int!>*/
- {/*double*/ 0.5: /*int*/ 0 };
+ /*cfe:nnbd.Map<double!,int!>!*/
+ {
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5:
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0
+ };
// ignore: unused_local_variable
var a3 =
/*cfe|dart2js.Map<int,num>*/
- /*cfe:nnbd.Map<int!,num>*/
+ /*cfe:nnbd.Map<int!,num>!*/
{
- /*int*/ 0: /*double*/ 0.5,
- /*int*/ 1: /*int*/ 2
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0:
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5,
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 1:
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 2
};
// ignore: unused_local_variable
var a4 =
/*cfe|dart2js.Map<num,double>*/
- /*cfe:nnbd.Map<num,double!>*/
+ /*cfe:nnbd.Map<num,double!>!*/
{
- /*int*/ 0: /*double*/ 0.5,
- /*double*/ 0.5: /*double*/ 0.5
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0:
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5,
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5:
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5
};
// ignore: unused_local_variable
- var a5 = /*Map<num,num>*/ {
- /*int*/ 0: /*double*/ 0.5,
- /*double*/ 0.5: /*int*/ 0
+ var a5 =
+ /*cfe|dart2js.Map<num,num>*/
+ /*cfe:nnbd.Map<num,num>!*/
+ {
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0:
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5,
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5:
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0
};
// ignore: unused_local_variable
var a6 =
/*cfe|dart2js.Map<int,Object>*/
- /*cfe:nnbd.Map<int!,Object>*/
+ /*cfe:nnbd.Map<int!,Object>!*/
{
- /*int*/ 0: /*double*/ 0.5,
- /*int*/ 1: /*String*/ ''
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0:
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5,
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 1:
+ /*cfe|dart2js.String*/
+ /*cfe:nnbd.String!*/
+ ''
};
// ignore: unused_local_variable
var a7 =
/*cfe|dart2js.Map<Object,double>*/
- /*cfe:nnbd.Map<Object,double!>*/
+ /*cfe:nnbd.Map<Object,double!>!*/
{
- /*int*/ 0: /*double*/ 0.5,
- /*String*/ '': /*double*/ 0.5
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0:
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5,
+ /*cfe|dart2js.String*/
+ /*cfe:nnbd.String!*/
+ '':
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5
};
// ignore: unused_local_variable
- var a8 = /*Map<Object,Object>*/ {
- /*int*/ 0: /*double*/ 0.5,
- /*String*/ '': /*String*/ ''
+ var a8 =
+ /*cfe|dart2js.Map<Object,Object>*/
+ /*cfe:nnbd.Map<Object,Object>!*/
+ {
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0:
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5,
+ /*cfe|dart2js.String*/
+ /*cfe:nnbd.String!*/
+ '':
+ /*cfe|dart2js.String*/
+ /*cfe:nnbd.String!*/
+ ''
};
}
diff --git a/pkg/front_end/test/static_types/data/null_aware_for_in.dart b/pkg/front_end/test/static_types/data/null_aware_for_in.dart
index 6f59a39..be939a7 100644
--- a/pkg/front_end/test/static_types/data/null_aware_for_in.dart
+++ b/pkg/front_end/test/static_types/data/null_aware_for_in.dart
@@ -13,6 +13,8 @@
/*cfe:nnbd.as: Class!*/
for (
// ignore: UNUSED_LOCAL_VARIABLE
- Class c
- in /*as: Iterable<dynamic>*/ /*dynamic*/ o?. /*dynamic*/ iterable) {}
+ Class c in
+ /*cfe|dart2js.as: Iterable<dynamic>*/
+ /*cfe:nnbd.as: Iterable<dynamic>!*/
+ /*dynamic*/ o?. /*dynamic*/ iterable) {}
}
diff --git a/pkg/front_end/test/static_types/data/prefix_postfix.dart b/pkg/front_end/test/static_types/data/prefix_postfix.dart
index 71db218..2913a74 100644
--- a/pkg/front_end/test/static_types/data/prefix_postfix.dart
+++ b/pkg/front_end/test/static_types/data/prefix_postfix.dart
@@ -5,31 +5,49 @@
/*cfe.library: nnbd=false*/
/*cfe:nnbd.library: nnbd=true*/
-num numTopLevel = /*int*/ 0;
-int intTopLevel = /*int*/ 0;
-dynamic dynamicTopLevel = /*int*/ 0;
+num numTopLevel = /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0;
+int intTopLevel = /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0;
+dynamic dynamicTopLevel = /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0;
testTopLevel() {
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
/*cfe:nnbd.num!*/
- numTopLevel /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++;
+ numTopLevel
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
/*cfe:nnbd.num!*/
- numTopLevel /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --;
+ numTopLevel
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
- /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
/*cfe:nnbd.num!*/
numTopLevel;
- /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
@@ -43,7 +61,9 @@
intTopLevel
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ ++;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
/*cfe|dart2js.update: int*/
/*cfe:nnbd.update: int!*/
@@ -52,11 +72,15 @@
intTopLevel
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ --;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ ++
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*cfe|dart2js.update: int*/
/*cfe:nnbd.update: int!*/
/*cfe|dart2js.int*/
@@ -65,7 +89,9 @@
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ --
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*cfe|dart2js.update: int*/
/*cfe:nnbd.update: int!*/
/*cfe|dart2js.int*/
@@ -73,22 +99,34 @@
intTopLevel;
/*update: dynamic*/ /*dynamic*/ dynamicTopLevel
- /*invoke: dynamic*/ /*int*/ ++;
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
/*update: dynamic*/ /*dynamic*/ dynamicTopLevel
- /*invoke: dynamic*/ /*int*/ --;
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
- /*invoke: dynamic*/ /*int*/ ++
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*update: dynamic*/ /*dynamic*/ dynamicTopLevel;
- /*invoke: dynamic*/ /*int*/ --
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*update: dynamic*/ /*dynamic*/ dynamicTopLevel;
}
class Class {
- num numInstance = /*int*/ 0;
- int intInstance = /*int*/ 0;
- dynamic dynamicInstance = /*int*/ 0;
+ num numInstance = /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0;
+ int intInstance = /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0;
+ dynamic dynamicInstance = /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0;
testInstance() {
/*cfe|dart2js.update: num*/
@@ -98,7 +136,9 @@
numInstance
/*cfe|dart2js.invoke: num*/
/*cfe:nnbd.invoke: num!*/
- /*int*/ ++;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
@@ -107,16 +147,26 @@
numInstance
/*cfe|dart2js.invoke: num*/
/*cfe:nnbd.invoke: num!*/
- /*int*/ --;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
- /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
/*cfe:nnbd.num!*/
numInstance;
- /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
@@ -130,7 +180,9 @@
intInstance
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ ++;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
/*cfe|dart2js.update: int*/
/*cfe:nnbd.update: int!*/
@@ -139,11 +191,15 @@
intInstance
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ --;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ ++
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*cfe|dart2js.update: int*/
/*cfe:nnbd.update: int!*/
/*cfe|dart2js.int*/
@@ -152,7 +208,9 @@
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ --
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*cfe|dart2js.update: int*/
/*cfe:nnbd.update: int!*/
/*cfe|dart2js.int*/
@@ -160,12 +218,24 @@
intInstance;
/*update: dynamic*/ /*dynamic*/ dynamicInstance
- /*invoke: dynamic*/ /*int*/ ++;
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
/*update: dynamic*/ /*dynamic*/ dynamicInstance
- /*invoke: dynamic*/ /*int*/ --;
- /*invoke: dynamic*/ /*int*/ ++
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*update: dynamic*/ /*dynamic*/ dynamicInstance;
- /*invoke: dynamic*/ /*int*/ --
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*update: dynamic*/ /*dynamic*/ dynamicInstance;
}
}
@@ -179,7 +249,10 @@
numInstance
/*cfe|dart2js.invoke: num*/
/*cfe:nnbd.invoke: num!*/
- /*int*/ ++;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
+
/*cfe|dart2js.Class*/
/*cfe:nnbd.Class!*/
c. /*cfe|dart2js.update: num*/ /*cfe:nnbd.update: num!*/
@@ -188,18 +261,31 @@
numInstance
/*cfe|dart2js.invoke: num*/
/*cfe:nnbd.invoke: num!*/
- /*int*/ --;
- /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
+
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*cfe|dart2js.Class*/
/*cfe:nnbd.Class!*/
- c. /*cfe|dart2js.update: num*/ /*cfe:nnbd.update: num!*/
+ c. /*cfe|dart2js.update: num*/
+ /*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
/*cfe:nnbd.num!*/
numInstance;
- /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*cfe|dart2js.Class*/
/*cfe:nnbd.Class!*/
- c. /*cfe|dart2js.update: num*/ /*cfe:nnbd.update: num!*/
+ c. /*cfe|dart2js.update: num*/
+ /*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
/*cfe:nnbd.num!*/
numInstance;
@@ -214,7 +300,9 @@
intInstance
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ ++;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
/*cfe|dart2js.Class*/
/*cfe:nnbd.Class!*/
@@ -226,11 +314,15 @@
intInstance
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ --;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ ++
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*cfe|dart2js.Class*/
/*cfe:nnbd.Class!*/
c.
@@ -242,7 +334,9 @@
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ --
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*cfe|dart2js.Class*/
/*cfe:nnbd.Class!*/
c.
@@ -255,83 +349,170 @@
/*cfe|dart2js.Class*/
/*cfe:nnbd.Class!*/
c. /*update: dynamic*/ /*dynamic*/ dynamicInstance
- /*invoke: dynamic*/ /*int*/ ++;
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
/*cfe|dart2js.Class*/
/*cfe:nnbd.Class!*/
c. /*update: dynamic*/ /*dynamic*/ dynamicInstance
- /*invoke: dynamic*/ /*int*/ --;
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
- /*invoke: dynamic*/ /*int*/ ++
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*cfe|dart2js.Class*/
/*cfe:nnbd.Class!*/
c. /*update: dynamic*/ /*dynamic*/ dynamicInstance;
- /*invoke: dynamic*/ /*int*/ --
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*cfe|dart2js.Class*/
/*cfe:nnbd.Class!*/
c. /*update: dynamic*/ /*dynamic*/ dynamicInstance;
}
testInstanceOnDynamic(dynamic c) {
- /*dynamic*/ c. /*update: dynamic*/ /*dynamic*/ numInstance
- /*invoke: dynamic*/ /*int*/ ++;
- /*dynamic*/ c. /*update: dynamic*/ /*dynamic*/ numInstance
- /*invoke: dynamic*/ /*int*/ --;
- /*invoke: dynamic*/ /*int*/ ++ /*dynamic*/ c
- . /*update: dynamic*/ /*dynamic*/ numInstance;
- /*invoke: dynamic*/ /*int*/ -- /*dynamic*/ c
- . /*update: dynamic*/ /*dynamic*/ numInstance;
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ numInstance
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
- /*dynamic*/ c. /*update: dynamic*/ /*dynamic*/ intInstance
- /*invoke: dynamic*/ /*int*/ ++;
- /*dynamic*/ c. /*update: dynamic*/ /*dynamic*/ intInstance
- /*invoke: dynamic*/ /*int*/ --;
- /*invoke: dynamic*/ /*int*/ ++ /*dynamic*/ c
- . /*update: dynamic*/ /*dynamic*/ intInstance;
- /*invoke: dynamic*/ /*int*/ -- /*dynamic*/ c
- . /*update: dynamic*/ /*dynamic*/ intInstance;
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ numInstance
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
- /*dynamic*/ c. /*update: dynamic*/ /*dynamic*/ dynamicInstance
- /*invoke: dynamic*/ /*int*/ ++;
- /*dynamic*/ c. /*update: dynamic*/ /*dynamic*/ dynamicInstance
- /*invoke: dynamic*/ /*int*/ --;
- /*invoke: dynamic*/ /*int*/ ++ /*dynamic*/ c
- . /*update: dynamic*/ /*dynamic*/ dynamicInstance;
- /*invoke: dynamic*/ /*int*/ -- /*dynamic*/ c
- . /*update: dynamic*/ /*dynamic*/ dynamicInstance;
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ numInstance;
+
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ numInstance;
+
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ intInstance
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
+
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ intInstance
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
+
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ intInstance;
+
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ intInstance;
+
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ dynamicInstance
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
+
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ dynamicInstance
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
+
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ dynamicInstance;
+
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
+ /*dynamic*/ c.
+ /*update: dynamic*/ /*dynamic*/ dynamicInstance;
}
main() {
/// ignore: unused_local_variable
- num numLocal = /*int*/ 0;
+ num numLocal = /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0;
/// ignore: unused_local_variable
- int intLocal = /*int*/ 0;
+ int intLocal = /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0;
/// ignore: unused_local_variable
- dynamic dynamicLocal = /*int*/ 0;
+ dynamic dynamicLocal = /*cfe|dart2js.int*/ /*cfe:nnbd.int!*/ 0;
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
/*cfe:nnbd.num!*/
- numLocal /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++;
+ numLocal
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
/*cfe:nnbd.num!*/
- numLocal /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --;
+ numLocal
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
- /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ ++
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
/*cfe:nnbd.num!*/
numLocal;
- /*cfe|dart2js.invoke: num*/ /*cfe:nnbd.invoke: num!*/ /*int*/ --
+ /*cfe|dart2js.invoke: num*/
+ /*cfe:nnbd.invoke: num!*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*cfe|dart2js.update: num*/
/*cfe:nnbd.update: num!*/
/*cfe|dart2js.num*/
@@ -345,7 +526,9 @@
intLocal
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ ++;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
/*cfe|dart2js.update: int*/
/*cfe:nnbd.update: int!*/
@@ -354,11 +537,15 @@
intLocal
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ --;
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ ++
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
/*cfe|dart2js.update: int*/
/*cfe:nnbd.update: int!*/
/*cfe|dart2js.int*/
@@ -367,18 +554,36 @@
/*cfe|dart2js.invoke: int*/
/*cfe:nnbd.invoke: int!*/
- /*int*/ --
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
/*cfe|dart2js.update: int*/
/*cfe:nnbd.update: int!*/
/*cfe|dart2js.int*/
/*cfe:nnbd.int!*/
intLocal;
- /*update: dynamic*/ /*dynamic*/ dynamicLocal /*invoke: dynamic*/ /*int*/ ++;
+ /*update: dynamic*/ /*dynamic*/ dynamicLocal
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++;
- /*update: dynamic*/ /*dynamic*/ dynamicLocal /*invoke: dynamic*/ /*int*/ --;
+ /*update: dynamic*/ /*dynamic*/ dynamicLocal
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --;
- /*invoke: dynamic*/ /*int*/ ++ /*update: dynamic*/ /*dynamic*/ dynamicLocal;
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ ++
+ /*update: dynamic*/ /*dynamic*/ dynamicLocal;
- /*invoke: dynamic*/ /*int*/ -- /*update: dynamic*/ /*dynamic*/ dynamicLocal;
+ /*invoke: dynamic*/
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ --
+ /*update: dynamic*/ /*dynamic*/ dynamicLocal;
}
diff --git a/pkg/front_end/test/static_types/data/promoted_access.dart b/pkg/front_end/test/static_types/data/promoted_access.dart
index a21bae7..26c66ce 100644
--- a/pkg/front_end/test/static_types/data/promoted_access.dart
+++ b/pkg/front_end/test/static_types/data/promoted_access.dart
@@ -24,7 +24,14 @@
}
main() {
- var c = new /*Class<dynamic>*/ Class/*<dynamic>*/();
- /*Class<dynamic>*/ c. /*invoke: dynamic*/ method(/*Class<dynamic>*/ c);
- /*invoke: dynamic*/ method/*<Class<dynamic>>*/(/*Class<dynamic>*/ c);
+ var c = new
+ /*cfe|dart2js.Class<dynamic>*/
+ /*cfe:nnbd.Class<dynamic>!*/
+ Class/*<dynamic>*/();
+ /*cfe|dart2js.Class<dynamic>*/ /*cfe:nnbd.Class<dynamic>!*/ c
+ . /*invoke: dynamic*/ method(
+ /*cfe|dart2js.Class<dynamic>*/ /*cfe:nnbd.Class<dynamic>!*/ c);
+ /*invoke: dynamic*/ method
+ /*cfe|dart2js.<Class<dynamic>>*/ /*cfe:nnbd.<Class<dynamic>!>*/ (
+ /*cfe|dart2js.Class<dynamic>*/ /*cfe:nnbd.Class<dynamic>!*/ c);
}
diff --git a/pkg/front_end/test/static_types/data/set_literals.dart b/pkg/front_end/test/static_types/data/set_literals.dart
index e7efad8..0a253e2 100644
--- a/pkg/front_end/test/static_types/data/set_literals.dart
+++ b/pkg/front_end/test/static_types/data/set_literals.dart
@@ -7,17 +7,44 @@
main() {
// ignore: unused_local_variable
- var a0 = /*Map<dynamic,dynamic>*/ {};
+ var a0 =
+ /*cfe|dart2js.Map<dynamic,dynamic>*/
+ /*cfe:nnbd.Map<dynamic,dynamic>!*/
+ {};
// ignore: unused_local_variable
var a1 =
/*cfe|dart2js.Set<int>*/
- /*cfe:nnbd.Set<int!>*/
- {/*int*/ 0};
+ /*cfe:nnbd.Set<int!>!*/
+ {
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0
+ };
// ignore: unused_local_variable
- var a2 = /*Set<num>*/ {/*int*/ 0, /*double*/ 0.5};
+ var a2 =
+ /*cfe|dart2js.Set<num>*/
+ /*cfe:nnbd.Set<num>!*/
+ {
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0,
+ /*cfe|dart2js.double*/
+ /*cfe:nnbd.double!*/
+ 0.5
+ };
// ignore: unused_local_variable
- var a3 = /*Set<Object>*/ {/*int*/ 0, /*String*/ ''};
+ var a3 =
+ /*cfe|dart2js.Set<Object>*/
+ /*cfe:nnbd.Set<Object>!*/
+ {
+ /*cfe|dart2js.int*/
+ /*cfe:nnbd.int!*/
+ 0,
+ /*cfe|dart2js.String*/
+ /*cfe:nnbd.String!*/
+ ''
+ };
}
diff --git a/pkg/front_end/test/static_types/static_type_test.dart b/pkg/front_end/test/static_types/static_type_test.dart
index 91e66a0..6ae12f2 100644
--- a/pkg/front_end/test/static_types/static_type_test.dart
+++ b/pkg/front_end/test/static_types/static_type_test.dart
@@ -11,6 +11,7 @@
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:kernel/ast.dart';
+import 'package:kernel/type_environment.dart';
main(List<String> args) async {
Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
@@ -49,6 +50,7 @@
class StaticTypeDataExtractor extends CfeDataExtractor<String> {
final TypeEnvironment _environment;
+ StaticTypeContext _staticTypeContext;
StaticTypeDataExtractor(InternalCompilerResult compilerResult,
Map<Id, ActualData<String>> actualMap)
@@ -58,6 +60,27 @@
super(compilerResult, actualMap);
@override
+ visitField(Field node) {
+ _staticTypeContext = new StaticTypeContext(node, _environment);
+ super.visitField(node);
+ _staticTypeContext = null;
+ }
+
+ @override
+ visitConstructor(Constructor node) {
+ _staticTypeContext = new StaticTypeContext(node, _environment);
+ super.visitConstructor(node);
+ _staticTypeContext = null;
+ }
+
+ @override
+ visitProcedure(Procedure node) {
+ _staticTypeContext = new StaticTypeContext(node, _environment);
+ super.visitProcedure(node);
+ _staticTypeContext = null;
+ }
+
+ @override
String computeLibraryValue(Id id, Library node) {
return 'nnbd=${node.isNonNullableByDefault}';
}
@@ -65,7 +88,7 @@
@override
String computeNodeValue(Id id, TreeNode node) {
if (node is Expression) {
- DartType type = node.getStaticType(_environment);
+ DartType type = node.getStaticType(_staticTypeContext);
return typeToText(type);
} else if (node is Arguments) {
if (node.types.isNotEmpty) {
diff --git a/pkg/front_end/test/unit_test_suites.dart b/pkg/front_end/test/unit_test_suites.dart
index a85b802..29cdd86 100644
--- a/pkg/front_end/test/unit_test_suites.dart
+++ b/pkg/front_end/test/unit_test_suites.dart
@@ -35,14 +35,17 @@
show createContext;
import 'spelling_test_src_suite.dart' as spelling_src show createContext;
+const suiteNamePrefix = "pkg/front_end/test";
+
class Options {
final String configurationName;
final bool verbose;
final bool printFailureLog;
final Uri outputDirectory;
+ final String testFilter;
Options(this.configurationName, this.verbose, this.printFailureLog,
- this.outputDirectory);
+ this.outputDirectory, this.testFilter);
static Options parse(List<String> args) {
var parser = new ArgParser()
@@ -58,13 +61,23 @@
var parsedArguments = parser.parse(args);
String outputPath = parsedArguments["output-directory"] ?? ".";
Uri outputDirectory = Uri.base.resolveUri(Uri.directory(outputPath));
- return Options(parsedArguments["named-configuration"],
- parsedArguments["verbose"], parsedArguments["print"], outputDirectory);
+ String filter;
+ if (parsedArguments.rest.length == 1) {
+ filter = parsedArguments.rest.single;
+ if (filter.startsWith("$suiteNamePrefix/")) {
+ filter = filter.substring(suiteNamePrefix.length + 1);
+ }
+ }
+ return Options(
+ parsedArguments["named-configuration"],
+ parsedArguments["verbose"],
+ parsedArguments["print"],
+ outputDirectory,
+ filter);
}
}
class ResultLogger implements Logger {
- final String suiteName;
final String prefix;
final bool verbose;
final bool printFailureLog;
@@ -74,8 +87,8 @@
final String configurationName;
final Set<String> seenTests = {};
- ResultLogger(this.suiteName, this.prefix, this.resultsPort, this.logsPort,
- this.verbose, this.printFailureLog, this.configurationName);
+ ResultLogger(this.prefix, this.resultsPort, this.logsPort, this.verbose,
+ this.printFailureLog, this.configurationName);
String getTestName(TestDescription description) {
return "$prefix/${description.shortName}";
@@ -127,6 +140,8 @@
if (result.trace != null) {
failureLog = "$failureLog\n\n${result.trace}";
}
+ failureLog = "$failureLog\n\nRe-run this test: dart "
+ "pkg/front_end/test/unit_test_suites.dart -p $testName";
String outcome = "${result.outcome}";
logsPort.send(jsonEncode({
"name": testName,
@@ -183,12 +198,14 @@
final String path;
final int shardCount;
final int shard;
+ final String prefix;
const Suite(this.name, this.createContext, this.testingRootPath,
- {this.path, this.shardCount: 1, this.shard: 0});
+ {this.path, this.shardCount: 1, this.shard: 0, String prefix})
+ : prefix = prefix ?? name;
}
-final List<Suite> suites = [
+const List<Suite> suites = [
const Suite(
"fasta/expression", expression.createContext, "../../testing.json"),
const Suite("fasta/outline", outline.createContext, "../../testing.json"),
@@ -200,13 +217,25 @@
const Suite("fasta/text_serialization", text_serialization.createContext,
"../../testing.json"),
const Suite("fasta/strong1", strong.createContext, "../../testing.json",
- path: "fasta/strong_tester.dart", shardCount: 4, shard: 0),
+ path: "fasta/strong_tester.dart",
+ shardCount: 4,
+ shard: 0,
+ prefix: "fasta/strong"),
const Suite("fasta/strong2", strong.createContext, "../../testing.json",
- path: "fasta/strong_tester.dart", shardCount: 4, shard: 1),
+ path: "fasta/strong_tester.dart",
+ shardCount: 4,
+ shard: 1,
+ prefix: "fasta/strong"),
const Suite("fasta/strong3", strong.createContext, "../../testing.json",
- path: "fasta/strong_tester.dart", shardCount: 4, shard: 2),
+ path: "fasta/strong_tester.dart",
+ shardCount: 4,
+ shard: 2,
+ prefix: "fasta/strong"),
const Suite("fasta/strong4", strong.createContext, "../../testing.json",
- path: "fasta/strong_tester.dart", shardCount: 4, shard: 3),
+ path: "fasta/strong_tester.dart",
+ shardCount: 4,
+ shard: 3,
+ prefix: "fasta/strong"),
const Suite("incremental_bulk_compiler_smoke",
incremental_bulk_compiler.createContext, "../testing.json"),
const Suite("incremental_load_from_dill", incremental_load.createContext,
@@ -229,24 +258,32 @@
final bool verbose;
final bool printFailureLog;
final String configurationName;
- const SuiteConfiguration(this.name, this.resultsPort, this.logsPort,
- this.verbose, this.printFailureLog, this.configurationName);
+ final String testFilter;
+ const SuiteConfiguration(
+ this.name,
+ this.resultsPort,
+ this.logsPort,
+ this.verbose,
+ this.printFailureLog,
+ this.configurationName,
+ this.testFilter);
}
void runSuite(SuiteConfiguration configuration) {
Suite suite = suites.where((s) => s.name == configuration.name).single;
- String name = suite.name;
- String fullSuiteName = "pkg/front_end/test/$name";
+ String name = suite.prefix;
+ String fullSuiteName = "$suiteNamePrefix/$name";
Uri suiteUri = Platform.script.resolve(suite.path ?? "${name}_suite.dart");
ResultLogger logger = ResultLogger(
- name,
fullSuiteName,
configuration.resultsPort,
configuration.logsPort,
configuration.verbose,
configuration.printFailureLog,
configuration.configurationName);
- runMe(<String>[], suite.createContext,
+ runMe(
+ <String>[if (configuration.testFilter != null) configuration.testFilter],
+ suite.createContext,
me: suiteUri,
configurationPath: suite.testingRootPath,
logger: logger,
@@ -269,21 +306,32 @@
List<Future<bool>> futures = [];
// Run test suites and record the results and possible failure logs.
for (Suite suite in suites) {
+ String name = suite.name;
+ String filter = options.testFilter;
+ if (filter != null) {
+ // Skip suites that are not hit by the test filter, is there is one.
+ if (!filter.startsWith(suite.prefix)) {
+ continue;
+ }
+ // Remove the 'fasta/' from filters, if there, because it is not used
+ // in the name defined in testing.json.
+ if (filter.startsWith("fasta/")) {
+ filter = filter.substring("fasta/".length);
+ }
+ }
// Start the test suite in a new isolate.
ReceivePort exitPort = new ReceivePort();
- String name = suite.name;
SuiteConfiguration configuration = SuiteConfiguration(
name,
resultsPort.sendPort,
logsPort.sendPort,
options.verbose,
options.printFailureLog,
- options.configurationName);
+ options.configurationName,
+ filter);
Future future = Future<bool>(() async {
Stopwatch stopwatch = Stopwatch()..start();
print("Running suite $name");
- // TODO(karlklose): Implement --filter to select tests to run
- // to implement deflaking (dartbug.com/38607).
Isolate isolate = await Isolate.spawn<SuiteConfiguration>(
runSuite, configuration,
onExit: exitPort.sendPort);
@@ -320,8 +368,8 @@
if (timeout) {
exitCode = 1;
} else {
- // The testing framework (pkg/testing) sets the exitCode to 1 if any test
- // failed, so we reset it here to indicate that the test runner was
+ // The testing framework (package:testing) sets the exitCode to `1` if any
+ // test failed, so we reset it here to indicate that the test runner was
// successful.
exitCode = 0;
}
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart b/pkg/front_end/testcases/extensions/call_methods.dart
new file mode 100644
index 0000000..1850a3b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/call_methods.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2019, 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.
+
+class A {
+ String get call => "My name is A";
+}
+
+class B {
+ String Function() get call => () => "My name is B";
+}
+
+extension on int {
+ String get call => "My name is int";
+}
+
+extension on num {
+ String get call => "My name is num";
+}
+
+extension on String {
+ String Function() get call => () => "My name is String";
+}
+
+main() {
+ // TODO(johnniwinther): Should the be an error?
+ ""();
+}
+
+errors() {
+ 1(10);
+ 1("10");
+ 1.0(10);
+ 1.0("10");
+ A a = new A();
+ a(2);
+ a(2, "3");
+ B b = new B();
+ b();
+}
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart.outline.expect b/pkg/front_end/testcases/extensions/call_methods.dart.outline.expect
new file mode 100644
index 0000000..b57cf7b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/call_methods.dart.outline.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ ;
+ get call() → core::String*
+ ;
+}
+class B extends core::Object {
+ synthetic constructor •() → self::B*
+ ;
+ get call() → () →* core::String*
+ ;
+}
+extension _extension#0 on core::int* {
+ get call = self::_extension#0|get#call;
+}
+extension _extension#1 on core::num* {
+ get call = self::_extension#1|get#call;
+}
+extension _extension#2 on core::String* {
+ get call = self::_extension#2|get#call;
+}
+static method _extension#0|get#call(final core::int* #this) → core::String*
+ ;
+static method _extension#1|get#call(final core::num* #this) → core::String*
+ ;
+static method _extension#2|get#call(final core::String* #this) → () →* core::String*
+ ;
+static method main() → dynamic
+ ;
+static method errors() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart.strong.expect b/pkg/front_end/testcases/extensions/call_methods.dart.strong.expect
new file mode 100644
index 0000000..6227c6f
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/call_methods.dart.strong.expect
@@ -0,0 +1,101 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:27:5: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// ""();
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:31:4: Error: 'call' isn't a function or method and can't be invoked.
+// 1(10);
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:32:4: Error: 'call' isn't a function or method and can't be invoked.
+// 1("10");
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:33:6: Error: 'call' isn't a function or method and can't be invoked.
+// 1.0(10);
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:34:6: Error: 'call' isn't a function or method and can't be invoked.
+// 1.0("10");
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:36:4: Error: 'call' isn't a function or method and can't be invoked.
+// a(2);
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:37:4: Error: 'call' isn't a function or method and can't be invoked.
+// a(2, "3");
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:39:4: Error: Cannot invoke an instance of 'B' because it declares 'call' to be something other than a method.
+// - 'B' is from 'pkg/front_end/testcases/extensions/call_methods.dart'.
+// Try changing 'call' to a method or explicitly invoke 'call'.
+// b();
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+ get call() → core::String*
+ return "My name is A";
+}
+class B extends core::Object {
+ synthetic constructor •() → self::B*
+ : super core::Object::•()
+ ;
+ get call() → () →* core::String*
+ return () → core::String* => "My name is B";
+}
+extension _extension#0 on core::int* {
+ get call = self::_extension#0|get#call;
+}
+extension _extension#1 on core::num* {
+ get call = self::_extension#1|get#call;
+}
+extension _extension#2 on core::String* {
+ get call = self::_extension#2|get#call;
+}
+static method _extension#0|get#call(final core::int* #this) → core::String*
+ return "My name is int";
+static method _extension#1|get#call(final core::num* #this) → core::String*
+ return "My name is num";
+static method _extension#2|get#call(final core::String* #this) → () →* core::String*
+ return () → core::String* => "My name is String";
+static method main() → dynamic {
+ self::_extension#2|get#call("");
+}
+static method errors() → dynamic {
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:31:4: Error: 'call' isn't a function or method and can't be invoked.
+ 1(10);
+ ^";
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:32:4: Error: 'call' isn't a function or method and can't be invoked.
+ 1(\"10\");
+ ^";
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:33:6: Error: 'call' isn't a function or method and can't be invoked.
+ 1.0(10);
+ ^";
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:34:6: Error: 'call' isn't a function or method and can't be invoked.
+ 1.0(\"10\");
+ ^";
+ self::A* a = new self::A::•();
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:36:4: Error: 'call' isn't a function or method and can't be invoked.
+ a(2);
+ ^";
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:37:4: Error: 'call' isn't a function or method and can't be invoked.
+ a(2, \"3\");
+ ^";
+ self::B* b = new self::B::•();
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:39:4: Error: Cannot invoke an instance of 'B' because it declares 'call' to be something other than a method.
+ - 'B' is from 'pkg/front_end/testcases/extensions/call_methods.dart'.
+Try changing 'call' to a method or explicitly invoke 'call'.
+ b();
+ ^";
+}
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/call_methods.dart.strong.transformed.expect
new file mode 100644
index 0000000..6227c6f
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/call_methods.dart.strong.transformed.expect
@@ -0,0 +1,101 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:27:5: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
+// ""();
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:31:4: Error: 'call' isn't a function or method and can't be invoked.
+// 1(10);
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:32:4: Error: 'call' isn't a function or method and can't be invoked.
+// 1("10");
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:33:6: Error: 'call' isn't a function or method and can't be invoked.
+// 1.0(10);
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:34:6: Error: 'call' isn't a function or method and can't be invoked.
+// 1.0("10");
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:36:4: Error: 'call' isn't a function or method and can't be invoked.
+// a(2);
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:37:4: Error: 'call' isn't a function or method and can't be invoked.
+// a(2, "3");
+// ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:39:4: Error: Cannot invoke an instance of 'B' because it declares 'call' to be something other than a method.
+// - 'B' is from 'pkg/front_end/testcases/extensions/call_methods.dart'.
+// Try changing 'call' to a method or explicitly invoke 'call'.
+// b();
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+ get call() → core::String*
+ return "My name is A";
+}
+class B extends core::Object {
+ synthetic constructor •() → self::B*
+ : super core::Object::•()
+ ;
+ get call() → () →* core::String*
+ return () → core::String* => "My name is B";
+}
+extension _extension#0 on core::int* {
+ get call = self::_extension#0|get#call;
+}
+extension _extension#1 on core::num* {
+ get call = self::_extension#1|get#call;
+}
+extension _extension#2 on core::String* {
+ get call = self::_extension#2|get#call;
+}
+static method _extension#0|get#call(final core::int* #this) → core::String*
+ return "My name is int";
+static method _extension#1|get#call(final core::num* #this) → core::String*
+ return "My name is num";
+static method _extension#2|get#call(final core::String* #this) → () →* core::String*
+ return () → core::String* => "My name is String";
+static method main() → dynamic {
+ self::_extension#2|get#call("");
+}
+static method errors() → dynamic {
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:31:4: Error: 'call' isn't a function or method and can't be invoked.
+ 1(10);
+ ^";
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:32:4: Error: 'call' isn't a function or method and can't be invoked.
+ 1(\"10\");
+ ^";
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:33:6: Error: 'call' isn't a function or method and can't be invoked.
+ 1.0(10);
+ ^";
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:34:6: Error: 'call' isn't a function or method and can't be invoked.
+ 1.0(\"10\");
+ ^";
+ self::A* a = new self::A::•();
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:36:4: Error: 'call' isn't a function or method and can't be invoked.
+ a(2);
+ ^";
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:37:4: Error: 'call' isn't a function or method and can't be invoked.
+ a(2, \"3\");
+ ^";
+ self::B* b = new self::B::•();
+ invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:39:4: Error: Cannot invoke an instance of 'B' because it declares 'call' to be something other than a method.
+ - 'B' is from 'pkg/front_end/testcases/extensions/call_methods.dart'.
+Try changing 'call' to a method or explicitly invoke 'call'.
+ b();
+ ^";
+}
diff --git a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect
index ddb1b0a..47f973b 100644
--- a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
diff --git a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.expect b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.expect
index 1341a83..8fe4a36 100644
--- a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.expect
@@ -1,6 +1,7 @@
library;
import self as self;
import "deferred_explicit_access_lib.dart" as def;
+import "dart:core" as core;
import "org-dartlang-testcase:///deferred_explicit_access_lib.dart" deferred as prefix;
@@ -15,7 +16,7 @@
self::expect(87, let final dynamic #t7 = CheckLibraryIsLoaded(prefix) in def::topLevelMethod());
}
static method expect(dynamic expected, dynamic actual) → dynamic {
- if(!expected.{dart.core::Object::==}(actual))
+ if(!expected.{core::Object::==}(actual))
throw "Expected ${expected}, actual ${actual}";
}
diff --git a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect
index 0508e3e..bcb6ce3 100644
--- a/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/deferred_import_hidden.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
diff --git a/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.expect b/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.expect
index 255aa8c..7030c4a 100644
--- a/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.expect
@@ -1,6 +1,7 @@
library;
import self as self;
import "import_via_prefix_lib.dart" as imp;
+import "dart:core" as core;
import "org-dartlang-testcase:///import_via_prefix_lib.dart" as prefix;
@@ -8,7 +9,7 @@
self::expect(3, imp::Extension|method("foo"));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
- if(!expected.{dart.core::Object::==}(actual))
+ if(!expected.{core::Object::==}(actual))
throw "Expected ${expected}, actual ${actual}";
}
diff --git a/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.transformed.expect
index 255aa8c..7030c4a 100644
--- a/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/import_via_prefix.dart.strong.transformed.expect
@@ -1,6 +1,7 @@
library;
import self as self;
import "import_via_prefix_lib.dart" as imp;
+import "dart:core" as core;
import "org-dartlang-testcase:///import_via_prefix_lib.dart" as prefix;
@@ -8,7 +9,7 @@
self::expect(3, imp::Extension|method("foo"));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
- if(!expected.{dart.core::Object::==}(actual))
+ if(!expected.{core::Object::==}(actual))
throw "Expected ${expected}, actual ${actual}";
}
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.expect b/pkg/front_end/testcases/extensions/index.dart.strong.expect
index cc8481e..52fbaa5 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.expect
@@ -72,11 +72,11 @@
self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
self::expect(1, let final self::MapLike<core::int*, core::int*>* #t61 = map2 in let final core::int* #t62 = 0 in let final core::int* #t63 = 1 in let final void #t64 = self::Extension|[]=<core::int*, core::int*>(#t61, #t62, #t63) in #t63);
- self::expect(3, let final core::Object* #t65 = map2 in let final core::int* #t66 = 0 in let final core::int* #t67 = self::Extension|[]<core::int*, core::int*>(#t65, #t66).{core::num::+}(2) in let final void #t68 = self::Extension|[]=<core::int*, core::int*>(#t65, #t66, #t67) in #t67);
- self::expect(5, let final core::Object* #t69 = map2 in let final core::int* #t70 = 0 in let final core::int* #t71 = self::Extension|[]<core::int*, core::int*>(#t69, #t70).{core::num::+}(2) in let final void #t72 = self::Extension|[]=<core::int*, core::int*>(#t69, #t70, #t71) in #t71);
- self::expect(5, let final core::Object* #t73 = map2 in let final core::int* #t74 = 0 in let final core::int* #t75 = self::Extension|[]<core::int*, core::int*>(#t73, #t74) in let final void #t76 = self::Extension|[]=<core::int*, core::int*>(#t73, #t74, #t75.{core::num::+}(1)) in #t75);
+ self::expect(3, let final self::MapLike<core::int*, core::int*>* #t65 = map2 in let final core::int* #t66 = 0 in let final core::int* #t67 = self::Extension|[]<core::int*, core::int*>(#t65, #t66).{core::num::+}(2) in let final void #t68 = self::Extension|[]=<core::int*, core::int*>(#t65, #t66, #t67) in #t67);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t69 = map2 in let final core::int* #t70 = 0 in let final core::int* #t71 = self::Extension|[]<core::int*, core::int*>(#t69, #t70).{core::num::+}(2) in let final void #t72 = self::Extension|[]=<core::int*, core::int*>(#t69, #t70, #t71) in #t71);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t73 = map2 in let final core::int* #t74 = 0 in let final core::int* #t75 = self::Extension|[]<core::int*, core::int*>(#t73, #t74) in let final void #t76 = self::Extension|[]=<core::int*, core::int*>(#t73, #t74, #t75.{core::num::+}(1)) in #t75);
self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
- self::expect(5, let final core::Object* #t77 = map2 in let final core::int* #t78 = 0 in let final core::int* #t79 = self::Extension|[]<core::int*, core::int*>(#t77, #t78).{core::num::-}(1) in let final void #t80 = self::Extension|[]=<core::int*, core::int*>(#t77, #t78, #t79) in #t79);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t77 = map2 in let final core::int* #t78 = 0 in let final core::int* #t79 = self::Extension|[]<core::int*, core::int*>(#t77, #t78).{core::num::-}(1) in let final void #t80 = self::Extension|[]=<core::int*, core::int*>(#t77, #t78, #t79) in #t79);
self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
}
static method explicitInferredTypeArguments() → dynamic {
@@ -99,11 +99,11 @@
self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
self::expect(1, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = 1 in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
- self::expect(3, let final core::Object* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
- self::expect(5, let final core::Object* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108).{core::num::+}(2) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109) in #t109);
- self::expect(5, let final core::Object* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113.{core::num::+}(1)) in #t113);
+ self::expect(3, let final self::MapLike<core::int*, core::int*>* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108).{core::num::+}(2) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109) in #t109);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113.{core::num::+}(1)) in #t113);
self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
- self::expect(5, let final core::Object* #t115 = map2 in let final core::int* #t116 = 0 in let final core::int* #t117 = self::Extension|[]<core::int*, core::int*>(#t115, #t116).{core::num::-}(1) in let final void #t118 = self::Extension|[]=<core::int*, core::int*>(#t115, #t116, #t117) in #t117);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t115 = map2 in let final core::int* #t116 = 0 in let final core::int* #t117 = self::Extension|[]<core::int*, core::int*>(#t115, #t116).{core::num::-}(1) in let final void #t118 = self::Extension|[]=<core::int*, core::int*>(#t115, #t116, #t117) in #t117);
self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
index cc8481e..52fbaa5 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
@@ -72,11 +72,11 @@
self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
self::expect(1, let final self::MapLike<core::int*, core::int*>* #t61 = map2 in let final core::int* #t62 = 0 in let final core::int* #t63 = 1 in let final void #t64 = self::Extension|[]=<core::int*, core::int*>(#t61, #t62, #t63) in #t63);
- self::expect(3, let final core::Object* #t65 = map2 in let final core::int* #t66 = 0 in let final core::int* #t67 = self::Extension|[]<core::int*, core::int*>(#t65, #t66).{core::num::+}(2) in let final void #t68 = self::Extension|[]=<core::int*, core::int*>(#t65, #t66, #t67) in #t67);
- self::expect(5, let final core::Object* #t69 = map2 in let final core::int* #t70 = 0 in let final core::int* #t71 = self::Extension|[]<core::int*, core::int*>(#t69, #t70).{core::num::+}(2) in let final void #t72 = self::Extension|[]=<core::int*, core::int*>(#t69, #t70, #t71) in #t71);
- self::expect(5, let final core::Object* #t73 = map2 in let final core::int* #t74 = 0 in let final core::int* #t75 = self::Extension|[]<core::int*, core::int*>(#t73, #t74) in let final void #t76 = self::Extension|[]=<core::int*, core::int*>(#t73, #t74, #t75.{core::num::+}(1)) in #t75);
+ self::expect(3, let final self::MapLike<core::int*, core::int*>* #t65 = map2 in let final core::int* #t66 = 0 in let final core::int* #t67 = self::Extension|[]<core::int*, core::int*>(#t65, #t66).{core::num::+}(2) in let final void #t68 = self::Extension|[]=<core::int*, core::int*>(#t65, #t66, #t67) in #t67);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t69 = map2 in let final core::int* #t70 = 0 in let final core::int* #t71 = self::Extension|[]<core::int*, core::int*>(#t69, #t70).{core::num::+}(2) in let final void #t72 = self::Extension|[]=<core::int*, core::int*>(#t69, #t70, #t71) in #t71);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t73 = map2 in let final core::int* #t74 = 0 in let final core::int* #t75 = self::Extension|[]<core::int*, core::int*>(#t73, #t74) in let final void #t76 = self::Extension|[]=<core::int*, core::int*>(#t73, #t74, #t75.{core::num::+}(1)) in #t75);
self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
- self::expect(5, let final core::Object* #t77 = map2 in let final core::int* #t78 = 0 in let final core::int* #t79 = self::Extension|[]<core::int*, core::int*>(#t77, #t78).{core::num::-}(1) in let final void #t80 = self::Extension|[]=<core::int*, core::int*>(#t77, #t78, #t79) in #t79);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t77 = map2 in let final core::int* #t78 = 0 in let final core::int* #t79 = self::Extension|[]<core::int*, core::int*>(#t77, #t78).{core::num::-}(1) in let final void #t80 = self::Extension|[]=<core::int*, core::int*>(#t77, #t78, #t79) in #t79);
self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
}
static method explicitInferredTypeArguments() → dynamic {
@@ -99,11 +99,11 @@
self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
self::expect(1, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = 1 in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
- self::expect(3, let final core::Object* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
- self::expect(5, let final core::Object* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108).{core::num::+}(2) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109) in #t109);
- self::expect(5, let final core::Object* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113.{core::num::+}(1)) in #t113);
+ self::expect(3, let final self::MapLike<core::int*, core::int*>* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108).{core::num::+}(2) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109) in #t109);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113.{core::num::+}(1)) in #t113);
self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
- self::expect(5, let final core::Object* #t115 = map2 in let final core::int* #t116 = 0 in let final core::int* #t117 = self::Extension|[]<core::int*, core::int*>(#t115, #t116).{core::num::-}(1) in let final void #t118 = self::Extension|[]=<core::int*, core::int*>(#t115, #t116, #t117) in #t117);
+ self::expect(5, let final self::MapLike<core::int*, core::int*>* #t115 = map2 in let final core::int* #t116 = 0 in let final core::int* #t117 = self::Extension|[]<core::int*, core::int*>(#t115, #t116).{core::num::-}(1) in let final void #t118 = self::Extension|[]=<core::int*, core::int*>(#t115, #t116, #t117) in #t117);
self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect b/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect
index ca61355..a4a39f8 100644
--- a/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/async_function.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
import "dart:async";
@@ -12,7 +13,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -39,7 +40,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -61,7 +62,7 @@
return :async_completer.{asy::Completer::future};
}
static method syncStarString() → core::Iterable<core::String*>* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<core::String*>* :iterator) → core::bool* yielding {
{
@@ -83,7 +84,7 @@
return new core::_SyncIterable::•<core::String*>(:sync_op);
}
static method syncStarString2() → core::Iterable<core::String*>* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<core::String*>* :iterator) → core::bool* yielding {
{
@@ -102,7 +103,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -120,7 +121,7 @@
else
[yield] null;
[yield] let dynamic #t1 = asy::_awaitHelper(self::asyncString(), :async_op_then, :async_op_error, :async_op) in null;
- if(:controller.{asy::_AsyncStarStreamController::add}(:result))
+ if(:controller.{asy::_AsyncStarStreamController::add}(_in::unsafeCast<core::String*>(:result)))
return null;
else
[yield] null;
@@ -146,7 +147,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -181,7 +182,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -189,7 +190,7 @@
#L5:
{
[yield] let dynamic #t2 = asy::_awaitHelper(self::asyncString(), :async_op_then, :async_op_error, :async_op) in null;
- core::String* str = :result;
+ core::String* str = _in::unsafeCast<core::String*>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
diff --git a/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect b/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
index 256ef3f..27b7653 100644
--- a/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/async_nested.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -23,12 +24,12 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
- dynamic :async_temporary_1;
- dynamic :async_temporary_2;
+ self::Node* :async_temporary_0;
+ self::Node* :async_temporary_1;
+ self::Node* :async_temporary_2;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
@@ -36,16 +37,16 @@
core::String* expected = "1 2 3 4 5 6 7 8 9 10";
:async_temporary_2 = new self::Node::•("2", <self::Node*>[]);
[yield] let dynamic #t4 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("7", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
- [yield] let dynamic #t5 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("6", <self::Node*>[:result])), :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_1 = :result;
+ [yield] let dynamic #t5 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("6", <self::Node*>[_in::unsafeCast<self::Node*>(:result)])), :async_op_then, :async_op_error, :async_op) in null;
+ :async_temporary_1 = _in::unsafeCast<self::Node*>(:result);
[yield] let dynamic #t6 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("8", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_0 = :result;
+ :async_temporary_0 = _in::unsafeCast<self::Node*>(:result);
[yield] let dynamic #t7 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("9", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
- [yield] let dynamic #t8 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("4", <self::Node*>[new self::Node::•("5", <self::Node*>[:async_temporary_1, :async_temporary_0, :result])])), :async_op_then, :async_op_error, :async_op) in null;
- [yield] let dynamic #t9 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("3", <self::Node*>[:result])), :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_0 = :result;
+ [yield] let dynamic #t8 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("4", <self::Node*>[new self::Node::•("5", <self::Node*>[:async_temporary_1, :async_temporary_0, _in::unsafeCast<self::Node*>(:result)])])), :async_op_then, :async_op_error, :async_op) in null;
+ [yield] let dynamic #t9 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("3", <self::Node*>[_in::unsafeCast<self::Node*>(:result)])), :async_op_then, :async_op_error, :async_op) in null;
+ :async_temporary_0 = _in::unsafeCast<self::Node*>(:result);
[yield] let dynamic #t10 = asy::_awaitHelper(asy::Future::value<self::Node*>(new self::Node::•("10", <self::Node*>[])), :async_op_then, :async_op_error, :async_op) in null;
- self::Node* node = new self::Node::•("1", <self::Node*>[:async_temporary_2, :async_temporary_0, :result]);
+ self::Node* node = new self::Node::•("1", <self::Node*>[:async_temporary_2, :async_temporary_0, _in::unsafeCast<self::Node*>(:result)]);
core::String* actual = node.{self::Node::toSimpleString}() as{TypeError} core::String*;
core::print(actual);
if(!actual.{core::String::==}(expected)) {
diff --git a/pkg/front_end/testcases/general/await.dart.strong.transformed.expect b/pkg/front_end/testcases/general/await.dart.strong.transformed.expect
index 1e0da3e..a4fa440 100644
--- a/pkg/front_end/testcases/general/await.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/await.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
static method main() → dynamic /* originally async */ {
final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
@@ -9,7 +10,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -17,7 +18,7 @@
#L1:
{
[yield] let dynamic #t1 = asy::_awaitHelper("Hello, World!", :async_op_then, :async_op_error, :async_op) in null;
- core::print(:result);
+ core::print(_in::unsafeCast<core::String*>(:result));
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
diff --git a/pkg/front_end/testcases/general/await_complex.dart b/pkg/front_end/testcases/general/await_complex.dart
new file mode 100644
index 0000000..4cae35f
--- /dev/null
+++ b/pkg/front_end/testcases/general/await_complex.dart
@@ -0,0 +1,256 @@
+// Copyright (c) 2014, 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.
+
+// This test was adapted from language_2/await_test
+
+import 'dart:async';
+
+int globalVariable = 1;
+int topLevelFoo(int param) => 1;
+int get topLevelGetter => globalVariable;
+void set topLevelSetter(val) {
+ globalVariable = val;
+}
+
+class C {
+ static int staticField = 1;
+ static int get staticGetter => staticField;
+ static void set staticSetter(val) {
+ staticField = val;
+ }
+
+ static int staticFoo(int param) => param;
+
+ int field = 1;
+ int get getter => field;
+ void set setter(val) {
+ field = val;
+ }
+
+ int foo(int param) => param;
+}
+
+dummy() => 1;
+
+staticMembers() async {
+ var a = C.staticField + await dummy();
+ expect(2, a);
+ var f = (C.staticField = 1) + await dummy();
+ expect(2, f);
+ var b = C.staticGetter + await dummy();
+ expect(2, b);
+ var c = (C.staticSetter = 1) + await dummy();
+ expect(2, c);
+ var d = C.staticFoo(2) + await dummy();
+ expect(3, d);
+ var e = C.staticField +
+ C.staticGetter +
+ (C.staticSetter = 1) +
+ C.staticFoo(1) +
+ await dummy();
+ expect(5, e);
+}
+
+topLevelMembers() async {
+ var a = globalVariable + await dummy();
+ expect(2, a);
+ var b = topLevelGetter + await dummy();
+ expect(2, b);
+ var c = (topLevelSetter = 1) + await dummy();
+ expect(2, c);
+ var d = topLevelFoo(1) + await dummy();
+ expect(2, d);
+ var e = globalVariable +
+ topLevelGetter +
+ (topLevelSetter = 1) +
+ topLevelFoo(1) +
+ await dummy();
+ expect(5, e);
+}
+
+instanceMembers() async {
+ var inst = new C();
+ var a = inst.field + await dummy();
+ expect(2, a);
+ var b = inst.getter + await dummy();
+ expect(2, b);
+ var c = (inst.setter = 1) + await dummy();
+ expect(2, c);
+ var d = inst.foo(1) + await dummy();
+ expect(2, d);
+ var e = inst.field +
+ inst.getter +
+ (inst.setter = 1) +
+ inst.foo(1) +
+ await dummy();
+ expect(5, e);
+}
+
+others() async {
+ var a = "${globalVariable} ${await dummy()} " + await "someString";
+ expect("1 1 someString", a);
+ var c = new C();
+ var d = c.field + await dummy();
+ var cnt = 2;
+ var b = [1, 2, 3];
+ b[cnt] = await dummy();
+ expect(1, b[cnt]);
+ var e = b[0] + await dummy();
+ expect(2, e);
+}
+
+conditionals() async {
+ var a = false;
+ var b = true;
+ var c = (a || b) || await dummy();
+ expect(true, c);
+ var d = (a || b) ? a : await dummy();
+ expect(false, d);
+ var e = (a is int) ? await dummy() : 2;
+ expect(2, e);
+ try {
+ var f = (a is int) ? await dummy() : 2;
+ } catch (e) {}
+}
+
+asserts() async {
+ for (final FutureOr<T> Function<T>(T) func in <Function>[id, future]) {
+ assert(await func(true));
+ assert(id(true), await func("message"));
+ assert(await func(true), await (func("message")));
+ try {
+ assert(await func(false), await (func("message")));
+ if (assertStatementsEnabled) throw "Didn't throw";
+ } on AssertionError catch (e) {
+ expect("message", e.message);
+ }
+ }
+}
+
+controlFlow() async {
+ for (final FutureOr<T> Function<T>(T) func in <Function>[id, future]) {
+ // For.
+ var c = 0;
+ for (var i = await (func(0)); await func(i < 5); await func(i++)) {
+ c++;
+ }
+ expect(5, c);
+ // While.
+ c = 0;
+ while (await func(c < 5)) c++;
+ expect(5, c);
+ // Do-while.
+ c = 0;
+ do {
+ c++;
+ } while (await func(c < 5));
+ expect(5, c);
+ // If.
+ if (await func(c == 5)) {
+ expect(5, c);
+ } else {
+ throw "unreachable";
+ }
+ // Throw.
+ try {
+ throw await func("string");
+ } on String {
+ // OK.
+ }
+
+ try {
+ await (throw "string");
+ } on String {
+ // OK.
+ }
+ // Try/catch/finally
+ try {
+ try {
+ throw "string";
+ } catch (e) {
+ expect("string", e);
+ expect(0, await func(0));
+ rethrow;
+ } finally {
+ expect(0, await func(0));
+ }
+ } catch (e) {
+ expect(0, await func(0));
+ expect("string", e);
+ } finally {
+ expect(0, await func(0));
+ }
+ // Switch
+ switch (await func(2)) {
+ case 2:
+ break;
+ default:
+ throw "unreachable";
+ }
+ // Return.
+ expect(
+ 42,
+ await () async {
+ return await func(42);
+ }());
+ expect(
+ 42,
+ await () async {
+ return func(42);
+ }());
+ // Yield.
+ Stream<int> testStream1() async* {
+ yield await func(42);
+ }
+
+ expectList([42], await testStream1().toList());
+ // Yield*
+ Stream<int> testStream2() async* {
+ yield* await func(intStream());
+ }
+
+ expectList([42], await testStream2().toList());
+ }
+}
+
+FutureOr<T> future<T>(T value) async => value;
+FutureOr<T> id<T>(T value) => value;
+
+Stream<int> intStream() async* {
+ yield 42;
+}
+
+final bool assertStatementsEnabled = () {
+ try {
+ assert(false);
+ return false;
+ } catch (_) {
+ return true;
+ }
+}();
+
+main() async {
+ for (int i = 0; i < 11; i++) {
+ await staticMembers();
+ await topLevelMembers();
+ await instanceMembers();
+ await conditionals();
+ await others();
+ await asserts();
+ await controlFlow();
+ }
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+expectList(List expected, List actual) {
+ if (expected.length != actual.length) {
+ throw 'Expected $expected, actual $actual';
+ }
+ for (int i = 0; i < expected.length; i++) {
+ expect(expected[i], actual[i]);
+ }
+}
diff --git a/pkg/front_end/testcases/general/await_complex.dart.outline.expect b/pkg/front_end/testcases/general/await_complex.dart.outline.expect
new file mode 100644
index 0000000..7d5cecc
--- /dev/null
+++ b/pkg/front_end/testcases/general/await_complex.dart.outline.expect
@@ -0,0 +1,61 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+class C extends core::Object {
+ static field core::int* staticField;
+ field core::int* field;
+ synthetic constructor •() → self::C*
+ ;
+ static get staticGetter() → core::int*
+ ;
+ static set staticSetter(dynamic val) → void
+ ;
+ static method staticFoo(core::int* param) → core::int*
+ ;
+ get getter() → core::int*
+ ;
+ set setter(dynamic val) → void
+ ;
+ method foo(core::int* param) → core::int*
+ ;
+}
+static field core::int* globalVariable;
+static final field core::bool* assertStatementsEnabled;
+static method topLevelFoo(core::int* param) → core::int*
+ ;
+static get topLevelGetter() → core::int*
+ ;
+static set topLevelSetter(dynamic val) → void
+ ;
+static method dummy() → dynamic
+ ;
+static method staticMembers() → dynamic
+ ;
+static method topLevelMembers() → dynamic
+ ;
+static method instanceMembers() → dynamic
+ ;
+static method others() → dynamic
+ ;
+static method conditionals() → dynamic
+ ;
+static method asserts() → dynamic
+ ;
+static method controlFlow() → dynamic
+ ;
+static method future<T extends core::Object* = dynamic>(self::future::T* value) → asy::FutureOr<self::future::T*>*
+ ;
+static method id<T extends core::Object* = dynamic>(self::id::T* value) → asy::FutureOr<self::id::T*>*
+ ;
+static method intStream() → asy::Stream<core::int*>*
+ ;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method expectList(core::List<dynamic>* expected, core::List<dynamic>* actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/await_complex.dart.strong.expect b/pkg/front_end/testcases/general/await_complex.dart.strong.expect
new file mode 100644
index 0000000..9cf401a
--- /dev/null
+++ b/pkg/front_end/testcases/general/await_complex.dart.strong.expect
@@ -0,0 +1,250 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+class C extends core::Object {
+ static field core::int* staticField = 1;
+ field core::int* field = 1;
+ synthetic constructor •() → self::C*
+ : super core::Object::•()
+ ;
+ static get staticGetter() → core::int*
+ return self::C::staticField;
+ static set staticSetter(dynamic val) → void {
+ self::C::staticField = val as{TypeError} core::int*;
+ }
+ static method staticFoo(core::int* param) → core::int*
+ return param;
+ get getter() → core::int*
+ return this.{self::C::field};
+ set setter(dynamic val) → void {
+ this.{self::C::field} = val as{TypeError} core::int*;
+ }
+ method foo(core::int* param) → core::int*
+ return param;
+}
+static field core::int* globalVariable = 1;
+static final field core::bool* assertStatementsEnabled = (() → core::bool* {
+ try {
+ assert(false);
+ return false;
+ }
+ on dynamic catch(final dynamic _) {
+ return true;
+ }
+}).call();
+static method topLevelFoo(core::int* param) → core::int*
+ return 1;
+static get topLevelGetter() → core::int*
+ return self::globalVariable;
+static set topLevelSetter(dynamic val) → void {
+ self::globalVariable = val as{TypeError} core::int*;
+}
+static method dummy() → dynamic
+ return 1;
+static method staticMembers() → dynamic async {
+ core::num* a = self::C::staticField.{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, a);
+ core::num* f = (self::C::staticField = 1).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, f);
+ core::num* b = self::C::staticGetter.{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, b);
+ core::num* c = (self::C::staticSetter = 1).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, c);
+ core::num* d = self::C::staticFoo(2).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(3, d);
+ core::num* e = self::C::staticField.{core::num::+}(self::C::staticGetter).{core::num::+}(self::C::staticSetter = 1).{core::num::+}(self::C::staticFoo(1)).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(5, e);
+}
+static method topLevelMembers() → dynamic async {
+ core::num* a = self::globalVariable.{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, a);
+ core::num* b = self::topLevelGetter.{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, b);
+ core::num* c = (self::topLevelSetter = 1).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, c);
+ core::num* d = self::topLevelFoo(1).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, d);
+ core::num* e = self::globalVariable.{core::num::+}(self::topLevelGetter).{core::num::+}(self::topLevelSetter = 1).{core::num::+}(self::topLevelFoo(1)).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(5, e);
+}
+static method instanceMembers() → dynamic async {
+ self::C* inst = new self::C::•();
+ core::num* a = inst.{self::C::field}.{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, a);
+ core::num* b = inst.{self::C::getter}.{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, b);
+ core::num* c = (inst.{self::C::setter} = 1).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, c);
+ core::num* d = inst.{self::C::foo}(1).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, d);
+ core::num* e = inst.{self::C::field}.{core::num::+}(inst.{self::C::getter}).{core::num::+}(inst.{self::C::setter} = 1).{core::num::+}(inst.{self::C::foo}(1)).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(5, e);
+}
+static method others() → dynamic async {
+ core::String* a = "${self::globalVariable} ${await self::dummy()} ".{core::String::+}(await "someString");
+ self::expect("1 1 someString", a);
+ self::C* c = new self::C::•();
+ core::num* d = c.{self::C::field}.{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ core::int* cnt = 2;
+ core::List<core::int*>* b = <core::int*>[1, 2, 3];
+ b.{core::List::[]=}(cnt, await self::dummy() as{TypeError} core::int*);
+ self::expect(1, b.{core::List::[]}(cnt));
+ core::num* e = b.{core::List::[]}(0).{core::num::+}(await self::dummy() as{TypeError} core::num*);
+ self::expect(2, e);
+}
+static method conditionals() → dynamic async {
+ core::bool* a = false;
+ core::bool* b = true;
+ core::bool* c = a || b || await self::dummy() as{TypeError} core::bool*;
+ self::expect(true, c);
+ dynamic d = a || b ?{dynamic} a : await self::dummy();
+ self::expect(false, d);
+ dynamic e = a is core::int* ?{dynamic} await self::dummy() : 2;
+ self::expect(2, e);
+ try {
+ dynamic f = a is core::int* ?{dynamic} await self::dummy() : 2;
+ }
+ on dynamic catch(final dynamic e) {
+ }
+}
+static method asserts() → dynamic async {
+ for (final core::Function* #t1 in <core::Function*>[#C1, #C2]) {
+ final <T extends core::Object* = dynamic>(T*) →* asy::FutureOr<T*>* func = #t1 as{TypeError} <T extends core::Object* = dynamic>(T*) →* asy::FutureOr<T*>*;
+ assert(await func.call<core::bool*>(true));
+ assert(self::id<core::bool*>(true) as{TypeError} core::bool*, await func.call<core::String*>("message"));
+ assert(await func.call<core::bool*>(true), await func.call<core::String*>("message"));
+ try {
+ assert(await func.call<core::bool*>(false), await func.call<core::String*>("message"));
+ if(self::assertStatementsEnabled)
+ throw "Didn't throw";
+ }
+ on core::AssertionError* catch(final core::AssertionError* e) {
+ self::expect("message", e.{core::AssertionError::message});
+ }
+ }
+}
+static method controlFlow() → dynamic async {
+ for (final core::Function* #t2 in <core::Function*>[#C1, #C2]) {
+ final <T extends core::Object* = dynamic>(T*) →* asy::FutureOr<T*>* func = #t2 as{TypeError} <T extends core::Object* = dynamic>(T*) →* asy::FutureOr<T*>*;
+ core::int* c = 0;
+ for (core::int* i = await func.call<core::int*>(0); await func.call<core::bool*>(i.{core::num::<}(5)); await func.call<core::int*>(let final core::int* #t3 = i in let final core::int* #t4 = i = #t3.{core::num::+}(1) in #t3)) {
+ c = c.{core::num::+}(1);
+ }
+ self::expect(5, c);
+ c = 0;
+ while (await func.call<core::bool*>(c.{core::num::<}(5)))
+ c = c.{core::num::+}(1);
+ self::expect(5, c);
+ c = 0;
+ do {
+ c = c.{core::num::+}(1);
+ }
+ while (await func.call<core::bool*>(c.{core::num::<}(5)))
+ self::expect(5, c);
+ if(await func.call<core::bool*>(c.{core::num::==}(5))) {
+ self::expect(5, c);
+ }
+ else {
+ throw "unreachable";
+ }
+ try {
+ throw await func.call<core::String*>("string");
+ }
+ on core::String* catch(no-exception-var) {
+ }
+ try {
+ await throw "string";
+ }
+ on core::String* catch(no-exception-var) {
+ }
+ try
+ try {
+ try
+ try {
+ throw "string";
+ }
+ on dynamic catch(final dynamic e) {
+ self::expect("string", e);
+ self::expect(0, await func.call<core::int*>(0));
+ rethrow;
+ }
+ finally {
+ self::expect(0, await func.call<core::int*>(0));
+ }
+ }
+ on dynamic catch(final dynamic e) {
+ self::expect(0, await func.call<core::int*>(0));
+ self::expect("string", e);
+ }
+ finally {
+ self::expect(0, await func.call<core::int*>(0));
+ }
+ #L1:
+ switch(await func.call<core::int*>(2)) {
+ #L2:
+ case #C3:
+ {
+ break #L1;
+ }
+ #L3:
+ default:
+ {
+ throw "unreachable";
+ }
+ }
+ self::expect(42, await(() → asy::Future<dynamic>* async {
+ return await func.call<dynamic>(42);
+ }).call());
+ self::expect(42, await(() → asy::Future<dynamic>* async {
+ return func.call<dynamic>(42);
+ }).call());
+ function testStream1() → asy::Stream<core::int*>* async* {
+ yield await func.call<core::int*>(42);
+ }
+ self::expectList(<dynamic>[42], await testStream1.call().{asy::Stream::toList}());
+ function testStream2() → asy::Stream<core::int*>* async* {
+ yield* await func.call<asy::Stream<core::int*>*>(self::intStream());
+ }
+ self::expectList(<dynamic>[42], await testStream2.call().{asy::Stream::toList}());
+ }
+}
+static method future<T extends core::Object* = dynamic>(self::future::T* value) → asy::FutureOr<self::future::T*>* async
+ return value;
+static method id<T extends core::Object* = dynamic>(self::id::T* value) → asy::FutureOr<self::id::T*>*
+ return value;
+static method intStream() → asy::Stream<core::int*>* async* {
+ yield 42;
+}
+static method main() → dynamic async {
+ for (core::int* i = 0; i.{core::num::<}(11); i = i.{core::num::+}(1)) {
+ await self::staticMembers();
+ await self::topLevelMembers();
+ await self::instanceMembers();
+ await self::conditionals();
+ await self::others();
+ await self::asserts();
+ await self::controlFlow();
+ }
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method expectList(core::List<dynamic>* expected, core::List<dynamic>* actual) → dynamic {
+ if(!expected.{core::List::length}.{core::num::==}(actual.{core::List::length})) {
+ throw "Expected ${expected}, actual ${actual}";
+ }
+ for (core::int* i = 0; i.{core::num::<}(expected.{core::List::length}); i = i.{core::num::+}(1)) {
+ self::expect(expected.{core::List::[]}(i), actual.{core::List::[]}(i));
+ }
+}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = tearoff self::future
+ #C3 = 2
+}
diff --git a/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect b/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect
new file mode 100644
index 0000000..afff0fe
--- /dev/null
+++ b/pkg/front_end/testcases/general/await_complex.dart.strong.transformed.expect
@@ -0,0 +1,801 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class C extends core::Object {
+ static field core::int* staticField = 1;
+ field core::int* field = 1;
+ synthetic constructor •() → self::C*
+ : super core::Object::•()
+ ;
+ static get staticGetter() → core::int*
+ return self::C::staticField;
+ static set staticSetter(dynamic val) → void {
+ self::C::staticField = val as{TypeError} core::int*;
+ }
+ static method staticFoo(core::int* param) → core::int*
+ return param;
+ get getter() → core::int*
+ return this.{self::C::field};
+ set setter(dynamic val) → void {
+ this.{self::C::field} = val as{TypeError} core::int*;
+ }
+ method foo(core::int* param) → core::int*
+ return param;
+}
+static field core::int* globalVariable = 1;
+static final field core::bool* assertStatementsEnabled = (() → core::bool* {
+ try {
+ assert(false);
+ return false;
+ }
+ on dynamic catch(final dynamic _) {
+ return true;
+ }
+}).call();
+static method topLevelFoo(core::int* param) → core::int*
+ return 1;
+static get topLevelGetter() → core::int*
+ return self::globalVariable;
+static set topLevelSetter(dynamic val) → void {
+ self::globalVariable = val as{TypeError} core::int*;
+}
+static method dummy() → dynamic
+ return 1;
+static method staticMembers() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ core::int* :async_temporary_0;
+ core::int* :async_temporary_1;
+ core::int* :async_temporary_2;
+ core::int* :async_temporary_3;
+ core::int* :async_temporary_4;
+ core::int* :async_temporary_5;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ :async_temporary_0 = self::C::staticField;
+ [yield] let dynamic #t1 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* a = :async_temporary_0.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, a);
+ :async_temporary_1 = self::C::staticField = 1;
+ [yield] let dynamic #t2 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* f = :async_temporary_1.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, f);
+ :async_temporary_2 = self::C::staticGetter;
+ [yield] let dynamic #t3 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* b = :async_temporary_2.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, b);
+ :async_temporary_3 = self::C::staticSetter = 1;
+ [yield] let dynamic #t4 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* c = :async_temporary_3.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, c);
+ :async_temporary_4 = self::C::staticFoo(2);
+ [yield] let dynamic #t5 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* d = :async_temporary_4.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(3, d);
+ :async_temporary_5 = self::C::staticField.{core::num::+}(self::C::staticGetter).{core::num::+}(self::C::staticSetter = 1).{core::num::+}(self::C::staticFoo(1));
+ [yield] let dynamic #t6 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* e = :async_temporary_5.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(5, e);
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method topLevelMembers() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ core::int* :async_temporary_0;
+ core::int* :async_temporary_1;
+ core::int* :async_temporary_2;
+ core::int* :async_temporary_3;
+ core::int* :async_temporary_4;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ :async_temporary_0 = self::globalVariable;
+ [yield] let dynamic #t7 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* a = :async_temporary_0.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, a);
+ :async_temporary_1 = self::topLevelGetter;
+ [yield] let dynamic #t8 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* b = :async_temporary_1.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, b);
+ :async_temporary_2 = self::topLevelSetter = 1;
+ [yield] let dynamic #t9 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* c = :async_temporary_2.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, c);
+ :async_temporary_3 = self::topLevelFoo(1);
+ [yield] let dynamic #t10 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* d = :async_temporary_3.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, d);
+ :async_temporary_4 = self::globalVariable.{core::num::+}(self::topLevelGetter).{core::num::+}(self::topLevelSetter = 1).{core::num::+}(self::topLevelFoo(1));
+ [yield] let dynamic #t11 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* e = :async_temporary_4.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(5, e);
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method instanceMembers() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ core::int* :async_temporary_0;
+ core::int* :async_temporary_1;
+ core::int* :async_temporary_2;
+ core::int* :async_temporary_3;
+ core::int* :async_temporary_4;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L3:
+ {
+ self::C* inst = new self::C::•();
+ :async_temporary_0 = inst.{self::C::field};
+ [yield] let dynamic #t12 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* a = :async_temporary_0.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, a);
+ :async_temporary_1 = inst.{self::C::getter};
+ [yield] let dynamic #t13 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* b = :async_temporary_1.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, b);
+ :async_temporary_2 = inst.{self::C::setter} = 1;
+ [yield] let dynamic #t14 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* c = :async_temporary_2.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, c);
+ :async_temporary_3 = inst.{self::C::foo}(1);
+ [yield] let dynamic #t15 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* d = :async_temporary_3.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, d);
+ :async_temporary_4 = inst.{self::C::field}.{core::num::+}(inst.{self::C::getter}).{core::num::+}(inst.{self::C::setter} = 1).{core::num::+}(inst.{self::C::foo}(1));
+ [yield] let dynamic #t16 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* e = :async_temporary_4.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(5, e);
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method others() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ core::String* :async_temporary_0;
+ core::int* :async_temporary_1;
+ core::int* :async_temporary_2;
+ core::List<core::int*>* :async_temporary_3;
+ core::int* :async_temporary_4;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L4:
+ {
+ :async_temporary_0 = self::globalVariable;
+ [yield] let dynamic #t17 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ :async_temporary_0 = "${:async_temporary_0} ${:result} ";
+ [yield] let dynamic #t18 = asy::_awaitHelper("someString", :async_op_then, :async_op_error, :async_op) in null;
+ core::String* a = :async_temporary_0.{core::String::+}(_in::unsafeCast<core::String*>(:result));
+ self::expect("1 1 someString", a);
+ self::C* c = new self::C::•();
+ :async_temporary_1 = c.{self::C::field};
+ [yield] let dynamic #t19 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* d = :async_temporary_1.{core::num::+}(:result as{TypeError} core::num*);
+ core::int* cnt = 2;
+ core::List<core::int*>* b = <core::int*>[1, 2, 3];
+ :async_temporary_3 = b;
+ :async_temporary_2 = cnt;
+ [yield] let dynamic #t20 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ :async_temporary_3.{core::List::[]=}(:async_temporary_2, :result as{TypeError} core::int*);
+ self::expect(1, b.{core::List::[]}(cnt));
+ :async_temporary_4 = b.{core::List::[]}(0);
+ [yield] let dynamic #t21 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ core::num* e = :async_temporary_4.{core::num::+}(:result as{TypeError} core::num*);
+ self::expect(2, e);
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method conditionals() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ dynamic :saved_try_context_var1;
+ core::bool* :async_temporary_0;
+ dynamic :async_temporary_1;
+ dynamic :async_temporary_2;
+ dynamic :async_temporary_3;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L5:
+ {
+ core::bool* a = false;
+ core::bool* b = true;
+ :async_temporary_0 = (a || b).==(true);
+ if(:async_temporary_0)
+ ;
+ else {
+ [yield] let dynamic #t22 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ :async_temporary_0 = (:result as{TypeError} core::bool*).==(true);
+ }
+ core::bool* c = :async_temporary_0;
+ self::expect(true, c);
+ if(a || b) {
+ :async_temporary_1 = a;
+ }
+ else {
+ [yield] let dynamic #t23 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ :async_temporary_1 = :result;
+ }
+ dynamic d = :async_temporary_1;
+ self::expect(false, d);
+ if(a is core::int*) {
+ [yield] let dynamic #t24 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ :async_temporary_2 = :result;
+ }
+ else {
+ :async_temporary_2 = 2;
+ }
+ dynamic e = :async_temporary_2;
+ self::expect(2, e);
+ try {
+ if(a is core::int*) {
+ [yield] let dynamic #t25 = asy::_awaitHelper(self::dummy(), :async_op_then, :async_op_error, :async_op) in null;
+ :async_temporary_3 = :result;
+ }
+ else {
+ :async_temporary_3 = 2;
+ }
+ dynamic f = :async_temporary_3;
+ }
+ on dynamic catch(final dynamic e) {
+ }
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method asserts() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ dynamic :saved_try_context_var1;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L6:
+ {
+ for (final core::Function* #t26 in <core::Function*>[#C1, #C2]) {
+ final <T extends core::Object* = dynamic>(T*) →* asy::FutureOr<T*>* func = #t26 as{TypeError} <T extends core::Object* = dynamic>(T*) →* asy::FutureOr<T*>*;
+ assert {
+ [yield] let dynamic #t27 = asy::_awaitHelper(func.call<core::bool*>(true), :async_op_then, :async_op_error, :async_op) in null;
+ assert(_in::unsafeCast<core::bool*>(:result));
+ }
+ assert {
+ if(self::id<core::bool*>(true) as{TypeError} core::bool*)
+ ;
+ else {
+ [yield] let dynamic #t28 = asy::_awaitHelper(func.call<core::String*>("message"), :async_op_then, :async_op_error, :async_op) in null;
+ assert(false, _in::unsafeCast<core::String*>(:result));
+ }
+ }
+ assert {
+ [yield] let dynamic #t29 = asy::_awaitHelper(func.call<core::bool*>(true), :async_op_then, :async_op_error, :async_op) in null;
+ if(_in::unsafeCast<core::bool*>(:result))
+ ;
+ else {
+ [yield] let dynamic #t30 = asy::_awaitHelper(func.call<core::String*>("message"), :async_op_then, :async_op_error, :async_op) in null;
+ assert(false, _in::unsafeCast<core::String*>(:result));
+ }
+ }
+ try {
+ assert {
+ [yield] let dynamic #t31 = asy::_awaitHelper(func.call<core::bool*>(false), :async_op_then, :async_op_error, :async_op) in null;
+ if(_in::unsafeCast<core::bool*>(:result))
+ ;
+ else {
+ [yield] let dynamic #t32 = asy::_awaitHelper(func.call<core::String*>("message"), :async_op_then, :async_op_error, :async_op) in null;
+ assert(false, _in::unsafeCast<core::String*>(:result));
+ }
+ }
+ if(self::assertStatementsEnabled)
+ throw "Didn't throw";
+ }
+ on core::AssertionError* catch(final core::AssertionError* e) {
+ self::expect("message", e.{core::AssertionError::message});
+ }
+ }
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method controlFlow() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ dynamic :saved_try_context_var1;
+ dynamic :saved_try_context_var2;
+ dynamic :saved_try_context_var3;
+ dynamic :exception0;
+ dynamic :stack_trace0;
+ core::List<dynamic>* :async_temporary_0;
+ core::List<dynamic>* :async_temporary_1;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L7:
+ {
+ for (final core::Function* #t33 in <core::Function*>[#C1, #C2]) {
+ final <T extends core::Object* = dynamic>(T*) →* asy::FutureOr<T*>* func = #t33 as{TypeError} <T extends core::Object* = dynamic>(T*) →* asy::FutureOr<T*>*;
+ core::int* c = 0;
+ {
+ dynamic #t34 = true;
+ core::int* #t35;
+ #L8:
+ while (true) {
+ core::int* i;
+ if(#t34) {
+ #t34 = false;
+ [yield] let dynamic #t36 = asy::_awaitHelper(func.call<core::int*>(0), :async_op_then, :async_op_error, :async_op) in null;
+ i = _in::unsafeCast<core::int*>(:result);
+ }
+ else {
+ i = #t35;
+ [yield] let dynamic #t37 = asy::_awaitHelper(func.call<core::int*>(let final core::int* #t38 = i in let final core::int* #t39 = i = #t38.{core::num::+}(1) in #t38), :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<core::int*>(:result);
+ }
+ [yield] let dynamic #t40 = asy::_awaitHelper(func.call<core::bool*>(i.{core::num::<}(5)), :async_op_then, :async_op_error, :async_op) in null;
+ if(_in::unsafeCast<core::bool*>(:result)) {
+ {
+ c = c.{core::num::+}(1);
+ }
+ #t35 = i;
+ }
+ else
+ break #L8;
+ }
+ }
+ self::expect(5, c);
+ c = 0;
+ #L9:
+ while (true) {
+ [yield] let dynamic #t41 = asy::_awaitHelper(func.call<core::bool*>(c.{core::num::<}(5)), :async_op_then, :async_op_error, :async_op) in null;
+ if(_in::unsafeCast<core::bool*>(:result))
+ c = c.{core::num::+}(1);
+ else
+ break #L9;
+ }
+ self::expect(5, c);
+ c = 0;
+ do {
+ c = c.{core::num::+}(1);
+ [yield] let dynamic #t42 = asy::_awaitHelper(func.call<core::bool*>(c.{core::num::<}(5)), :async_op_then, :async_op_error, :async_op) in null;
+ }
+ while (_in::unsafeCast<core::bool*>(:result))
+ self::expect(5, c);
+ [yield] let dynamic #t43 = asy::_awaitHelper(func.call<core::bool*>(c.{core::num::==}(5)), :async_op_then, :async_op_error, :async_op) in null;
+ if(_in::unsafeCast<core::bool*>(:result)) {
+ self::expect(5, c);
+ }
+ else {
+ throw "unreachable";
+ }
+ try {
+ [yield] let dynamic #t44 = asy::_awaitHelper(func.call<core::String*>("string"), :async_op_then, :async_op_error, :async_op) in null;
+ throw _in::unsafeCast<core::String*>(:result);
+ }
+ on core::String* catch(no-exception-var) {
+ }
+ try {
+ [yield] let dynamic #t45 = asy::_awaitHelper(throw "string", :async_op_then, :async_op_error, :async_op) in null;
+ _in::unsafeCast<<BottomType>>(:result);
+ }
+ on core::String* catch(no-exception-var) {
+ }
+ try
+ try {
+ try
+ try {
+ throw "string";
+ }
+ on dynamic catch(final dynamic e) {
+ self::expect("string", e);
+ [yield] let dynamic #t46 = asy::_awaitHelper(func.call<core::int*>(0), :async_op_then, :async_op_error, :async_op) in null;
+ self::expect(0, _in::unsafeCast<core::int*>(:result));
+ rethrow;
+ }
+ finally {
+ [yield] let dynamic #t47 = asy::_awaitHelper(func.call<core::int*>(0), :async_op_then, :async_op_error, :async_op) in null;
+ self::expect(0, _in::unsafeCast<core::int*>(:result));
+ }
+ }
+ on dynamic catch(final dynamic e) {
+ [yield] let dynamic #t48 = asy::_awaitHelper(func.call<core::int*>(0), :async_op_then, :async_op_error, :async_op) in null;
+ self::expect(0, _in::unsafeCast<core::int*>(:result));
+ self::expect("string", e);
+ }
+ finally {
+ [yield] let dynamic #t49 = asy::_awaitHelper(func.call<core::int*>(0), :async_op_then, :async_op_error, :async_op) in null;
+ self::expect(0, _in::unsafeCast<core::int*>(:result));
+ }
+ #L10:
+ {
+ [yield] let dynamic #t50 = asy::_awaitHelper(func.call<core::int*>(2), :async_op_then, :async_op_error, :async_op) in null;
+ switch(_in::unsafeCast<core::int*>(:result)) {
+ #L11:
+ case #C3:
+ {
+ break #L10;
+ }
+ #L12:
+ default:
+ {
+ throw "unreachable";
+ }
+ }
+ }
+ [yield] let dynamic #t51 = asy::_awaitHelper((() → asy::Future<dynamic>* /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L13:
+ {
+ [yield] let dynamic #t52 = asy::_awaitHelper(func.call<dynamic>(42), :async_op_then, :async_op_error, :async_op) in null;
+ :return_value = :result;
+ break #L13;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+ }).call(), :async_op_then, :async_op_error, :async_op) in null;
+ self::expect(42, :result);
+ [yield] let dynamic #t53 = asy::_awaitHelper((() → asy::Future<dynamic>* /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L14:
+ {
+ :return_value = func.call<dynamic>(42);
+ break #L14;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+ }).call(), :async_op_then, :async_op_error, :async_op) in null;
+ self::expect(42, :result);
+ function testStream1() → asy::Stream<core::int*>* /* originally async* */ {
+ asy::_AsyncStarStreamController<core::int*>* :controller;
+ dynamic :controller_stream;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ dynamic :saved_try_context_var1;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try
+ try {
+ #L15:
+ {
+ [yield] let dynamic #t54 = asy::_awaitHelper(func.call<core::int*>(42), :async_op_then, :async_op_error, :async_op) in null;
+ if(:controller.{asy::_AsyncStarStreamController::add}(_in::unsafeCast<core::int*>(:result)))
+ return null;
+ else
+ [yield] null;
+ }
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
+ }
+ finally {
+ :controller.{asy::_AsyncStarStreamController::close}();
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :controller = new asy::_AsyncStarStreamController::•<core::int*>(:async_op);
+ :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
+ return :controller_stream;
+ }
+ :async_temporary_0 = <dynamic>[42];
+ [yield] let dynamic #t55 = asy::_awaitHelper(testStream1.call().{asy::Stream::toList}(), :async_op_then, :async_op_error, :async_op) in null;
+ self::expectList(:async_temporary_0, _in::unsafeCast<core::List<core::int*>*>(:result));
+ function testStream2() → asy::Stream<core::int*>* /* originally async* */ {
+ asy::_AsyncStarStreamController<core::int*>* :controller;
+ dynamic :controller_stream;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ dynamic :saved_try_context_var1;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try
+ try {
+ #L16:
+ {
+ [yield] let dynamic #t56 = asy::_awaitHelper(func.call<asy::Stream<core::int*>*>(self::intStream()), :async_op_then, :async_op_error, :async_op) in null;
+ if(:controller.{asy::_AsyncStarStreamController::addStream}(_in::unsafeCast<asy::Stream<core::int*>*>(:result)))
+ return null;
+ else
+ [yield] null;
+ }
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
+ }
+ finally {
+ :controller.{asy::_AsyncStarStreamController::close}();
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :controller = new asy::_AsyncStarStreamController::•<core::int*>(:async_op);
+ :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
+ return :controller_stream;
+ }
+ :async_temporary_1 = <dynamic>[42];
+ [yield] let dynamic #t57 = asy::_awaitHelper(testStream2.call().{asy::Stream::toList}(), :async_op_then, :async_op_error, :async_op) in null;
+ self::expectList(:async_temporary_1, _in::unsafeCast<core::List<core::int*>*>(:result));
+ }
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method future<T extends core::Object* = dynamic>(self::future::T* value) → asy::FutureOr<self::future::T*>* /* originally async */ {
+ final asy::_AsyncAwaitCompleter<self::future::T*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::future::T*>();
+ asy::FutureOr<self::future::T*>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L17:
+ {
+ :return_value = value;
+ break #L17;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method id<T extends core::Object* = dynamic>(self::id::T* value) → asy::FutureOr<self::id::T*>*
+ return value;
+static method intStream() → asy::Stream<core::int*>* /* originally async* */ {
+ asy::_AsyncStarStreamController<core::int*>* :controller;
+ dynamic :controller_stream;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ dynamic :saved_try_context_var1;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try
+ try {
+ #L18:
+ {
+ if(:controller.{asy::_AsyncStarStreamController::add}(42))
+ return null;
+ else
+ [yield] null;
+ }
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :controller.{asy::_AsyncStarStreamController::addError}(:exception, :stack_trace);
+ }
+ finally {
+ :controller.{asy::_AsyncStarStreamController::close}();
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :controller = new asy::_AsyncStarStreamController::•<core::int*>(:async_op);
+ :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
+ return :controller_stream;
+}
+static method main() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L19:
+ {
+ for (core::int* i = 0; i.{core::num::<}(11); i = i.{core::num::+}(1)) {
+ [yield] let dynamic #t58 = asy::_awaitHelper(self::staticMembers(), :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ [yield] let dynamic #t59 = asy::_awaitHelper(self::topLevelMembers(), :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ [yield] let dynamic #t60 = asy::_awaitHelper(self::instanceMembers(), :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ [yield] let dynamic #t61 = asy::_awaitHelper(self::conditionals(), :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ [yield] let dynamic #t62 = asy::_awaitHelper(self::others(), :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ [yield] let dynamic #t63 = asy::_awaitHelper(self::asserts(), :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ [yield] let dynamic #t64 = asy::_awaitHelper(self::controlFlow(), :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ }
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method expectList(core::List<dynamic>* expected, core::List<dynamic>* actual) → dynamic {
+ if(!expected.{core::List::length}.{core::num::==}(actual.{core::List::length})) {
+ throw "Expected ${expected}, actual ${actual}";
+ }
+ for (core::int* i = 0; i.{core::num::<}(expected.{core::List::length}); i = i.{core::num::+}(1)) {
+ self::expect(expected.{core::List::[]}(i), actual.{core::List::[]}(i));
+ }
+}
+
+constants {
+ #C1 = tearoff self::id
+ #C2 = tearoff self::future
+ #C3 = 2
+}
diff --git a/pkg/front_end/testcases/general/await_in_cascade.dart b/pkg/front_end/testcases/general/await_in_cascade.dart
new file mode 100644
index 0000000..47cc183
--- /dev/null
+++ b/pkg/front_end/testcases/general/await_in_cascade.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2016, 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.
+
+// This test was adapted from language_2/await_in_cascade_ test
+
+import 'dart:async';
+
+class C {
+ Future<List<int>> m() async => []..add(await _m());
+ Future<int> _m() async => 42;
+}
+
+main() async {
+ expect(42, (await new C().m()).first);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/general/await_in_cascade.dart.outline.expect b/pkg/front_end/testcases/general/await_in_cascade.dart.outline.expect
new file mode 100644
index 0000000..c59c111
--- /dev/null
+++ b/pkg/front_end/testcases/general/await_in_cascade.dart.outline.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+class C extends core::Object {
+ synthetic constructor •() → self::C*
+ ;
+ method m() → asy::Future<core::List<core::int*>*>*
+ ;
+ method _m() → asy::Future<core::int*>*
+ ;
+}
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/await_in_cascade.dart.strong.expect b/pkg/front_end/testcases/general/await_in_cascade.dart.strong.expect
new file mode 100644
index 0000000..4db7c74
--- /dev/null
+++ b/pkg/front_end/testcases/general/await_in_cascade.dart.strong.expect
@@ -0,0 +1,23 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+class C extends core::Object {
+ synthetic constructor •() → self::C*
+ : super core::Object::•()
+ ;
+ method m() → asy::Future<core::List<core::int*>*>* async
+ return let final core::List<core::int*>* #t1 = <core::int*>[] in let final void #t2 = #t1.{core::List::add}(await this.{self::C::_m}()) in #t1;
+ method _m() → asy::Future<core::int*>* async
+ return 42;
+}
+static method main() → dynamic async {
+ self::expect(42, (await new self::C::•().{self::C::m}()).{core::Iterable::first});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect
new file mode 100644
index 0000000..be2d683
--- /dev/null
+++ b/pkg/front_end/testcases/general/await_in_cascade.dart.strong.transformed.expect
@@ -0,0 +1,102 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class C extends core::Object {
+ synthetic constructor •() → self::C*
+ : super core::Object::•()
+ ;
+ method m() → asy::Future<core::List<core::int*>*>* /* originally async */ {
+ final asy::_AsyncAwaitCompleter<core::List<core::int*>*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::List<core::int*>*>();
+ asy::FutureOr<core::List<core::int*>*>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ final core::List<core::int*>* #t1 = <core::int*>[];
+ [yield] let dynamic #t2 = asy::_awaitHelper(this.{self::C::_m}(), :async_op_then, :async_op_error, :async_op) in null;
+ :return_value = let final void #t3 = #t1.{core::List::add}(_in::unsafeCast<core::int*>(:result)) in #t1;
+ break #L1;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+ }
+ method _m() → asy::Future<core::int*>* /* originally async */ {
+ final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
+ asy::FutureOr<core::int*>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ :return_value = 42;
+ break #L2;
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+ }
+}
+static method main() → dynamic /* originally async */ {
+ final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+ asy::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L3:
+ {
+ [yield] let dynamic #t4 = asy::_awaitHelper(new self::C::•().{self::C::m}(), :async_op_then, :async_op_error, :async_op) in null;
+ self::expect(42, _in::unsafeCast<core::List<core::int*>*>(:result).{core::Iterable::first});
+ }
+ asy::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+ :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{asy::Completer::future};
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/general/bug33196.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33196.dart.strong.transformed.expect
index b555ba7..ca4c8a8 100644
--- a/pkg/front_end/testcases/general/bug33196.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33196.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
index 6e31cf5..052b974 100644
--- a/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33206.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -26,7 +27,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -55,7 +56,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -82,7 +83,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -91,10 +92,10 @@
{
final self::Y* #t1 = new self::Y::•();
[yield] let dynamic #t2 = asy::_awaitHelper(self::f1(), :async_op_then, :async_op_error, :async_op) in null;
- final void #t3 = #t1.{self::Y::f}(:result);
+ final void #t3 = #t1.{self::Y::f}(_in::unsafeCast<core::List<core::Object*>*>(:result));
final void #t4 = #t1.{self::Y::f}(self::f2());
[yield] let dynamic #t5 = asy::_awaitHelper(self::f3(), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = new self::X::•(#t1, :result);
+ :return_value = new self::X::•(#t1, _in::unsafeCast<core::Object*>(:result));
break #L3;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -115,7 +116,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -123,7 +124,7 @@
#L4:
{
[yield] let dynamic #t6 = asy::_awaitHelper(self::foo(), :async_op_then, :async_op_error, :async_op) in null;
- core::print(:result);
+ core::print(_in::unsafeCast<self::X*>(:result));
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
diff --git a/pkg/front_end/testcases/general/call.dart.strong.expect b/pkg/front_end/testcases/general/call.dart.strong.expect
index 0346035..58e7da3 100644
--- a/pkg/front_end/testcases/general/call.dart.strong.expect
+++ b/pkg/front_end/testcases/general/call.dart.strong.expect
@@ -76,11 +76,11 @@
dynamic string3 = callable.{self::Callable::call}.call(1);
dynamic string4 = callable.{self::Callable::call}.call.call(1);
self::CallableGetter* callableGetter = new self::CallableGetter::•();
- dynamic string5 = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/call.dart:29:31: Error: Cannot invoke an instance of 'CallableGetter' because it declares 'call' to be something other than a method.
+ dynamic string5 = invalid-expression "pkg/front_end/testcases/general/call.dart:29:31: Error: Cannot invoke an instance of 'CallableGetter' because it declares 'call' to be something other than a method.
- 'CallableGetter' is from 'pkg/front_end/testcases/general/call.dart'.
Try changing 'call' to a method or explicitly invoke 'call'.
var string5 = callableGetter(1);
- ^" in callableGetter.{self::CallableGetter::call}(1);
+ ^";
dynamic string6 = callableGetter.{self::CallableGetter::call}(1);
dynamic string7 = callableGetter.{self::CallableGetter::call}.call(1);
dynamic string8 = callableGetter.{self::CallableGetter::call}.call.call(1);
@@ -92,11 +92,11 @@
dynamic nothing6 = callable.{self::Callable::call}();
dynamic nothing7 = callable.{self::Callable::call}.call();
dynamic nothing8 = callable.{self::Callable::call}.call.call();
- dynamic nothing9 = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/call.dart:44:32: Error: Cannot invoke an instance of 'CallableGetter' because it declares 'call' to be something other than a method.
+ dynamic nothing9 = invalid-expression "pkg/front_end/testcases/general/call.dart:44:32: Error: Cannot invoke an instance of 'CallableGetter' because it declares 'call' to be something other than a method.
- 'CallableGetter' is from 'pkg/front_end/testcases/general/call.dart'.
Try changing 'call' to a method or explicitly invoke 'call'.
var nothing9 = callableGetter();
- ^" in callableGetter.{self::CallableGetter::call}();
+ ^";
dynamic nothing10 = callableGetter.{self::CallableGetter::call}();
dynamic nothing11 = callableGetter.{self::CallableGetter::call}.call();
dynamic nothing12 = callableGetter.{self::CallableGetter::call}.call.call();
diff --git a/pkg/front_end/testcases/general/cascade.dart.strong.expect b/pkg/front_end/testcases/general/cascade.dart.strong.expect
index 1536d20..ed144d6 100644
--- a/pkg/front_end/testcases/general/cascade.dart.strong.expect
+++ b/pkg/front_end/testcases/general/cascade.dart.strong.expect
@@ -15,7 +15,7 @@
// pkg/front_end/testcases/general/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'int'.
// Try correcting the name to the name of an existing method, or defining a method named '[]'.
// ..first[0].toString()
-// ^^
+// ^
//
// pkg/front_end/testcases/general/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'int'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
@@ -41,7 +41,7 @@
^^^^".{core::Object::toString}() in let final void #t16 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'int'.
Try correcting the name to the name of an existing method, or defining a method named '[]'.
..first[0].toString()
- ^^".{core::Object::toString}() in let final void #t17 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'int'.
+ ^".{core::Object::toString}() in let final void #t17 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'int'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
..[0].last.toString();
^^^^".{core::Object::toString}() in #t13;
diff --git a/pkg/front_end/testcases/general/cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/general/cascade.dart.strong.transformed.expect
index 1536d20..ed144d6 100644
--- a/pkg/front_end/testcases/general/cascade.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/cascade.dart.strong.transformed.expect
@@ -15,7 +15,7 @@
// pkg/front_end/testcases/general/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'int'.
// Try correcting the name to the name of an existing method, or defining a method named '[]'.
// ..first[0].toString()
-// ^^
+// ^
//
// pkg/front_end/testcases/general/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'int'.
// Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
@@ -41,7 +41,7 @@
^^^^".{core::Object::toString}() in let final void #t16 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:29:12: Error: The method '[]' isn't defined for the class 'int'.
Try correcting the name to the name of an existing method, or defining a method named '[]'.
..first[0].toString()
- ^^".{core::Object::toString}() in let final void #t17 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'int'.
+ ^".{core::Object::toString}() in let final void #t17 = invalid-expression "pkg/front_end/testcases/general/cascade.dart:30:11: Error: The getter 'last' isn't defined for the class 'int'.
Try correcting the name to the name of an existing getter, or defining a getter or field named 'last'.
..[0].last.toString();
^^^^".{core::Object::toString}() in #t13;
diff --git a/pkg/front_end/testcases/general/check_deferred_before_args2.dart.strong.transformed.expect b/pkg/front_end/testcases/general/check_deferred_before_args2.dart.strong.transformed.expect
index 422eb51..d20f094 100644
--- a/pkg/front_end/testcases/general/check_deferred_before_args2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/check_deferred_before_args2.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
diff --git a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
index 4360cc9..afb21c7 100644
--- a/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/control_flow_collection_inference.dart.strong.transformed.expect
@@ -425,6 +425,7 @@
import "dart:core" as core;
import "dart:collection" as col;
import "dart:async" as asy;
+import "dart:_internal" as _in;
class A extends core::Object {
synthetic constructor •() → self::A*
@@ -1813,7 +1814,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -2100,7 +2101,7 @@
while (true) {
dynamic #t399 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t400 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
dynamic i = :for-iterator.{asy::_StreamIterator::current};
#t397.{core::List::add}(i);
}
@@ -2127,7 +2128,7 @@
while (true) {
dynamic #t404 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t405 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
dynamic i = :for-iterator.{asy::_StreamIterator::current};
#t402.{core::Set::add}(i);
}
@@ -2156,7 +2157,7 @@
while (true) {
dynamic #t409 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t410 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
dynamic i = :for-iterator.{asy::_StreamIterator::current};
#t407.{core::Map::[]=}("bar", i);
}
@@ -2186,7 +2187,7 @@
while (true) {
dynamic #t415 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t416 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
core::int* i = :for-iterator.{asy::_StreamIterator::current};
#t412.{core::List::add}(i);
}
@@ -2214,7 +2215,7 @@
while (true) {
dynamic #t421 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t422 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
core::int* i = :for-iterator.{asy::_StreamIterator::current};
#t418.{core::Set::add}(i);
}
@@ -2244,7 +2245,7 @@
while (true) {
dynamic #t427 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t428 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
core::int* i = :for-iterator.{asy::_StreamIterator::current};
#t424.{core::Map::[]=}("bar", i);
}
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.expect
index b4a23c0..d9a0e7e 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.expect
@@ -20,7 +20,7 @@
import "dart:core" as core;
part error_location_05_lib1.dart;
-static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x1(dynamic z = #C1, {dynamic z = #C1}) → dynamic {}
+static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x1(dynamic z, {dynamic z = #C1}) → dynamic {}
static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x2() → dynamic {
function y(dynamic z, {dynamic z = #C1}) → core::Null? {}
}
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.transformed.expect
index b4a23c0..d9a0e7e 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_05.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
import "dart:core" as core;
part error_location_05_lib1.dart;
-static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x1(dynamic z = #C1, {dynamic z = #C1}) → dynamic {}
+static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x1(dynamic z, {dynamic z = #C1}) → dynamic {}
static method /* from org-dartlang-testcase:///error_location_05_lib1.dart */ x2() → dynamic {
function y(dynamic z, {dynamic z = #C1}) → core::Null? {}
}
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.expect
index 2d14468..a8ad767 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.expect
@@ -20,7 +20,7 @@
import "dart:core" as core;
part error_location_06_lib1.dart;
-static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x1(dynamic z = #C1, {dynamic z = #C1}) → dynamic {}
+static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x1(dynamic z, {dynamic z = #C1}) → dynamic {}
static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x2() → dynamic {
function y(dynamic z, {dynamic z = #C1}) → core::Null? {}
}
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.transformed.expect
index 2d14468..a8ad767 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_06.dart.strong.transformed.expect
@@ -20,7 +20,7 @@
import "dart:core" as core;
part error_location_06_lib1.dart;
-static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x1(dynamic z = #C1, {dynamic z = #C1}) → dynamic {}
+static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x1(dynamic z, {dynamic z = #C1}) → dynamic {}
static method /* from org-dartlang-testcase:///error_location_06_lib1.dart */ x2() → dynamic {
function y(dynamic z, {dynamic z = #C1}) → core::Null? {}
}
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart b/pkg/front_end/testcases/general/ffi_sample.dart
new file mode 100644
index 0000000..db95797
--- /dev/null
+++ b/pkg/front_end/testcases/general/ffi_sample.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2019, 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.
+
+// This test was adapted from samples/ffi/coordinate.dart
+
+import 'dart:ffi';
+
+import "package:ffi/ffi.dart";
+
+/// Sample struct for dart:ffi library.
+class Coordinate extends Struct {
+ @Double()
+ double x;
+
+ @Double()
+ double y;
+
+ Pointer<Coordinate> next;
+
+ factory Coordinate.allocate(double x, double y, Pointer<Coordinate> next) {
+ return allocate<Coordinate>().ref
+ ..x = x
+ ..y = y
+ ..next = next;
+ }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.outline.expect b/pkg/front_end/testcases/general/ffi_sample.dart.outline.expect
new file mode 100644
index 0000000..37826b4
--- /dev/null
+++ b/pkg/front_end/testcases/general/ffi_sample.dart.outline.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:ffi" as ffi;
+import "dart:core" as core;
+
+import "dart:ffi";
+import "package:ffi/ffi.dart";
+
+class Coordinate extends ffi::Struct {
+ @ffi::Double::•()
+ field core::double* x;
+ @ffi::Double::•()
+ field core::double* y;
+ field ffi::Pointer<self::Coordinate*>* next;
+ static factory allocate(core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate*
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.strong.expect b/pkg/front_end/testcases/general/ffi_sample.dart.strong.expect
new file mode 100644
index 0000000..acbd85c
--- /dev/null
+++ b/pkg/front_end/testcases/general/ffi_sample.dart.strong.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:ffi" as ffi;
+import "dart:core" as core;
+import "package:ffi/src/allocation.dart" as all;
+
+import "dart:ffi";
+import "package:ffi/ffi.dart";
+
+class Coordinate extends ffi::Struct {
+ @#C1
+ field core::double* x = null;
+ @#C1
+ field core::double* y = null;
+ field ffi::Pointer<self::Coordinate*>* next = null;
+ static factory allocate(core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate* {
+ return let final self::Coordinate* #t1 = ffi::StructPointer|get#ref<self::Coordinate*>(all::allocate<self::Coordinate*>()) in let final void #t2 = #t1.{self::Coordinate::x} = x in let final void #t3 = #t1.{self::Coordinate::y} = y in let final void #t4 = #t1.{self::Coordinate::next} = next in #t1;
+ }
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = ffi::Double {}
+}
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.strong.transformed.expect b/pkg/front_end/testcases/general/ffi_sample.dart.strong.transformed.expect
new file mode 100644
index 0000000..2b10843
--- /dev/null
+++ b/pkg/front_end/testcases/general/ffi_sample.dart.strong.transformed.expect
@@ -0,0 +1,54 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:ffi" as ffi;
+import "package:ffi/src/allocation.dart" as all;
+
+import "dart:ffi";
+import "package:ffi/ffi.dart";
+
+@#C3
+class Coordinate extends ffi::Struct {
+ @#C3
+ static final field core::int* #sizeOf = (#C6).{core::List::[]}(ffi::_abi())/* from null */;
+ @#C3
+ constructor #fromPointer(dynamic #pointer) → dynamic
+ : super ffi::Struct::_fromPointer(#pointer)
+ ;
+ static factory allocate(core::double* x, core::double* y, ffi::Pointer<self::Coordinate*>* next) → self::Coordinate* {
+ return let final self::Coordinate* #t1 = ffi::StructPointer|get#ref<self::Coordinate*>(all::allocate<self::Coordinate*>()) in let final void #t2 = #t1.{self::Coordinate::x} = x in let final void #t3 = #t1.{self::Coordinate::y} = y in let final void #t4 = #t1.{self::Coordinate::next} = next in #t1;
+ }
+ get #_ptr_x() → ffi::Pointer<ffi::Double*>*
+ return this.{ffi::Struct::_addressOf}.{ffi::Pointer::cast}<ffi::Double*>();
+ get x() → core::double*
+ return ffi::_loadDouble(this.{self::Coordinate::#_ptr_x}, #C7);
+ set x(core::double* #v) → void
+ return ffi::_storeDouble(this.{self::Coordinate::#_ptr_x}, #C7, #v);
+ get #_ptr_y() → ffi::Pointer<ffi::Double*>*
+ return this.{ffi::Struct::_addressOf}.{ffi::Pointer::_offsetBy}((#C9).{core::List::[]}(ffi::_abi())).{ffi::Pointer::cast}<ffi::Double*>();
+ get y() → core::double*
+ return ffi::_loadDouble(this.{self::Coordinate::#_ptr_y}, #C7);
+ set y(core::double* #v) → void
+ return ffi::_storeDouble(this.{self::Coordinate::#_ptr_y}, #C7, #v);
+ get #_ptr_next() → ffi::Pointer<ffi::Pointer<self::Coordinate*>*>*
+ return this.{ffi::Struct::_addressOf}.{ffi::Pointer::_offsetBy}((#C11).{core::List::[]}(ffi::_abi())).{ffi::Pointer::cast}<ffi::Pointer<self::Coordinate*>*>();
+ get next() → ffi::Pointer<self::Coordinate*>*
+ return ffi::_loadPointer<ffi::Pointer<self::Coordinate*>*>(this.{self::Coordinate::#_ptr_next}, #C7);
+ set next(ffi::Pointer<self::Coordinate*>* #v) → void
+ return ffi::_storePointer<ffi::Pointer<self::Coordinate*>*>(this.{self::Coordinate::#_ptr_next}, #C7, #v);
+}
+static method main() → dynamic {}
+
+constants {
+ #C1 = "vm:entry-point"
+ #C2 = null
+ #C3 = core::pragma {name:#C1, options:#C2}
+ #C4 = 24
+ #C5 = 20
+ #C6 = <core::int*>[#C4, #C5, #C4]
+ #C7 = 0
+ #C8 = 8
+ #C9 = <core::int*>[#C8, #C8, #C8]
+ #C10 = 16
+ #C11 = <core::int*>[#C10, #C10, #C10]
+}
diff --git a/pkg/front_end/testcases/general/future_or_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/future_or_test.dart.strong.transformed.expect
index 9ec74f5..1d1c466 100644
--- a/pkg/front_end/testcases/general/future_or_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/future_or_test.dart.strong.transformed.expect
@@ -23,7 +23,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -56,7 +56,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/general/issue39344.dart b/pkg/front_end/testcases/general/issue39344.dart
new file mode 100644
index 0000000..e8fe329
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue39344.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2019, 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.
+
+class A {}
+
+class B extends A {}
+
+List<B> xs;
+List<List<B>> xss;
+
+class Class<T extends A> {
+ void method1a(T t) {
+ if (t is B) {
+ // `t` is now promoted to T & B
+
+ // The list literal has type List<T>, not List<T & B>
+ var ys = [t];
+ xs = ys;
+ }
+ }
+
+ void method1b(T t) {
+ if (t is B) {
+ // `t` is now promoted to T & B
+
+ // The list literal has type List<List<T>>, not List<List<T & B>>
+ var yss = [
+ [t]
+ ];
+ xss = yss;
+ }
+ }
+
+ void method2a(T t) {
+ dynamic alias;
+ if (t is B) {
+ // `t` is now promoted to T & B
+
+ // The list literal has type List<T>, not List<T & B>
+ var ys = [t];
+ alias = ys;
+ xs = alias;
+ }
+ }
+
+ void method2b(T t) {
+ dynamic alias;
+ if (t is B) {
+ // `t` is now promoted to T & B
+
+ // The list literal has type List<List<T>>, not List<List<T & B>>
+ var yss = [
+ [t]
+ ];
+ alias = yss;
+ xss = alias;
+ }
+ }
+}
+
+void main() {
+ throws(() {
+ Class<A>().method2a(B());
+ print(xs.runtimeType); // 'List<A>'.
+ });
+ throws(() {
+ Class<A>().method2b(B());
+ print(xs.runtimeType); // 'List<A>'.
+ });
+}
+
+void errors() {
+ Class<A>().method1a(B());
+ Class<A>().method1b(B());
+}
+
+void throws(void Function() f) {
+ try {
+ f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw 'Expected throws';
+}
diff --git a/pkg/front_end/testcases/general/issue39344.dart.outline.expect b/pkg/front_end/testcases/general/issue39344.dart.outline.expect
new file mode 100644
index 0000000..18fa4de
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue39344.dart.outline.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ ;
+}
+class B extends self::A {
+ synthetic constructor •() → self::B*
+ ;
+}
+class Class<T extends self::A* = self::A*> extends core::Object {
+ synthetic constructor •() → self::Class<self::Class::T*>*
+ ;
+ method method1a(generic-covariant-impl self::Class::T* t) → void
+ ;
+ method method1b(generic-covariant-impl self::Class::T* t) → void
+ ;
+ method method2a(generic-covariant-impl self::Class::T* t) → void
+ ;
+ method method2b(generic-covariant-impl self::Class::T* t) → void
+ ;
+}
+static field core::List<self::B*>* xs;
+static field core::List<core::List<self::B*>*>* xss;
+static method main() → void
+ ;
+static method errors() → void
+ ;
+static method throws(() →* void f) → void
+ ;
diff --git a/pkg/front_end/testcases/general/issue39344.dart.strong.expect b/pkg/front_end/testcases/general/issue39344.dart.strong.expect
new file mode 100644
index 0000000..8c367fc
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue39344.dart.strong.expect
@@ -0,0 +1,96 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue39344.dart:19:12: Error: A value of type 'List<T>' can't be assigned to a variable of type 'List<B>'.
+// - 'List' is from 'dart:core'.
+// - 'B' is from 'pkg/front_end/testcases/general/issue39344.dart'.
+// xs = ys;
+// ^
+//
+// pkg/front_end/testcases/general/issue39344.dart:31:13: Error: A value of type 'List<List<T>>' can't be assigned to a variable of type 'List<List<B>>'.
+// - 'List' is from 'dart:core'.
+// - 'B' is from 'pkg/front_end/testcases/general/issue39344.dart'.
+// xss = yss;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+}
+class B extends self::A {
+ synthetic constructor •() → self::B*
+ : super self::A::•()
+ ;
+}
+class Class<T extends self::A* = self::A*> extends core::Object {
+ synthetic constructor •() → self::Class<self::Class::T*>*
+ : super core::Object::•()
+ ;
+ method method1a(generic-covariant-impl self::Class::T* t) → void {
+ if(t is self::B*) {
+ core::List<self::Class::T*>* ys = <self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}];
+ self::xs = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/issue39344.dart:19:12: Error: A value of type 'List<T>' can't be assigned to a variable of type 'List<B>'.
+ - 'List' is from 'dart:core'.
+ - 'B' is from 'pkg/front_end/testcases/general/issue39344.dart'.
+ xs = ys;
+ ^" in ys as{TypeError} core::List<self::B*>*;
+ }
+ }
+ method method1b(generic-covariant-impl self::Class::T* t) → void {
+ if(t is self::B*) {
+ core::List<core::List<self::Class::T*>*>* yss = <core::List<self::Class::T*>*>[<self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}]];
+ self::xss = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/issue39344.dart:31:13: Error: A value of type 'List<List<T>>' can't be assigned to a variable of type 'List<List<B>>'.
+ - 'List' is from 'dart:core'.
+ - 'B' is from 'pkg/front_end/testcases/general/issue39344.dart'.
+ xss = yss;
+ ^" in yss as{TypeError} core::List<core::List<self::B*>*>*;
+ }
+ }
+ method method2a(generic-covariant-impl self::Class::T* t) → void {
+ dynamic alias;
+ if(t is self::B*) {
+ core::List<self::Class::T*>* ys = <self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}];
+ alias = ys;
+ self::xs = alias as{TypeError} core::List<self::B*>*;
+ }
+ }
+ method method2b(generic-covariant-impl self::Class::T* t) → void {
+ dynamic alias;
+ if(t is self::B*) {
+ core::List<core::List<self::Class::T*>*>* yss = <core::List<self::Class::T*>*>[<self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}]];
+ alias = yss;
+ self::xss = alias as{TypeError} core::List<core::List<self::B*>*>*;
+ }
+ }
+}
+static field core::List<self::B*>* xs;
+static field core::List<core::List<self::B*>*>* xss;
+static method main() → void {
+ self::throws(() → core::Null? {
+ new self::Class::•<self::A*>().{self::Class::method2a}(new self::B::•());
+ core::print(self::xs.{core::Object::runtimeType});
+ });
+ self::throws(() → core::Null? {
+ new self::Class::•<self::A*>().{self::Class::method2b}(new self::B::•());
+ core::print(self::xs.{core::Object::runtimeType});
+ });
+}
+static method errors() → void {
+ new self::Class::•<self::A*>().{self::Class::method1a}(new self::B::•());
+ new self::Class::•<self::A*>().{self::Class::method1b}(new self::B::•());
+}
+static method throws(() →* void f) → void {
+ try {
+ f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "Expected throws";
+}
diff --git a/pkg/front_end/testcases/general/issue39344.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue39344.dart.strong.transformed.expect
new file mode 100644
index 0000000..8c367fc
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue39344.dart.strong.transformed.expect
@@ -0,0 +1,96 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue39344.dart:19:12: Error: A value of type 'List<T>' can't be assigned to a variable of type 'List<B>'.
+// - 'List' is from 'dart:core'.
+// - 'B' is from 'pkg/front_end/testcases/general/issue39344.dart'.
+// xs = ys;
+// ^
+//
+// pkg/front_end/testcases/general/issue39344.dart:31:13: Error: A value of type 'List<List<T>>' can't be assigned to a variable of type 'List<List<B>>'.
+// - 'List' is from 'dart:core'.
+// - 'B' is from 'pkg/front_end/testcases/general/issue39344.dart'.
+// xss = yss;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+}
+class B extends self::A {
+ synthetic constructor •() → self::B*
+ : super self::A::•()
+ ;
+}
+class Class<T extends self::A* = self::A*> extends core::Object {
+ synthetic constructor •() → self::Class<self::Class::T*>*
+ : super core::Object::•()
+ ;
+ method method1a(generic-covariant-impl self::Class::T* t) → void {
+ if(t is self::B*) {
+ core::List<self::Class::T*>* ys = <self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}];
+ self::xs = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/issue39344.dart:19:12: Error: A value of type 'List<T>' can't be assigned to a variable of type 'List<B>'.
+ - 'List' is from 'dart:core'.
+ - 'B' is from 'pkg/front_end/testcases/general/issue39344.dart'.
+ xs = ys;
+ ^" in ys as{TypeError} core::List<self::B*>*;
+ }
+ }
+ method method1b(generic-covariant-impl self::Class::T* t) → void {
+ if(t is self::B*) {
+ core::List<core::List<self::Class::T*>*>* yss = <core::List<self::Class::T*>*>[<self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}]];
+ self::xss = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/issue39344.dart:31:13: Error: A value of type 'List<List<T>>' can't be assigned to a variable of type 'List<List<B>>'.
+ - 'List' is from 'dart:core'.
+ - 'B' is from 'pkg/front_end/testcases/general/issue39344.dart'.
+ xss = yss;
+ ^" in yss as{TypeError} core::List<core::List<self::B*>*>*;
+ }
+ }
+ method method2a(generic-covariant-impl self::Class::T* t) → void {
+ dynamic alias;
+ if(t is self::B*) {
+ core::List<self::Class::T*>* ys = <self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}];
+ alias = ys;
+ self::xs = alias as{TypeError} core::List<self::B*>*;
+ }
+ }
+ method method2b(generic-covariant-impl self::Class::T* t) → void {
+ dynamic alias;
+ if(t is self::B*) {
+ core::List<core::List<self::Class::T*>*>* yss = <core::List<self::Class::T*>*>[<self::Class::T*>[t{self::Class::T* & self::B* /* '*' & '*' = '*' */}]];
+ alias = yss;
+ self::xss = alias as{TypeError} core::List<core::List<self::B*>*>*;
+ }
+ }
+}
+static field core::List<self::B*>* xs;
+static field core::List<core::List<self::B*>*>* xss;
+static method main() → void {
+ self::throws(() → core::Null? {
+ new self::Class::•<self::A*>().{self::Class::method2a}(new self::B::•());
+ core::print(self::xs.{core::Object::runtimeType});
+ });
+ self::throws(() → core::Null? {
+ new self::Class::•<self::A*>().{self::Class::method2b}(new self::B::•());
+ core::print(self::xs.{core::Object::runtimeType});
+ });
+}
+static method errors() → void {
+ new self::Class::•<self::A*>().{self::Class::method1a}(new self::B::•());
+ new self::Class::•<self::A*>().{self::Class::method1b}(new self::B::•());
+}
+static method throws(() →* void f) → void {
+ try {
+ f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "Expected throws";
+}
diff --git a/pkg/front_end/testcases/general/issue39421.dart b/pkg/front_end/testcases/general/issue39421.dart
new file mode 100644
index 0000000..e83ee28
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue39421.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+// This is a regression test for http://dartbug.com/39421.
+
+class A {}
+
+class A {}
+
+class B {
+ foo(List<Null> a) {}
+}
+
+class C extends B {
+ foo(List<A> a) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue39421.dart.outline.expect b/pkg/front_end/testcases/general/issue39421.dart.outline.expect
new file mode 100644
index 0000000..1987156
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue39421.dart.outline.expect
@@ -0,0 +1,52 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue39421.dart:9:7: Error: 'A' is already declared in this scope.
+// class A {}
+// ^
+// pkg/front_end/testcases/general/issue39421.dart:7:7: Context: Previous declaration of 'A'.
+// class A {}
+// ^
+//
+// pkg/front_end/testcases/general/issue39421.dart:16:12: Error: 'A' isn't a type.
+// foo(List<A> a) {}
+// ^
+// pkg/front_end/testcases/general/issue39421.dart:16:12: Context: This isn't a type.
+// foo(List<A> a) {}
+// ^
+//
+// pkg/front_end/testcases/general/issue39421.dart:16:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
+// - 'List' is from 'dart:core'.
+// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
+// foo(List<A> a) {}
+// ^
+// pkg/front_end/testcases/general/issue39421.dart:12:3: Context: This is the overridden method ('foo').
+// foo(List<Null> a) {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A#1 extends core::Object {
+ synthetic constructor •() → self::A#1*
+ ;
+}
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ ;
+}
+class B extends core::Object {
+ synthetic constructor •() → self::B*
+ ;
+ method foo(core::List<core::Null?>* a) → dynamic
+ ;
+}
+class C extends self::B {
+ synthetic constructor •() → self::C*
+ ;
+ method foo(core::List<invalid-type>* a) → dynamic
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/issue39421.dart.strong.expect b/pkg/front_end/testcases/general/issue39421.dart.strong.expect
new file mode 100644
index 0000000..6103be6
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue39421.dart.strong.expect
@@ -0,0 +1,57 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue39421.dart:9:7: Error: 'A' is already declared in this scope.
+// class A {}
+// ^
+// pkg/front_end/testcases/general/issue39421.dart:7:7: Context: Previous declaration of 'A'.
+// class A {}
+// ^
+//
+// pkg/front_end/testcases/general/issue39421.dart:16:12: Error: 'A' isn't a type.
+// foo(List<A> a) {}
+// ^
+// pkg/front_end/testcases/general/issue39421.dart:16:12: Context: This isn't a type.
+// foo(List<A> a) {}
+// ^
+//
+// pkg/front_end/testcases/general/issue39421.dart:16:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
+// - 'List' is from 'dart:core'.
+// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
+// foo(List<A> a) {}
+// ^
+// pkg/front_end/testcases/general/issue39421.dart:12:3: Context: This is the overridden method ('foo').
+// foo(List<Null> a) {}
+// ^
+//
+// pkg/front_end/testcases/general/issue39421.dart:16:12: Error: Can't use 'A' because it is declared more than once.
+// foo(List<A> a) {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A#1 extends core::Object {
+ synthetic constructor •() → self::A#1*
+ : super core::Object::•()
+ ;
+}
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+}
+class B extends core::Object {
+ synthetic constructor •() → self::B*
+ : super core::Object::•()
+ ;
+ method foo(core::List<core::Null?>* a) → dynamic {}
+}
+class C extends self::B {
+ synthetic constructor •() → self::C*
+ : super self::B::•()
+ ;
+ method foo(core::List<invalid-type>* a) → dynamic {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue39421.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue39421.dart.strong.transformed.expect
new file mode 100644
index 0000000..6103be6
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue39421.dart.strong.transformed.expect
@@ -0,0 +1,57 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue39421.dart:9:7: Error: 'A' is already declared in this scope.
+// class A {}
+// ^
+// pkg/front_end/testcases/general/issue39421.dart:7:7: Context: Previous declaration of 'A'.
+// class A {}
+// ^
+//
+// pkg/front_end/testcases/general/issue39421.dart:16:12: Error: 'A' isn't a type.
+// foo(List<A> a) {}
+// ^
+// pkg/front_end/testcases/general/issue39421.dart:16:12: Context: This isn't a type.
+// foo(List<A> a) {}
+// ^
+//
+// pkg/front_end/testcases/general/issue39421.dart:16:15: Error: The parameter 'a' of the method 'C.foo' has type 'List<invalid-type>', which does not match the corresponding type, 'List<Null>', in the overridden method, 'B.foo'.
+// - 'List' is from 'dart:core'.
+// Change to a supertype of 'List<Null>', or, for a covariant parameter, a subtype.
+// foo(List<A> a) {}
+// ^
+// pkg/front_end/testcases/general/issue39421.dart:12:3: Context: This is the overridden method ('foo').
+// foo(List<Null> a) {}
+// ^
+//
+// pkg/front_end/testcases/general/issue39421.dart:16:12: Error: Can't use 'A' because it is declared more than once.
+// foo(List<A> a) {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A#1 extends core::Object {
+ synthetic constructor •() → self::A#1*
+ : super core::Object::•()
+ ;
+}
+class A extends core::Object {
+ synthetic constructor •() → self::A*
+ : super core::Object::•()
+ ;
+}
+class B extends core::Object {
+ synthetic constructor •() → self::B*
+ : super core::Object::•()
+ ;
+ method foo(core::List<core::Null?>* a) → dynamic {}
+}
+class C extends self::B {
+ synthetic constructor •() → self::C*
+ : super self::B::•()
+ ;
+ method foo(core::List<invalid-type>* a) → dynamic {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect
index 3c5f989..4bcc6e9 100644
--- a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect
+++ b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect
@@ -175,7 +175,7 @@
// - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
// Try correcting the name to the name of an existing method, or defining a method named '[]'.
// print(foo[2]);
-// ^^
+// ^
//
// pkg/front_end/testcases/general/operator_method_not_found.dart:31:9: Error: The method '~' isn't defined for the class 'Foo'.
// - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
@@ -284,7 +284,7 @@
- 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
Try correcting the name to the name of an existing method, or defining a method named '[]'.
print(foo[2]);
- ^^");
+ ^");
core::print(invalid-expression "pkg/front_end/testcases/general/operator_method_not_found.dart:31:9: Error: The method '~' isn't defined for the class 'Foo'.
- 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
Try correcting the name to the name of an existing method, or defining a method named '~'.
diff --git a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect
index 3c5f989..4bcc6e9 100644
--- a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect
@@ -175,7 +175,7 @@
// - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
// Try correcting the name to the name of an existing method, or defining a method named '[]'.
// print(foo[2]);
-// ^^
+// ^
//
// pkg/front_end/testcases/general/operator_method_not_found.dart:31:9: Error: The method '~' isn't defined for the class 'Foo'.
// - 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
@@ -284,7 +284,7 @@
- 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
Try correcting the name to the name of an existing method, or defining a method named '[]'.
print(foo[2]);
- ^^");
+ ^");
core::print(invalid-expression "pkg/front_end/testcases/general/operator_method_not_found.dart:31:9: Error: The method '~' isn't defined for the class 'Foo'.
- 'Foo' is from 'pkg/front_end/testcases/general/operator_method_not_found.dart'.
Try correcting the name to the name of an existing method, or defining a method named '~'.
diff --git a/pkg/front_end/testcases/general/sdk_diagnostic.dart.outline.expect b/pkg/front_end/testcases/general/sdk_diagnostic.dart.outline.expect
index 50a933c..3f5874b 100644
--- a/pkg/front_end/testcases/general/sdk_diagnostic.dart.outline.expect
+++ b/pkg/front_end/testcases/general/sdk_diagnostic.dart.outline.expect
@@ -12,7 +12,7 @@
//
// class C extends Iterable<Object> {
// ^
-// sdk/lib/core/iterable.dart:154:19: Context: 'Iterable.iterator' is defined here.
+// sdk/lib/core/iterable.dart:156:19: Context: 'Iterable.iterator' is defined here.
// Iterator<E> get iterator;
// ^^^^^^^^
//
diff --git a/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.expect b/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.expect
index edca57d..80fbfff 100644
--- a/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.expect
+++ b/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.expect
@@ -12,14 +12,14 @@
//
// class C extends Iterable<Object> {
// ^
-// sdk/lib/core/iterable.dart:154:19: Context: 'Iterable.iterator' is defined here.
+// sdk/lib/core/iterable.dart:156:19: Context: 'Iterable.iterator' is defined here.
// Iterator<E> get iterator;
// ^^^^^^^^
//
// pkg/front_end/testcases/general/sdk_diagnostic.dart:12:8: Error: Too few positional arguments: 1 required, 0 given.
// print(incorrectArgument: "fisk");
// ^
-// sdk/lib/core/print.dart:8:6: Context: Found this candidate, but the arguments don't match.
+// sdk/lib/core/print.dart:10:6: Context: Found this candidate, but the arguments don't match.
// void print(Object object) {
// ^^^^^
//
diff --git a/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.transformed.expect b/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.transformed.expect
index edca57d..80fbfff 100644
--- a/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/sdk_diagnostic.dart.strong.transformed.expect
@@ -12,14 +12,14 @@
//
// class C extends Iterable<Object> {
// ^
-// sdk/lib/core/iterable.dart:154:19: Context: 'Iterable.iterator' is defined here.
+// sdk/lib/core/iterable.dart:156:19: Context: 'Iterable.iterator' is defined here.
// Iterator<E> get iterator;
// ^^^^^^^^
//
// pkg/front_end/testcases/general/sdk_diagnostic.dart:12:8: Error: Too few positional arguments: 1 required, 0 given.
// print(incorrectArgument: "fisk");
// ^
-// sdk/lib/core/print.dart:8:6: Context: Found this candidate, but the arguments don't match.
+// sdk/lib/core/print.dart:10:6: Context: Found this candidate, but the arguments don't match.
// void print(Object object) {
// ^^^^^
//
diff --git a/pkg/front_end/testcases/general/unsound_promotion.dart.strong.expect b/pkg/front_end/testcases/general/unsound_promotion.dart.strong.expect
index 7251f88..cb3e61b 100644
--- a/pkg/front_end/testcases/general/unsound_promotion.dart.strong.expect
+++ b/pkg/front_end/testcases/general/unsound_promotion.dart.strong.expect
@@ -2,11 +2,14 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/general/unsound_promotion.dart:21:16: Error: Can't infer a type for 'T', it can be either 'S' or 'A'.
+// pkg/front_end/testcases/general/unsound_promotion.dart:21:16: Error: Inferred type argument 'S' doesn't conform to the bound 'A' of the type variable 'T' on 'g'.
// - 'A' is from 'pkg/front_end/testcases/general/unsound_promotion.dart'.
-// Try adding a type argument selecting one of the options.
+// Try specifying type arguments explicitly so that they conform to the bounds.
// var list = g(s);
// ^
+// pkg/front_end/testcases/general/unsound_promotion.dart:13:11: Context: This is the type variable whose bound isn't conformed to.
+// List<T> g<T extends A>(T t) {
+// ^
//
import self as self;
import "dart:core" as core;
@@ -34,7 +37,7 @@
}
static method f<S extends core::Object* = dynamic>(self::f::S* s) → core::List<self::f::S*>* {
if(s is self::A*) {
- core::List<self::f::S* & self::A* /* '*' & '*' = '*' */>* list = self::g<self::f::S* & self::A* /* '*' & '*' = '*' */>(s{self::f::S* & self::A* /* '*' & '*' = '*' */});
+ core::List<self::f::S*>* list = self::g<self::f::S*>(s{self::f::S* & self::A* /* '*' & '*' = '*' */});
return list;
}
return null;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect
index 69ca563..10227fc 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/crash_test_1.yaml.world.1.expect
@@ -35,7 +35,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml
index d3fe395..0c6b1b9 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_1.yaml
@@ -7,6 +7,7 @@
type: newworld
worlds:
- entry: actualMain.dart
+ useExperimentalInvalidation: true
sources:
actualMain.dart: |
import 'main.dart' as m;
@@ -36,6 +37,7 @@
}
expectedLibraryCount: 4
- entry: actualMain.dart
+ useExperimentalInvalidation: true
worldType: updated
expectInitializeFromDill: false
invalidate:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml
index e9a82b1..a8367f4 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml
@@ -7,6 +7,7 @@
type: newworld
worlds:
- entry: main.dart
+ useExperimentalInvalidation: true
sources:
main.dart: |
import 'libA.dart';
@@ -33,6 +34,7 @@
}
expectedLibraryCount: 2
- entry: main.dart
+ useExperimentalInvalidation: true
worldType: updated
expectInitializeFromDill: false
invalidate:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml
index 4ba8586..4465423 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml
@@ -7,6 +7,7 @@
type: newworld
worlds:
- entry: main.dart
+ useExperimentalInvalidation: true
sources:
main.dart: |
import 'libA.dart';
@@ -28,6 +29,7 @@
}
expectedLibraryCount: 2
- entry: main.dart
+ useExperimentalInvalidation: true
worldType: updated
expectInitializeFromDill: false
invalidate:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect
index 7a4295d..91e8487 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.1.expect
@@ -7,7 +7,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -15,7 +15,7 @@
#L1:
{
[yield] let dynamic #t1 = dart.async::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
- :result;
+ dart._internal::unsafeCast<dart.core::Null?>(:result);
:return_value = "hello";
break #L1;
}
@@ -50,7 +50,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect
index 42e02f0..b5437cc 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_3.yaml.world.2.expect
@@ -7,7 +7,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -15,7 +15,7 @@
#L1:
{
[yield] let dynamic #t1 = dart.async::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
- :result;
+ dart._internal::unsafeCast<dart.core::Null?>(:result);
:return_value = "hello";
break #L1;
}
@@ -50,7 +50,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml
index 554f242..4c12698 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_4.yaml
@@ -8,6 +8,7 @@
type: newworld
worlds:
- entry: main.dart
+ useExperimentalInvalidation: true
sources:
main.dart: |
import 'libA.dart';
@@ -27,6 +28,7 @@
}
expectedLibraryCount: 2
- entry: main.dart
+ useExperimentalInvalidation: true
worldType: updated
expectInitializeFromDill: false
invalidate:
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml
new file mode 100644
index 0000000..02c6454
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml
@@ -0,0 +1,47 @@
+# Copyright (c) 2019, 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.md file.
+
+# Compile an application with a part, change a file,
+# but don't change the outline.
+
+type: newworld
+worlds:
+ - entry: main.dart
+ useExperimentalInvalidation: true
+ sources:
+ main.dart: |
+ part 'myPart.dart';
+
+ class Foo {
+ const Foo();
+ @override
+ toString() => 'Foo!';
+ }
+
+ main() async {
+ await whatever();
+ print(const Foo());
+ }
+ myPart.dart: |
+ part of 'main.dart';
+ whatever() async {
+ await null;
+ return "hello";
+ }
+ expectedLibraryCount: 1
+ - entry: main.dart
+ useExperimentalInvalidation: true
+ worldType: updated
+ expectInitializeFromDill: false
+ invalidate:
+ - myPart.dart
+ sources:
+ myPart.dart: |
+ part of 'main.dart';
+ whatever() async {
+ await null;
+ return "hello!!!";
+ }
+ expectedLibraryCount: 1
+ expectsRebuildBodiesOnly: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.1.expect
new file mode 100644
index 0000000..164275c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.1.expect
@@ -0,0 +1,76 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+ part myPart.dart;
+ class Foo extends dart.core::Object {
+ const constructor •() → main::Foo*
+ : super dart.core::Object::•()
+ ;
+ @#C1
+ method toString() → dart.core::String*
+ return "Foo!";
+ }
+ static method main() → dynamic /* originally async */ {
+ final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+ dart.async::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dart.core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ [yield] let dynamic #t1 = dart.async::_awaitHelper(main::whatever(), :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ dart.core::print(#C2);
+ }
+ dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+ :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{dart.async::Completer::future};
+ }
+ static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
+ final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+ dart.async::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dart.core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ [yield] let dynamic #t2 = dart.async::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
+ dart._internal::unsafeCast<dart.core::Null?>(:result);
+ :return_value = "hello";
+ break #L2;
+ }
+ dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+ :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{dart.async::Completer::future};
+ }
+}
+constants {
+ #C1 = dart.core::_Override {}
+ #C2 = main::Foo {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.2.expect
new file mode 100644
index 0000000..eda5685
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_5.yaml.world.2.expect
@@ -0,0 +1,76 @@
+main = <No Member>;
+library from "org-dartlang-test:///main.dart" as main {
+
+ part myPart.dart;
+ class Foo extends dart.core::Object {
+ const constructor •() → main::Foo*
+ : super dart.core::Object::•()
+ ;
+ @#C1
+ method toString() → dart.core::String*
+ return "Foo!";
+ }
+ static method main() → dynamic /* originally async */ {
+ final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+ dart.async::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dart.core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L1:
+ {
+ [yield] let dynamic #t1 = dart.async::_awaitHelper(main::whatever(), :async_op_then, :async_op_error, :async_op) in null;
+ :result;
+ dart.core::print(#C2);
+ }
+ dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+ :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{dart.async::Completer::future};
+ }
+ static method /* from org-dartlang-test:///myPart.dart */ whatever() → dynamic /* originally async */ {
+ final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+ dart.async::FutureOr<dynamic>* :return_value;
+ dynamic :async_stack_trace;
+ dynamic :async_op_then;
+ dynamic :async_op_error;
+ dart.core::int* :await_jump_var = 0;
+ dynamic :await_ctx_var;
+ dynamic :saved_try_context_var0;
+ function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
+ try {
+ #L2:
+ {
+ [yield] let dynamic #t2 = dart.async::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
+ dart._internal::unsafeCast<dart.core::Null?>(:result);
+ :return_value = "hello!!!";
+ break #L2;
+ }
+ dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+ return;
+ }
+ on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+ :async_completer.{dart.async::Completer::completeError}(:exception, :stack_trace);
+ }
+ :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+ :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+ :async_completer.start(:async_op);
+ return :async_completer.{dart.async::Completer::future};
+ }
+}
+constants {
+ #C1 = dart.core::_Override {}
+ #C2 = main::Foo {}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml
new file mode 100644
index 0000000..8aa50fc
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml
@@ -0,0 +1,91 @@
+# Copyright (c) 2019, 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.md file.
+
+# Compile an application, change a file, but don't change the outline.
+
+type: newworld
+worlds:
+ - entry: main.dart
+ useExperimentalInvalidation: true
+ errors: true
+ sources:
+ main.dart: |
+ import 'libA.dart';
+
+ class Foo {
+ final message;
+ Foo(this.message);
+ @override
+ toString() { return '$message' } // missing ;
+ }
+
+ main() {
+ Foo foo = new Foo("hello");
+ whatever(foo);
+ CompilationStrategy compilationStrategy = CompilationStrategy.direct;
+ print(compilationStrategy);
+ }
+
+ enum CompilationStrategy { direct, toKernel, toData, fromData }
+ libA.dart: |
+ import 'main.dart';
+ whatever(Foo foo) {
+ print(foo);
+ }
+ expectedLibraryCount: 2
+ - entry: main.dart
+ useExperimentalInvalidation: true
+ errors: true
+ worldType: updated
+ expectInitializeFromDill: false
+ invalidate:
+ - main.dart
+ sources:
+ main.dart: |
+ import 'libA.dart';
+
+ class Foo {
+ final message;
+ Foo(this.message);
+ @override
+ toString() { return '$message!!!' } // missing ; still
+ }
+
+ main() {
+ Foo foo = new Foo("hello");
+ whatever(foo);
+ CompilationStrategy compilationStrategy = CompilationStrategy.direct;
+ print(compilationStrategy);
+ }
+
+ enum CompilationStrategy { direct, toKernel, toData, fromData }
+ expectedLibraryCount: 2
+ expectsRebuildBodiesOnly: true
+ - entry: main.dart
+ useExperimentalInvalidation: true
+ worldType: updated
+ expectInitializeFromDill: false
+ invalidate:
+ - main.dart
+ sources:
+ main.dart: |
+ import 'libA.dart';
+
+ class Foo {
+ final message;
+ Foo(this.message);
+ @override
+ toString() { return '$message?!?'; } // fixed
+ }
+
+ main() {
+ Foo foo = new Foo("hello");
+ whatever(foo);
+ CompilationStrategy compilationStrategy = CompilationStrategy.direct;
+ print(compilationStrategy);
+ }
+
+ enum CompilationStrategy { direct, toKernel, toData, fromData }
+ expectedLibraryCount: 2
+ expectsRebuildBodiesOnly: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect
new file mode 100644
index 0000000..db672db
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect
@@ -0,0 +1,67 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+ import "org-dartlang-test:///main.dart";
+
+ static method whatever(main::Foo* foo) → dynamic {
+ dart.core::print(foo);
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:7:32: Error: Expected ';' after this.
+// toString() { return '$message' } // missing ;
+// ^
+//
+
+ import "org-dartlang-test:///libA.dart";
+
+ class Foo extends dart.core::Object {
+ final field dynamic message;
+ constructor •(dynamic message) → main::Foo*
+ : main::Foo::message = message, super dart.core::Object::•()
+ ;
+ @#C1
+ method toString() → dart.core::String* {
+ return "${this.{main::Foo::message}}";
+ }
+ }
+ class CompilationStrategy extends dart.core::Object {
+ final field dart.core::int* index;
+ final field dart.core::String* _name;
+ static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
+ static const field main::CompilationStrategy* direct = #C4;
+ static const field main::CompilationStrategy* toKernel = #C7;
+ static const field main::CompilationStrategy* toData = #C10;
+ static const field main::CompilationStrategy* fromData = #C13;
+ const constructor •(dart.core::int* index, dart.core::String* _name) → main::CompilationStrategy*
+ : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
+ ;
+ method toString() → dart.core::String*
+ return this.{=main::CompilationStrategy::_name};
+ }
+ static method main() → dynamic {
+ main::Foo* foo = new main::Foo::•("hello");
+ libA::whatever(foo);
+ main::CompilationStrategy* compilationStrategy = #C4;
+ dart.core::print(compilationStrategy);
+ }
+}
+constants {
+ #C1 = dart.core::_Override {}
+ #C2 = 0
+ #C3 = "CompilationStrategy.direct"
+ #C4 = main::CompilationStrategy {index:#C2, _name:#C3}
+ #C5 = 1
+ #C6 = "CompilationStrategy.toKernel"
+ #C7 = main::CompilationStrategy {index:#C5, _name:#C6}
+ #C8 = 2
+ #C9 = "CompilationStrategy.toData"
+ #C10 = main::CompilationStrategy {index:#C8, _name:#C9}
+ #C11 = 3
+ #C12 = "CompilationStrategy.fromData"
+ #C13 = main::CompilationStrategy {index:#C11, _name:#C12}
+ #C14 = <main::CompilationStrategy*>[#C4, #C7, #C10, #C13]
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect
new file mode 100644
index 0000000..efb24e4
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect
@@ -0,0 +1,67 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+ import "org-dartlang-test:///main.dart";
+
+ static method whatever(main::Foo* foo) → dynamic {
+ dart.core::print(foo);
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:7:32: Error: Expected ';' after this.
+// toString() { return '$message!!!' } // missing ; still
+// ^^^^
+//
+
+ import "org-dartlang-test:///libA.dart";
+
+ class Foo extends dart.core::Object {
+ final field dynamic message;
+ constructor •(dynamic message) → main::Foo*
+ : main::Foo::message = message, super dart.core::Object::•()
+ ;
+ @#C1
+ method toString() → dart.core::String* {
+ return "${this.{main::Foo::message}}!!!";
+ }
+ }
+ class CompilationStrategy extends dart.core::Object {
+ final field dart.core::int* index;
+ final field dart.core::String* _name;
+ static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
+ static const field main::CompilationStrategy* direct = #C4;
+ static const field main::CompilationStrategy* toKernel = #C7;
+ static const field main::CompilationStrategy* toData = #C10;
+ static const field main::CompilationStrategy* fromData = #C13;
+ const constructor •(dart.core::int* index, dart.core::String* _name) → main::CompilationStrategy*
+ : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
+ ;
+ method toString() → dart.core::String*
+ return this.{=main::CompilationStrategy::_name};
+ }
+ static method main() → dynamic {
+ main::Foo* foo = new main::Foo::•("hello");
+ libA::whatever(foo);
+ main::CompilationStrategy* compilationStrategy = #C4;
+ dart.core::print(compilationStrategy);
+ }
+}
+constants {
+ #C1 = dart.core::_Override {}
+ #C2 = 0
+ #C3 = "CompilationStrategy.direct"
+ #C4 = main::CompilationStrategy {index:#C2, _name:#C3}
+ #C5 = 1
+ #C6 = "CompilationStrategy.toKernel"
+ #C7 = main::CompilationStrategy {index:#C5, _name:#C6}
+ #C8 = 2
+ #C9 = "CompilationStrategy.toData"
+ #C10 = main::CompilationStrategy {index:#C8, _name:#C9}
+ #C11 = 3
+ #C12 = "CompilationStrategy.fromData"
+ #C13 = main::CompilationStrategy {index:#C11, _name:#C12}
+ #C14 = <main::CompilationStrategy*>[#C4, #C7, #C10, #C13]
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect
new file mode 100644
index 0000000..6872d26
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect
@@ -0,0 +1,60 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+ import "org-dartlang-test:///main.dart";
+
+ static method whatever(main::Foo* foo) → dynamic {
+ dart.core::print(foo);
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///libA.dart";
+
+ class Foo extends dart.core::Object {
+ final field dynamic message;
+ constructor •(dynamic message) → main::Foo*
+ : main::Foo::message = message, super dart.core::Object::•()
+ ;
+ @#C1
+ method toString() → dart.core::String* {
+ return "${this.{main::Foo::message}}?!?";
+ }
+ }
+ class CompilationStrategy extends dart.core::Object {
+ final field dart.core::int* index;
+ final field dart.core::String* _name;
+ static const field dart.core::List<main::CompilationStrategy*>* values = #C14;
+ static const field main::CompilationStrategy* direct = #C4;
+ static const field main::CompilationStrategy* toKernel = #C7;
+ static const field main::CompilationStrategy* toData = #C10;
+ static const field main::CompilationStrategy* fromData = #C13;
+ const constructor •(dart.core::int* index, dart.core::String* _name) → main::CompilationStrategy*
+ : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
+ ;
+ method toString() → dart.core::String*
+ return this.{=main::CompilationStrategy::_name};
+ }
+ static method main() → dynamic {
+ main::Foo* foo = new main::Foo::•("hello");
+ libA::whatever(foo);
+ main::CompilationStrategy* compilationStrategy = #C4;
+ dart.core::print(compilationStrategy);
+ }
+}
+constants {
+ #C1 = dart.core::_Override {}
+ #C2 = 0
+ #C3 = "CompilationStrategy.direct"
+ #C4 = main::CompilationStrategy {index:#C2, _name:#C3}
+ #C5 = 1
+ #C6 = "CompilationStrategy.toKernel"
+ #C7 = main::CompilationStrategy {index:#C5, _name:#C6}
+ #C8 = 2
+ #C9 = "CompilationStrategy.toData"
+ #C10 = main::CompilationStrategy {index:#C8, _name:#C9}
+ #C11 = 3
+ #C12 = "CompilationStrategy.fromData"
+ #C13 = main::CompilationStrategy {index:#C11, _name:#C12}
+ #C14 = <main::CompilationStrategy*>[#C4, #C7, #C10, #C13]
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml
new file mode 100644
index 0000000..701c6a7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml
@@ -0,0 +1,93 @@
+# Copyright (c) 2019, 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.md file.
+
+# Compile an application, change a file, but don't change the outline.
+
+type: newworld
+worlds:
+ - entry: main.dart
+ useExperimentalInvalidation: true
+ sources:
+ main.dart: |
+ import 'libA.dart';
+
+ const String useMeAsAnnotation = "hello";
+
+ @useMeAsAnnotation
+ class Bar {
+ @useMeAsAnnotation
+ Bar(@useMeAsAnnotation int x) {}
+ }
+
+ @useMeAsAnnotation
+ class Foo extends Bar {
+ @useMeAsAnnotation
+ final message;
+ @useMeAsAnnotation
+ Foo(@useMeAsAnnotation this.message) : super(42);
+ @override
+ toString() { return '$message'; }
+ }
+
+ @useMeAsAnnotation
+ main() {
+ @useMeAsAnnotation
+ Foo foo = new Foo("hello");
+ whatever(foo);
+ @useMeAsAnnotation
+ CompilationStrategy compilationStrategy = CompilationStrategy.direct;
+ print(compilationStrategy);
+ }
+
+ @useMeAsAnnotation
+ enum CompilationStrategy { @useMeAsAnnotation direct, @useMeAsAnnotation toKernel, @useMeAsAnnotation toData, @useMeAsAnnotation fromData }
+ libA.dart: |
+ import 'main.dart';
+ @useMeAsAnnotation
+ whatever(Foo foo) {
+ print(foo);
+ }
+ expectedLibraryCount: 2
+ - entry: main.dart
+ useExperimentalInvalidation: true
+ worldType: updated
+ expectInitializeFromDill: false
+ invalidate:
+ - main.dart
+ sources:
+ main.dart: |
+ import 'libA.dart';
+
+ const String useMeAsAnnotation = "hello";
+
+ @useMeAsAnnotation
+ class Bar {
+ @useMeAsAnnotation
+ Bar(@useMeAsAnnotation int x) {}
+ }
+
+ @useMeAsAnnotation
+ class Foo extends Bar {
+ @useMeAsAnnotation
+ final message;
+ @useMeAsAnnotation
+ Foo(@useMeAsAnnotation this.message) : super(42);
+ @override
+ toString() { return '$message'; }
+ }
+
+ @useMeAsAnnotation
+ main() {
+ @useMeAsAnnotation
+ Foo foo = new Foo("hello");
+ whatever(foo);
+ @useMeAsAnnotation
+ CompilationStrategy compilationStrategy = CompilationStrategy.direct;
+ print(compilationStrategy);
+ }
+
+ @useMeAsAnnotation
+ enum CompilationStrategy { @useMeAsAnnotation direct, @useMeAsAnnotation toKernel, @useMeAsAnnotation toData, @useMeAsAnnotation fromData }
+ expectedLibraryCount: 2
+ expectsRebuildBodiesOnly: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect
new file mode 100644
index 0000000..05b87bb
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect
@@ -0,0 +1,78 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+ import "org-dartlang-test:///main.dart";
+
+ @#C1
+ static method whatever(main::Foo* foo) → dynamic {
+ dart.core::print(foo);
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///libA.dart";
+
+ @#C1
+ class Bar extends dart.core::Object {
+ @#C1
+ constructor •(@#C1 dart.core::int* x) → main::Bar*
+ : super dart.core::Object::•() {}
+ }
+ @#C1
+ class Foo extends main::Bar {
+ @#C1
+ final field dynamic message;
+ @#C1
+ constructor •(@#C1 dynamic message) → main::Foo*
+ : main::Foo::message = message, super main::Bar::•(42)
+ ;
+ @#C2
+ method toString() → dart.core::String* {
+ return "${this.{main::Foo::message}}";
+ }
+ }
+ @#C1
+ class CompilationStrategy extends dart.core::Object {
+ final field dart.core::int* index;
+ final field dart.core::String* _name;
+ static const field dart.core::List<main::CompilationStrategy*>* values = #C15;
+ @#C1
+ static const field main::CompilationStrategy* direct = #C5;
+ @#C1
+ static const field main::CompilationStrategy* toKernel = #C8;
+ @#C1
+ static const field main::CompilationStrategy* toData = #C11;
+ @#C1
+ static const field main::CompilationStrategy* fromData = #C14;
+ const constructor •(dart.core::int* index, dart.core::String* _name) → main::CompilationStrategy*
+ : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
+ ;
+ method toString() → dart.core::String*
+ return this.{=main::CompilationStrategy::_name};
+ }
+ static const field dart.core::String* useMeAsAnnotation = #C1;
+ @#C1
+ static method main() → dynamic {
+ @#C1 main::Foo* foo = new main::Foo::•("hello");
+ libA::whatever(foo);
+ @#C1 main::CompilationStrategy* compilationStrategy = #C5;
+ dart.core::print(compilationStrategy);
+ }
+}
+constants {
+ #C1 = "hello"
+ #C2 = dart.core::_Override {}
+ #C3 = 0
+ #C4 = "CompilationStrategy.direct"
+ #C5 = main::CompilationStrategy {index:#C3, _name:#C4}
+ #C6 = 1
+ #C7 = "CompilationStrategy.toKernel"
+ #C8 = main::CompilationStrategy {index:#C6, _name:#C7}
+ #C9 = 2
+ #C10 = "CompilationStrategy.toData"
+ #C11 = main::CompilationStrategy {index:#C9, _name:#C10}
+ #C12 = 3
+ #C13 = "CompilationStrategy.fromData"
+ #C14 = main::CompilationStrategy {index:#C12, _name:#C13}
+ #C15 = <main::CompilationStrategy*>[#C5, #C8, #C11, #C14]
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect
new file mode 100644
index 0000000..05b87bb
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect
@@ -0,0 +1,78 @@
+main = <No Member>;
+library from "org-dartlang-test:///libA.dart" as libA {
+
+ import "org-dartlang-test:///main.dart";
+
+ @#C1
+ static method whatever(main::Foo* foo) → dynamic {
+ dart.core::print(foo);
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///libA.dart";
+
+ @#C1
+ class Bar extends dart.core::Object {
+ @#C1
+ constructor •(@#C1 dart.core::int* x) → main::Bar*
+ : super dart.core::Object::•() {}
+ }
+ @#C1
+ class Foo extends main::Bar {
+ @#C1
+ final field dynamic message;
+ @#C1
+ constructor •(@#C1 dynamic message) → main::Foo*
+ : main::Foo::message = message, super main::Bar::•(42)
+ ;
+ @#C2
+ method toString() → dart.core::String* {
+ return "${this.{main::Foo::message}}";
+ }
+ }
+ @#C1
+ class CompilationStrategy extends dart.core::Object {
+ final field dart.core::int* index;
+ final field dart.core::String* _name;
+ static const field dart.core::List<main::CompilationStrategy*>* values = #C15;
+ @#C1
+ static const field main::CompilationStrategy* direct = #C5;
+ @#C1
+ static const field main::CompilationStrategy* toKernel = #C8;
+ @#C1
+ static const field main::CompilationStrategy* toData = #C11;
+ @#C1
+ static const field main::CompilationStrategy* fromData = #C14;
+ const constructor •(dart.core::int* index, dart.core::String* _name) → main::CompilationStrategy*
+ : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
+ ;
+ method toString() → dart.core::String*
+ return this.{=main::CompilationStrategy::_name};
+ }
+ static const field dart.core::String* useMeAsAnnotation = #C1;
+ @#C1
+ static method main() → dynamic {
+ @#C1 main::Foo* foo = new main::Foo::•("hello");
+ libA::whatever(foo);
+ @#C1 main::CompilationStrategy* compilationStrategy = #C5;
+ dart.core::print(compilationStrategy);
+ }
+}
+constants {
+ #C1 = "hello"
+ #C2 = dart.core::_Override {}
+ #C3 = 0
+ #C4 = "CompilationStrategy.direct"
+ #C5 = main::CompilationStrategy {index:#C3, _name:#C4}
+ #C6 = 1
+ #C7 = "CompilationStrategy.toKernel"
+ #C8 = main::CompilationStrategy {index:#C6, _name:#C7}
+ #C9 = 2
+ #C10 = "CompilationStrategy.toData"
+ #C11 = main::CompilationStrategy {index:#C9, _name:#C10}
+ #C12 = 3
+ #C13 = "CompilationStrategy.fromData"
+ #C14 = main::CompilationStrategy {index:#C12, _name:#C13}
+ #C15 = <main::CompilationStrategy*>[#C5, #C8, #C11, #C14]
+}
diff --git a/pkg/front_end/testcases/inference/async_await.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/async_await.dart.strong.transformed.expect
index 07361ac..ecb9078 100644
--- a/pkg/front_end/testcases/inference/async_await.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_await.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -16,7 +17,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -39,7 +40,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -66,7 +67,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -93,7 +94,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -120,7 +121,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -147,7 +148,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -174,7 +175,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -201,7 +202,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -228,7 +229,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -255,7 +256,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -282,7 +283,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -304,25 +305,25 @@
return :async_completer.{asy::Completer::future};
}
[yield] let dynamic #t1 = asy::_awaitHelper(x0, :async_op_then, :async_op_error, :async_op) in null;
- core::int* y0 = :result;
+ core::int* y0 = _in::unsafeCast<core::int*>(:result);
[yield] let dynamic #t2 = asy::_awaitHelper(x1, :async_op_then, :async_op_error, :async_op) in null;
- core::int* y1 = :result;
+ core::int* y1 = _in::unsafeCast<core::int*>(:result);
[yield] let dynamic #t3 = asy::_awaitHelper(x2, :async_op_then, :async_op_error, :async_op) in null;
- asy::Future<core::int*>* y2 = :result;
+ asy::Future<core::int*>* y2 = _in::unsafeCast<asy::Future<core::int*>*>(:result);
[yield] let dynamic #t4 = asy::_awaitHelper(x3, :async_op_then, :async_op_error, :async_op) in null;
- asy::FutureOr<core::int*>* y3 = :result;
+ asy::FutureOr<core::int*>* y3 = _in::unsafeCast<asy::FutureOr<core::int*>*>(:result);
[yield] let dynamic #t5 = asy::_awaitHelper(x4, :async_op_then, :async_op_error, :async_op) in null;
- self::MyFuture* y4 = :result;
+ self::MyFuture* y4 = _in::unsafeCast<self::MyFuture*>(:result);
[yield] let dynamic #t6 = asy::_awaitHelper(x5, :async_op_then, :async_op_error, :async_op) in null;
- core::int* y5 = :result;
+ core::int* y5 = _in::unsafeCast<core::int*>(:result);
[yield] let dynamic #t7 = asy::_awaitHelper(x6, :async_op_then, :async_op_error, :async_op) in null;
- asy::Future<core::int*>* y6 = :result;
+ asy::Future<core::int*>* y6 = _in::unsafeCast<asy::Future<core::int*>*>(:result);
[yield] let dynamic #t8 = asy::_awaitHelper(x7, :async_op_then, :async_op_error, :async_op) in null;
- asy::FutureOr<core::int*>* y7 = :result;
+ asy::FutureOr<core::int*>* y7 = _in::unsafeCast<asy::FutureOr<core::int*>*>(:result);
[yield] let dynamic #t9 = asy::_awaitHelper(x8, :async_op_then, :async_op_error, :async_op) in null;
- self::MyFuture* y8 = :result;
+ self::MyFuture* y8 = _in::unsafeCast<self::MyFuture*>(:result);
[yield] let dynamic #t10 = asy::_awaitHelper(x9, :async_op_then, :async_op_error, :async_op) in null;
- core::int* y9 = :result;
+ core::int* y9 = _in::unsafeCast<core::int*>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.strong.transformed.expect
index 2345aff..c587b4b 100644
--- a/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_closure_return_type_flatten.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.strong.transformed.expect
index 63abde7..69a4666 100644
--- a/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_closure_return_type_future.dart.strong.transformed.expect
@@ -9,7 +9,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.strong.transformed.expect
index 18510a2..13ab2d2 100644
--- a/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_closure_return_type_future_or.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.strong.transformed.expect
index 0ee4ee6..461478b 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_futures.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.strong.transformed.expect
index 4c207d0..6675875 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_all_returns_are_values.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.strong.transformed.expect
index 456e45d..83d4912 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_mix_of_values_and_futures.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.strong.transformed.expect
index 360b2cd..c640de2 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_async_star.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect
index e8faa37..72c0762 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
import "dart:async";
@@ -11,7 +12,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -24,7 +25,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -48,7 +49,7 @@
asy::Future<dynamic>* y = f.call();
asy::Future<core::String*>* z = f.call();
[yield] let dynamic #t1 = asy::_awaitHelper(f.call(), :async_op_then, :async_op_error, :async_op) in null;
- core::String* s = :result;
+ core::String* s = _in::unsafeCast<core::Null?>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect
index ae912fe..c810580 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_async_star.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
import "dart:async";
@@ -11,7 +12,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -24,7 +25,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -56,7 +57,7 @@
asy::Stream<dynamic>* y = f.call();
asy::Stream<core::String*>* z = f.call();
[yield] let dynamic #t1 = asy::_awaitHelper(f.call().{asy::Stream::first}, :async_op_then, :async_op_error, :async_op) in null;
- core::String* s = :result;
+ core::String* s = _in::unsafeCast<core::Null?>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.transformed.expect
index f94cf54..9a2c1650 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_infer_bottom_sync_star.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
static method main() → dynamic {
() →* core::Iterable<core::Null?>* f = () → core::Iterable<core::Null?>* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<core::Null?>* :iterator) → core::bool* yielding {
{
diff --git a/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.strong.transformed.expect
index f8df559..90b9e1e 100644
--- a/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/block_bodied_lambdas_sync_star.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
static method test() → dynamic {
() →* core::Iterable<core::num*>* f = () → core::Iterable<core::num*>* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<core::num*>* :iterator) → core::bool* yielding {
{
diff --git a/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.expect b/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.expect
index c3a99bc..f5dbe06 100644
--- a/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.expect
@@ -42,11 +42,11 @@
core::int* callA = new self::A::•().{self::A::call}();
core::int* callFieldA = new self::D::•().{self::D::fieldA}();
core::int* callGetA = new self::D::•().{self::D::getA}();
- dynamic callFieldB = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:27:71: Error: 'fieldB' isn't a function or method and can't be invoked.
+ dynamic callFieldB = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:27:71: Error: 'fieldB' isn't a function or method and can't be invoked.
var /*@ type=dynamic */ callFieldB = new D(). /*@target=D::fieldB*/ fieldB();
- ^" in new self::D::•().{self::D::fieldB}();
- dynamic callGetB = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:28:67: Error: 'getB' isn't a function or method and can't be invoked.
+ ^";
+ dynamic callGetB = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:28:67: Error: 'getB' isn't a function or method and can't be invoked.
var /*@ type=dynamic */ callGetB = new D(). /*@target=D::getB*/ getB();
- ^" in new self::D::•().{self::D::getB}();
+ ^";
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.transformed.expect
index c3a99bc..f5dbe06 100644
--- a/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.transformed.expect
@@ -42,11 +42,11 @@
core::int* callA = new self::A::•().{self::A::call}();
core::int* callFieldA = new self::D::•().{self::D::fieldA}();
core::int* callGetA = new self::D::•().{self::D::getA}();
- dynamic callFieldB = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:27:71: Error: 'fieldB' isn't a function or method and can't be invoked.
+ dynamic callFieldB = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:27:71: Error: 'fieldB' isn't a function or method and can't be invoked.
var /*@ type=dynamic */ callFieldB = new D(). /*@target=D::fieldB*/ fieldB();
- ^" in new self::D::•().{self::D::fieldB}();
- dynamic callGetB = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:28:67: Error: 'getB' isn't a function or method and can't be invoked.
+ ^";
+ dynamic callGetB = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:28:67: Error: 'getB' isn't a function or method and can't be invoked.
var /*@ type=dynamic */ callGetB = new D(). /*@target=D::getB*/ getB();
- ^" in new self::D::•().{self::D::getB}();
+ ^";
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect
index bc89d37..947d113 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_async_await.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
import "dart:async";
@@ -11,7 +12,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -20,9 +21,9 @@
{
dynamic d;
[yield] let dynamic #t1 = asy::_awaitHelper(<core::int*>[d as{TypeError} core::int*], :async_op_then, :async_op_error, :async_op) in null;
- core::List<core::int*>* l0 = :result;
+ core::List<core::int*>* l0 = _in::unsafeCast<core::List<core::int*>*>(:result);
[yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::List<core::int*>*>(<core::int*>[d as{TypeError} core::int*]), :async_op_then, :async_op_error, :async_op) in null;
- core::List<core::int*>* l1 = :result;
+ core::List<core::int*>* l1 = _in::unsafeCast<core::List<core::int*>*>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect
index c9450cf..95bdb47 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_for_each.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -17,7 +18,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -50,7 +51,7 @@
while (true) {
dynamic #t3 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t4 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
dynamic x = :for-iterator.{asy::_StreamIterator::current};
{}
}
@@ -72,7 +73,7 @@
while (true) {
dynamic #t6 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t7 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
dynamic x = :for-iterator.{asy::_StreamIterator::current};
{}
}
@@ -94,7 +95,7 @@
while (true) {
dynamic #t9 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t10 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
core::Object* x = :for-iterator.{asy::_StreamIterator::current};
{}
}
@@ -116,7 +117,7 @@
while (true) {
dynamic #t12 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t13 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final dynamic #t14 = :for-iterator.{asy::_StreamIterator::current};
{
d = #t14;
@@ -140,7 +141,7 @@
while (true) {
dynamic #t16 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t17 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final core::Object* #t18 = :for-iterator.{asy::_StreamIterator::current};
{
o = #t18;
@@ -174,7 +175,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -199,7 +200,7 @@
while (true) {
dynamic #t20 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t21 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
core::int* x = :for-iterator.{asy::_StreamIterator::current};
{}
}
@@ -221,7 +222,7 @@
while (true) {
dynamic #t23 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t24 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
core::int* x = :for-iterator.{asy::_StreamIterator::current};
{}
}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.outline.expect
index 2fc00f4..ab7413c 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_on_list_literals_infer_if_value_types_match_context.dart.outline.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
typedef Asserter<contravariant T extends core::Object* = dynamic> = (T*) →* void;
-typedef AsserterBuilder<contravariant S extends core::Object* = dynamic, unrelated T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
+typedef AsserterBuilder<contravariant S extends core::Object* = dynamic, contravariant T extends core::Object* = dynamic> = (S*) →* (T*) →* void;
class DartType extends core::Object {
synthetic constructor •() → self::DartType*
;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
index 0f46239..b784630 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_yield_yield_star.dart.strong.transformed.expect
@@ -42,7 +42,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -92,7 +92,7 @@
return :controller_stream;
}
static method bar() → core::Iterable<core::Map<core::int*, core::int*>*>* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<core::Map<core::int*, core::int*>*>* :iterator) → core::bool* yielding {
{
diff --git a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect
index d2367f2..4ae05470 100644
--- a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect
@@ -19,9 +19,9 @@
static method test() → dynamic {
dynamic d = new self::Foo::•();
core::int* get_hashCode = d.{core::Object::hashCode};
- dynamic call_hashCode = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/dynamic_methods.dart:16:39: Error: 'hashCode' isn't a function or method and can't be invoked.
+ dynamic call_hashCode = invalid-expression "pkg/front_end/testcases/inference/dynamic_methods.dart:16:39: Error: 'hashCode' isn't a function or method and can't be invoked.
d. /*@target=Object::hashCode*/ hashCode();
- ^" in d.{core::Object::hashCode}();
+ ^";
core::String* call_toString = d.{core::Object::toString}();
dynamic call_toStringArg = d.toString(color: "pink");
dynamic call_foo0 = d.foo();
diff --git a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect
index d2367f2..4ae05470 100644
--- a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect
@@ -19,9 +19,9 @@
static method test() → dynamic {
dynamic d = new self::Foo::•();
core::int* get_hashCode = d.{core::Object::hashCode};
- dynamic call_hashCode = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/dynamic_methods.dart:16:39: Error: 'hashCode' isn't a function or method and can't be invoked.
+ dynamic call_hashCode = invalid-expression "pkg/front_end/testcases/inference/dynamic_methods.dart:16:39: Error: 'hashCode' isn't a function or method and can't be invoked.
d. /*@target=Object::hashCode*/ hashCode();
- ^" in d.{core::Object::hashCode}();
+ ^";
core::String* call_toString = d.{core::Object::toString}();
dynamic call_toStringArg = d.toString(color: "pink");
dynamic call_foo0 = d.foo();
diff --git a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.strong.transformed.expect
index fb79f44..1e3cd61 100644
--- a/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/for_each_downcast_iterable.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
static method test() → dynamic /* originally async */ {
final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
@@ -9,7 +10,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -31,7 +32,7 @@
while (true) {
dynamic #t1 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t2 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
dynamic x = :for-iterator.{asy::_StreamIterator::current};
{}
}
@@ -57,7 +58,7 @@
while (true) {
dynamic #t5 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t6 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final dynamic #t7 = :for-iterator.{asy::_StreamIterator::current};
{
y = #t7 as{TypeError} core::int*;
diff --git a/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
index f53682d..8aa7e82 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,7 +32,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -39,7 +40,7 @@
#L1:
{
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -60,7 +61,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -68,7 +69,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -89,7 +90,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -116,7 +117,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -147,7 +148,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -174,7 +175,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
index b43b873..1e87f8a 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,7 +32,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -39,7 +40,7 @@
#L1:
{
[yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -60,7 +61,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -68,7 +69,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -89,7 +90,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -116,7 +117,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -147,7 +148,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -174,7 +175,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
index 60990e7..df9aa51 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,7 +32,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -39,7 +40,7 @@
#L1:
{
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -60,7 +61,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -68,7 +69,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -89,7 +90,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -116,7 +117,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -147,7 +148,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -174,7 +175,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
index 8125700..c349f97 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,7 +32,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -39,7 +40,7 @@
#L1:
{
[yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -60,7 +61,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -68,7 +69,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -89,7 +90,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -116,7 +117,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -147,7 +148,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -174,7 +175,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
index 6e1684b..1afc871 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,7 +32,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -39,7 +40,7 @@
#L1:
{
[yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -60,7 +61,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -68,7 +69,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -89,7 +90,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -116,7 +117,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -147,7 +148,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -174,7 +175,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
index 5a87ad0..9731f3b 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,7 +32,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -39,7 +40,7 @@
#L1:
{
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L1;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -60,7 +61,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -68,7 +69,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :result;
+ :return_value = _in::unsafeCast<core::int*>(:result);
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -89,7 +90,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -116,7 +117,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -147,7 +148,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -174,7 +175,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
index c15d6b6..5abd329 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,10 +32,10 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
+ core::int* :async_temporary_0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
@@ -44,7 +45,7 @@
}
else {
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_0 = :result;
+ :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
:return_value = :async_temporary_0;
break #L1;
@@ -67,7 +68,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -75,7 +76,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(x, :async_op_then, :async_op_error, :async_op) in null;
- :return_value = (:result ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
+ :return_value = (_in::unsafeCast<core::bool*>(:result) ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
index c3baf4e..852ab83 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,10 +32,10 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
+ core::int* :async_temporary_0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
@@ -44,7 +45,7 @@
}
else {
[yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_0 = :result;
+ :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
:return_value = :async_temporary_0;
break #L1;
@@ -67,7 +68,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -75,7 +76,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(x, :async_op_then, :async_op_error, :async_op) in null;
- :return_value = (:result ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
+ :return_value = (_in::unsafeCast<core::bool*>(:result) ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
index a1e0911..56e7a58 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,10 +32,10 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
+ core::int* :async_temporary_0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
@@ -44,7 +45,7 @@
}
else {
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_0 = :result;
+ :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
:return_value = :async_temporary_0;
break #L1;
@@ -67,7 +68,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -75,7 +76,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(x, :async_op_then, :async_op_error, :async_op) in null;
- :return_value = (:result ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
+ :return_value = (_in::unsafeCast<core::bool*>(:result) ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
index 0ee0ff4..8009681 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,10 +32,10 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
+ core::int* :async_temporary_0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
@@ -44,7 +45,7 @@
}
else {
[yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_0 = :result;
+ :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
:return_value = :async_temporary_0;
break #L1;
@@ -67,7 +68,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -75,7 +76,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(x, :async_op_then, :async_op_error, :async_op) in null;
- :return_value = (:result ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
+ :return_value = (_in::unsafeCast<core::bool*>(:result) ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
index 71a707c..9cda589 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,10 +32,10 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
+ core::int* :async_temporary_0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
@@ -44,7 +45,7 @@
}
else {
[yield] let dynamic #t1 = asy::_awaitHelper(new self::MyFuture::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_0 = :result;
+ :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
:return_value = :async_temporary_0;
break #L1;
@@ -67,7 +68,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -75,7 +76,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(x, :async_op_then, :async_op_error, :async_op) in null;
- :return_value = (:result ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
+ :return_value = (_in::unsafeCast<core::bool*>(:result) ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
index 7cdb74e..50485af 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,10 +32,10 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
+ core::int* :async_temporary_0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
@@ -44,7 +45,7 @@
}
else {
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_0 = :result;
+ :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
:return_value = :async_temporary_0;
break #L1;
@@ -67,7 +68,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -75,7 +76,7 @@
#L2:
{
[yield] let dynamic #t2 = asy::_awaitHelper(x, :async_op_then, :async_op_error, :async_op) in null;
- :return_value = (:result ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
+ :return_value = (_in::unsafeCast<core::bool*>(:result) ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} asy::FutureOr<core::int*>*;
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
index 49ce857..760de92 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -31,10 +32,10 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
+ core::int* :async_temporary_0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L1:
@@ -42,7 +43,7 @@
final core::int* #t1 = x;
if(#t1.{core::num::==}(null)) {
[yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::value<core::int*>(3), :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_0 = :result;
+ :async_temporary_0 = _in::unsafeCast<core::int*>(:result);
}
else {
:async_temporary_0 = #t1;
@@ -68,7 +69,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -76,7 +77,7 @@
#L2:
{
[yield] let dynamic #t3 = asy::_awaitHelper(x, :async_op_then, :async_op_error, :async_op) in null;
- :return_value = (let final core::int* #t4 = :result in #t4.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t4) as{TypeError} asy::FutureOr<core::int*>*;
+ :return_value = (let final core::int* #t4 = _in::unsafeCast<core::int*>(:result) in #t4.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t4) as{TypeError} asy::FutureOr<core::int*>*;
break #L2;
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
index 0c94989..4f29e0f 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
@@ -29,7 +29,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -56,7 +56,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -83,7 +83,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
index 8d24cfe..46ac20c 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
@@ -29,7 +29,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -56,7 +56,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -83,7 +83,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
index 873f587..2819009 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
@@ -43,7 +43,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -70,7 +70,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
index 5d28067..e4688e7 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
@@ -32,7 +32,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -59,7 +59,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
index af242e2..daeed90 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
@@ -43,7 +43,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -70,7 +70,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
index 675a8a6..7bd9b40 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
@@ -32,7 +32,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -59,7 +59,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect
index 4ec9a21..69f42e3 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_future_return.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -16,7 +17,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -26,7 +27,7 @@
asy::Future<core::List<self::A*>*>* f1 = null;
asy::Future<core::List<self::A*>*>* f2 = null;
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::wait<core::List<self::A*>*>(<asy::Future<core::List<self::A*>*>*>[f1, f2]), :async_op_then, :async_op_error, :async_op) in null;
- core::List<core::List<self::A*>*>* merged = :result;
+ core::List<core::List<self::A*>*>* merged = _in::unsafeCast<core::List<core::List<self::A*>*>*>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.strong.transformed.expect
index 671564f..ce99844 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_generic_method_with_generic_return.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -13,7 +14,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -22,7 +23,7 @@
{
asy::Future<core::String*>* f;
[yield] let dynamic #t1 = asy::_awaitHelper(self::id<asy::FutureOr<core::String*>*>(f), :async_op_then, :async_op_error, :async_op) in null;
- core::String* s = :result;
+ core::String* s = _in::unsafeCast<core::String*>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
diff --git a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect
index 0ae7eb2..c71cd17 100644
--- a/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_upwards_generic_methods.dart.strong.transformed.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -26,7 +27,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -37,9 +38,9 @@
asy::Future<self::C*>* c = asy::Future::value<self::C*>(new self::C::•());
core::List<asy::Future<self::A*>*>* lll = <asy::Future<self::A*>*>[b, c];
[yield] let dynamic #t1 = asy::_awaitHelper(asy::Future::wait<self::A*>(lll), :async_op_then, :async_op_error, :async_op) in null;
- core::List<self::A*>* result = :result;
+ core::List<self::A*>* result = _in::unsafeCast<core::List<self::A*>*>(:result);
[yield] let dynamic #t2 = asy::_awaitHelper(asy::Future::wait<self::A*>(<asy::Future<self::A*>*>[b, c]), :async_op_then, :async_op_error, :async_op) in null;
- core::List<self::A*>* result2 = :result;
+ core::List<self::A*>* result2 = _in::unsafeCast<core::List<self::A*>*>(:result);
core::List<self::A*>* list = result;
list = result2;
}
diff --git a/pkg/front_end/testcases/inference/generator_closure.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generator_closure.dart.strong.transformed.expect
index 2f0ff59..fc34967 100644
--- a/pkg/front_end/testcases/inference/generator_closure.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generator_closure.dart.strong.transformed.expect
@@ -13,7 +13,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.outline.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.outline.expect
index 4c088aa..cd56022 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_function_parameter_type2.dart.outline.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-typedef G<unrelated V extends core::Object* = dynamic> = () →* core::List<V*>*;
+typedef G<V extends core::Object* = dynamic> = () →* core::List<V*>*;
class C<T extends core::Object* = dynamic> extends self::D<self::C::T*> {
synthetic constructor •() → self::C<self::C::T*>*
;
diff --git a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.strong.transformed.expect
index 5ee8e86..e6b1e38 100644
--- a/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_local_function_return_type.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -42,7 +42,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -64,7 +64,7 @@
return :async_completer.{asy::Completer::future};
}
function f4() → core::Iterable<core::int*>* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<core::int*>* :iterator) → core::bool* yielding {
{
@@ -83,7 +83,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
diff --git a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
index 55072fa..7fe8c70 100644
--- a/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart.strong.transformed.expect
@@ -31,6 +31,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -50,7 +51,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -69,7 +70,7 @@
while (true) {
dynamic #t1 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t2 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
core::String* i = :for-iterator.{asy::_StreamIterator::current};
{
core::int* x = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:17:44: Error: A value of type 'String' can't be assigned to a variable of type 'int'.
@@ -110,7 +111,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -129,7 +130,7 @@
while (true) {
dynamic #t5 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t6 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
self::Baz::T* i = :for-iterator.{asy::_StreamIterator::current};
{
core::int* x = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:25:44: Error: A value of type 'T' can't be assigned to a variable of type 'int'.
@@ -171,7 +172,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -191,7 +192,7 @@
while (true) {
dynamic #t9 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t10 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
self::Foo* x = :for-iterator.{asy::_StreamIterator::current};
{
core::String* y = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:38:45: Error: A value of type 'Foo' can't be assigned to a variable of type 'String'.
@@ -218,7 +219,7 @@
while (true) {
dynamic #t13 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t14 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
dynamic x = :for-iterator.{asy::_StreamIterator::current};
{
core::String* y = x as{TypeError} core::String*;
@@ -242,7 +243,7 @@
while (true) {
dynamic #t16 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t17 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final self::Foo* #t18 = :for-iterator.{asy::_StreamIterator::current};
{
core::String* x = let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/inference/infer_types_on_loop_indices_for_each_loop_async.dart:45:21: Error: A value of type 'Foo' can't be assigned to a variable of type 'String'.
@@ -272,7 +273,7 @@
while (true) {
dynamic #t21 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t22 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final self::Foo* #t23 = :for-iterator.{asy::_StreamIterator::current};
{
z = #t23;
@@ -298,7 +299,7 @@
while (true) {
dynamic #t25 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t26 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final dynamic #t27 = :for-iterator.{asy::_StreamIterator::current};
{
self::Foo* x = #t27 as{TypeError} self::Foo*;
@@ -324,7 +325,7 @@
while (true) {
dynamic #t29 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t30 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final dynamic #t31 = :for-iterator.{asy::_StreamIterator::current};
{
self::Foo* x = #t31 as{TypeError} self::Foo*;
@@ -355,7 +356,7 @@
while (true) {
dynamic #t34 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t35 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
dynamic x = :for-iterator.{asy::_StreamIterator::current};
{
core::String* y = x as{TypeError} core::String*;
diff --git a/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect
index 02cb679..d796649 100644
--- a/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/local_return_and_yield.dart.strong.transformed.expect
@@ -24,7 +24,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -49,7 +49,7 @@
return :async_completer.{asy::Completer::future};
}
function c() → core::Iterable<(core::int*) →* core::int*>* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<(core::int*) →* core::int*>* :iterator) → core::bool* yielding {
{
@@ -63,7 +63,7 @@
return new core::_SyncIterable::•<(core::int*) →* core::int*>(:sync_op);
}
function d() → core::Iterable<(core::int*) →* core::int*>* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<(core::int*) →* core::int*>* :iterator) → core::bool* yielding {
{
@@ -82,7 +82,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -117,7 +117,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
diff --git a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect
index 0dba3ea..f6ea666 100644
--- a/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/top_level_return_and_yield.dart.strong.transformed.expect
@@ -23,7 +23,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -48,7 +48,7 @@
return :async_completer.{asy::Completer::future};
}
static method c() → core::Iterable<(core::int*) →* core::int*>* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<(core::int*) →* core::int*>* :iterator) → core::bool* yielding {
{
@@ -62,7 +62,7 @@
return new core::_SyncIterable::•<(core::int*) →* core::int*>(:sync_op);
}
static method d() → core::Iterable<(core::int*) →* core::int*>* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<(core::int*) →* core::int*>* :iterator) → core::bool* yielding {
{
@@ -81,7 +81,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -116,7 +116,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
diff --git a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect
index 200434f..ee4302e 100644
--- a/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_invalid_iterable.dart.strong.transformed.expect
@@ -25,6 +25,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
static method test() → dynamic /* originally async */ {
final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
@@ -32,7 +33,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -61,7 +62,7 @@
while (true) {
dynamic #t4 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t5 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final dynamic #t6 = :for-iterator.{asy::_StreamIterator::current};
{
core::int* x = #t6 as{TypeError} core::int*;
@@ -95,7 +96,7 @@
while (true) {
dynamic #t11 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t12 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final dynamic #t13 = :for-iterator.{asy::_StreamIterator::current};
{
y = #t13 as{TypeError} core::int*;
diff --git a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect
index 650e52c..649f649 100644
--- a/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart.strong.transformed.expect
@@ -17,6 +17,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
import "dart:async";
@@ -38,7 +39,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -65,7 +66,7 @@
while (true) {
dynamic #t2 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t3 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final self::A* #t4 = :for-iterator.{asy::_StreamIterator::current};
{
a = #t4;
@@ -92,7 +93,7 @@
while (true) {
dynamic #t7 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t8 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final self::A* #t9 = :for-iterator.{asy::_StreamIterator::current};
{
b = #t9 as{TypeError} self::B*;
@@ -123,7 +124,7 @@
while (true) {
dynamic #t13 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t14 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final self::A* #t15 = :for-iterator.{asy::_StreamIterator::current};
{
i = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/inference_new/for_each_outer_var_type.dart:27:16: Error: A value of type 'A' can't be assigned to a variable of type 'int'.
@@ -154,7 +155,7 @@
while (true) {
dynamic #t19 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t20 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
final self::A* #t21 = :for-iterator.{asy::_StreamIterator::current};
{
a = #t21;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.outline.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.outline.expect
index 5985c4c..ada0233 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.outline.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.outline.expect
@@ -16,7 +16,7 @@
import self as self;
import "dart:core" as core;
-typedef Fisk<unrelated TypeY extends core::Object* = dynamic> = () →* void;
+typedef Fisk<unrelated TypeY extends dynamic = dynamic> = () →* void;
class Hest<TypeX extends () →* void = () →* void> extends core::Object {
synthetic constructor •() → self::Hest<self::Hest::TypeX*>*
;
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.expect
index 7b9d47f..f4c5a8b 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.expect
@@ -16,7 +16,7 @@
import self as self;
import "dart:core" as core;
-typedef Fisk<unrelated TypeY extends core::Object* = dynamic> = () →* void;
+typedef Fisk<unrelated TypeY extends dynamic = dynamic> = () →* void;
class Hest<TypeX extends () →* void = () →* void> extends core::Object {
synthetic constructor •() → self::Hest<self::Hest::TypeX*>*
: super core::Object::•()
diff --git a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.transformed.expect b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.transformed.expect
index 7b9d47f..f4c5a8b 100644
--- a/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/instantiate_to_bound/non_simple_class_typedef_cycle.dart.strong.transformed.expect
@@ -16,7 +16,7 @@
import self as self;
import "dart:core" as core;
-typedef Fisk<unrelated TypeY extends core::Object* = dynamic> = () →* void;
+typedef Fisk<unrelated TypeY extends dynamic = dynamic> = () →* void;
class Hest<TypeX extends () →* void = () →* void> extends core::Object {
synthetic constructor •() → self::Hest<self::Hest::TypeX*>*
: super core::Object::•()
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart
new file mode 100644
index 0000000..1ff72a5
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2019, 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.
+
+class Class {
+ late int field = 10;
+
+ Class.constructor1();
+ Class.constructor2(int this.field);
+ Class.constructor3(int value) : this.field = value + 1;
+ Class.constructor4([int this.field = 42]);
+}
+
+class Subclass extends Class {
+ Subclass.constructor1() : super.constructor1();
+ Subclass.constructor2(int value) : super.constructor2(value);
+ Subclass.constructor3(int value) : super.constructor3(value);
+ Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+
+test1() {
+ var c1 = new Class.constructor1();
+ expect(10, c1.field);
+ c1.field = 16;
+ expect(16, c1.field);
+
+ var c2 = new Class.constructor2(42);
+ expect(42, c2.field);
+ c2.field = 43;
+ expect(43, c2.field);
+
+ var c3 = new Class.constructor3(87);
+ expect(88, c3.field);
+ c3.field = 89;
+ expect(89, c3.field);
+
+ var c4 = new Class.constructor4();
+ expect(42, c4.field);
+ c4.field = 43;
+ expect(43, c4.field);
+
+ var c5 = new Class.constructor4(123);
+ expect(123, c5.field);
+ c5.field = 124;
+ expect(124, c5.field);
+}
+
+test2() {
+ var c1 = new Subclass.constructor1();
+ expect(10, c1.field);
+ c1.field = 16;
+ expect(16, c1.field);
+
+ var c2 = new Subclass.constructor2(42);
+ expect(42, c2.field);
+ c2.field = 43;
+ expect(43, c2.field);
+
+ var c3 = new Subclass.constructor3(87);
+ expect(88, c3.field);
+ c3.field = 89;
+ expect(89, c3.field);
+
+ var c4 = new Subclass.constructor4();
+ expect(87, c4.field);
+ c4.field = 88;
+ expect(88, c4.field);
+
+ var c5 = new Subclass.constructor4(123);
+ expect(123, c5.field);
+ c5.field = 124;
+ expect(124, c5.field);
+}
+
+main() {
+ test1();
+ test2();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.outline.expect
new file mode 100644
index 0000000..e809201
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.outline.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field;
+ constructor constructor1() → self::Class
+ ;
+ constructor constructor2(core::int field) → self::Class
+ ;
+ constructor constructor3(core::int value) → self::Class
+ ;
+ constructor constructor4([core::int field]) → self::Class
+ ;
+ get field() → core::int;
+ set field(core::int #t1) → void;
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ ;
+ constructor constructor4([core::int value]) → self::Subclass
+ ;
+}
+static method test1() → dynamic
+ ;
+static method test2() → dynamic
+ ;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect
new file mode 100644
index 0000000..77c1250
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.expect
@@ -0,0 +1,94 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int
+ return let final core::int? #t1 = this.{self::Class::_#field} in #t1.==(null) ?{core::int} this.{self::Class::_#field} = 10 : #t1{core::int};
+ set field(core::int #t2) → void
+ this.{self::Class::_#field} = #t2;
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::expect(10, c1.{self::Class::field});
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ c4.{self::Class::field} = 43;
+ self::expect(43, c4.{self::Class::field});
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::expect(10, c1.{self::Class::field});
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ c4.{self::Class::field} = 88;
+ self::expect(88, c4.{self::Class::field});
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..77c1250
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.strong.transformed.expect
@@ -0,0 +1,94 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int
+ return let final core::int? #t1 = this.{self::Class::_#field} in #t1.==(null) ?{core::int} this.{self::Class::_#field} = 10 : #t1{core::int};
+ set field(core::int #t2) → void
+ this.{self::Class::_#field} = #t2;
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::expect(10, c1.{self::Class::field});
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ c4.{self::Class::field} = 43;
+ self::expect(43, c4.{self::Class::field});
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::expect(10, c1.{self::Class::field});
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ c4.{self::Class::field} = 88;
+ self::expect(88, c4.{self::Class::field});
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart
new file mode 100644
index 0000000..b06db9d
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2019, 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.
+
+class Class {
+ late int field;
+
+ Class.constructor1();
+ Class.constructor2(int this.field);
+ Class.constructor3(int value) : this.field = value + 1;
+ Class.constructor4([int this.field = 42]);
+}
+
+class Subclass extends Class {
+ Subclass.constructor1() : super.constructor1();
+ Subclass.constructor2(int value) : super.constructor2(value);
+ Subclass.constructor3(int value) : super.constructor3(value);
+ Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+
+test1() {
+ var c1 = new Class.constructor1();
+ throws(() => c1.field, 'Read value from uninitialized Class.field');
+ c1.field = 16;
+ expect(16, c1.field);
+
+ var c2 = new Class.constructor2(42);
+ expect(42, c2.field);
+ c2.field = 43;
+ expect(43, c2.field);
+
+ var c3 = new Class.constructor3(87);
+ expect(88, c3.field);
+ c3.field = 89;
+ expect(89, c3.field);
+
+ var c4 = new Class.constructor4();
+ expect(42, c4.field);
+ c4.field = 43;
+ expect(43, c4.field);
+
+ var c5 = new Class.constructor4(123);
+ expect(123, c5.field);
+ c5.field = 124;
+ expect(124, c5.field);
+}
+
+test2() {
+ var c1 = new Subclass.constructor1();
+ throws(() => c1.field, 'Read value from uninitialized Class.field');
+ c1.field = 16;
+ expect(16, c1.field);
+
+ var c2 = new Subclass.constructor2(42);
+ expect(42, c2.field);
+ c2.field = 43;
+ expect(43, c2.field);
+
+ var c3 = new Subclass.constructor3(87);
+ expect(88, c3.field);
+ c3.field = 89;
+ expect(89, c3.field);
+
+ var c4 = new Subclass.constructor4();
+ expect(87, c4.field);
+ c4.field = 88;
+ expect(88, c4.field);
+
+ var c5 = new Subclass.constructor4(123);
+ expect(123, c5.field);
+ c5.field = 124;
+ expect(124, c5.field);
+}
+
+main() {
+ test1();
+ test2();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..46ce40c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.outline.expect
@@ -0,0 +1,37 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field;
+ constructor constructor1() → self::Class
+ ;
+ constructor constructor2(core::int field) → self::Class
+ ;
+ constructor constructor3(core::int value) → self::Class
+ ;
+ constructor constructor4([core::int field]) → self::Class
+ ;
+ get field() → core::int;
+ set field(core::int #t1) → void;
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ ;
+ constructor constructor4([core::int value]) → self::Subclass
+ ;
+}
+static method test1() → dynamic
+ ;
+static method test2() → dynamic
+ ;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..7e44af1
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.expect
@@ -0,0 +1,105 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int
+ return let final core::int? #t1 = this.{self::Class::_#field} in #t1.==(null) ?{core::int} throw "Field 'field' has not been initialized." : #t1{core::int};
+ set field(core::int #t2) → void
+ this.{self::Class::_#field} = #t2;
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::throws(() → core::int => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ c4.{self::Class::field} = 43;
+ self::expect(43, c4.{self::Class::field});
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::throws(() → core::int => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ c4.{self::Class::field} = 88;
+ self::expect(88, c4.{self::Class::field});
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..7e44af1
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,105 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int
+ return let final core::int? #t1 = this.{self::Class::_#field} in #t1.==(null) ?{core::int} throw "Field 'field' has not been initialized." : #t1{core::int};
+ set field(core::int #t2) → void
+ this.{self::Class::_#field} = #t2;
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::throws(() → core::int => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ c4.{self::Class::field} = 43;
+ self::expect(43, c4.{self::Class::field});
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::throws(() → core::int => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ c4.{self::Class::field} = 88;
+ self::expect(88, c4.{self::Class::field});
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart
new file mode 100644
index 0000000..e857d22
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2019, 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.
+
+class Class {
+ late final int field;
+
+ Class.constructor1();
+ Class.constructor2(int this.field);
+ Class.constructor3(int value) : this.field = value + 1;
+ Class.constructor4([int this.field = 42]);
+}
+
+class Subclass extends Class {
+ Subclass.constructor1() : super.constructor1();
+ Subclass.constructor2(int value) : super.constructor2(value);
+ Subclass.constructor3(int value) : super.constructor3(value);
+ Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+
+test1() {
+ var c1 = new Class.constructor1();
+ throws(() => c1.field, 'Read value from uninitialized Class.field');
+ c1.field = 16;
+ expect(16, c1.field);
+ throws(() => c1.field = 17, 'Write value to initialized Class.field');
+
+ var c2 = new Class.constructor2(42);
+ expect(42, c2.field);
+ throws(() => c2.field = 43, 'Write value to initialized Class.field');
+
+ var c3 = new Class.constructor3(87);
+ expect(88, c3.field);
+ throws(() => c3.field = 89, 'Write value to initialized Class.field');
+
+ var c4 = new Class.constructor4();
+ expect(42, c4.field);
+ throws(() => c4.field = 43, 'Write value to initialized Class.field');
+
+ var c5 = new Class.constructor4(123);
+ expect(123, c5.field);
+ throws(() => c5.field = 124, 'Write value to initialized Class.field');
+
+ var c6 = new Class.constructor1();
+ c6.field = 32;
+ expect(32, c6.field);
+ throws(() => c6.field = 32, 'Write value to initialized Class.field');
+}
+
+test2() {
+ var c1 = new Subclass.constructor1();
+ throws(() => c1.field, 'Read value from uninitialized Class1.field');
+ c1.field = 16;
+ expect(16, c1.field);
+ throws(() => c1.field = 17, 'Write value to initialized Class.field');
+
+ var c2 = new Subclass.constructor2(42);
+ expect(42, c2.field);
+ throws(() => c2.field = 43, 'Write value to initialized Class.field');
+
+ var c3 = new Subclass.constructor3(87);
+ expect(88, c3.field);
+ throws(() => c3.field = 89, 'Write value to initialized Class.field');
+
+ var c4 = new Subclass.constructor4();
+ expect(87, c4.field);
+ throws(() => c4.field = 88, 'Write value to initialized Class.field');
+
+ var c5 = new Subclass.constructor4(123);
+ expect(123, c5.field);
+ throws(() => c5.field = 124, 'Write value to initialized Class.field');
+
+ var c6 = new Subclass.constructor1();
+ c6.field = 32;
+ expect(32, c6.field);
+ throws(() => c6.field = 32, 'Write value to initialized Class.field');
+}
+
+main() {
+ test1();
+ test2();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..46ce40c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.outline.expect
@@ -0,0 +1,37 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field;
+ constructor constructor1() → self::Class
+ ;
+ constructor constructor2(core::int field) → self::Class
+ ;
+ constructor constructor3(core::int value) → self::Class
+ ;
+ constructor constructor4([core::int field]) → self::Class
+ ;
+ get field() → core::int;
+ set field(core::int #t1) → void;
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ ;
+ constructor constructor4([core::int value]) → self::Subclass
+ ;
+}
+static method test1() → dynamic
+ ;
+static method test2() → dynamic
+ ;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..8e4ad19
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.expect
@@ -0,0 +1,110 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int
+ return let final core::int? #t1 = this.{self::Class::_#field} in #t1.==(null) ?{core::int} throw "Field 'field' has not been initialized." : #t1{core::int};
+ set field(core::int #t2) → void
+ if(this.{self::Class::_#field}.==(null))
+ this.{self::Class::_#field} = #t2;
+ else
+ throw "Field 'field' has already been initialized.";
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::throws(() → core::int => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::throws(() → core::int => c1.{self::Class::field} = 17, "Write value to initialized Class.field");
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ self::throws(() → core::int => c2.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ self::throws(() → core::int => c3.{self::Class::field} = 89, "Write value to initialized Class.field");
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ self::throws(() → core::int => c4.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ self::throws(() → core::int => c5.{self::Class::field} = 124, "Write value to initialized Class.field");
+ self::Class c6 = new self::Class::constructor1();
+ c6.{self::Class::field} = 32;
+ self::expect(32, c6.{self::Class::field});
+ self::throws(() → core::int => c6.{self::Class::field} = 32, "Write value to initialized Class.field");
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::throws(() → core::int => c1.{self::Class::field}, "Read value from uninitialized Class1.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::throws(() → core::int => c1.{self::Class::field} = 17, "Write value to initialized Class.field");
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ self::throws(() → core::int => c2.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ self::throws(() → core::int => c3.{self::Class::field} = 89, "Write value to initialized Class.field");
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ self::throws(() → core::int => c4.{self::Class::field} = 88, "Write value to initialized Class.field");
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ self::throws(() → core::int => c5.{self::Class::field} = 124, "Write value to initialized Class.field");
+ self::Subclass c6 = new self::Subclass::constructor1();
+ c6.{self::Class::field} = 32;
+ self::expect(32, c6.{self::Class::field});
+ self::throws(() → core::int => c6.{self::Class::field} = 32, "Write value to initialized Class.field");
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..8e4ad19
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,110 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int
+ return let final core::int? #t1 = this.{self::Class::_#field} in #t1.==(null) ?{core::int} throw "Field 'field' has not been initialized." : #t1{core::int};
+ set field(core::int #t2) → void
+ if(this.{self::Class::_#field}.==(null))
+ this.{self::Class::_#field} = #t2;
+ else
+ throw "Field 'field' has already been initialized.";
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::throws(() → core::int => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::throws(() → core::int => c1.{self::Class::field} = 17, "Write value to initialized Class.field");
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ self::throws(() → core::int => c2.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ self::throws(() → core::int => c3.{self::Class::field} = 89, "Write value to initialized Class.field");
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ self::throws(() → core::int => c4.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ self::throws(() → core::int => c5.{self::Class::field} = 124, "Write value to initialized Class.field");
+ self::Class c6 = new self::Class::constructor1();
+ c6.{self::Class::field} = 32;
+ self::expect(32, c6.{self::Class::field});
+ self::throws(() → core::int => c6.{self::Class::field} = 32, "Write value to initialized Class.field");
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::throws(() → core::int => c1.{self::Class::field}, "Read value from uninitialized Class1.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::throws(() → core::int => c1.{self::Class::field} = 17, "Write value to initialized Class.field");
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ self::throws(() → core::int => c2.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ self::throws(() → core::int => c3.{self::Class::field} = 89, "Write value to initialized Class.field");
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ self::throws(() → core::int => c4.{self::Class::field} = 88, "Write value to initialized Class.field");
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ self::throws(() → core::int => c5.{self::Class::field} = 124, "Write value to initialized Class.field");
+ self::Subclass c6 = new self::Subclass::constructor1();
+ c6.{self::Class::field} = 32;
+ self::expect(32, c6.{self::Class::field});
+ self::throws(() → core::int => c6.{self::Class::field} = 32, "Write value to initialized Class.field");
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart
new file mode 100644
index 0000000..c7bf971
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2019, 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.
+
+int? initField() => 10;
+
+class Class {
+ late int? field = initField();
+
+ Class.constructor1();
+ Class.constructor2(int this.field);
+ Class.constructor3(int value) : this.field = value + 1;
+ Class.constructor4([int this.field = 42]);
+}
+
+class Subclass extends Class {
+ Subclass.constructor1() : super.constructor1();
+ Subclass.constructor2(int value) : super.constructor2(value);
+ Subclass.constructor3(int value) : super.constructor3(value);
+ Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+
+test1() {
+ var c1 = new Class.constructor1();
+ expect(10, c1.field);
+ c1.field = 16;
+ expect(16, c1.field);
+
+ var c2 = new Class.constructor2(42);
+ expect(42, c2.field);
+ c2.field = 43;
+ expect(43, c2.field);
+
+ var c3 = new Class.constructor3(87);
+ expect(88, c3.field);
+ c3.field = 89;
+ expect(89, c3.field);
+
+ var c4 = new Class.constructor4();
+ expect(42, c4.field);
+ c4.field = 43;
+ expect(43, c4.field);
+
+ var c5 = new Class.constructor4(123);
+ expect(123, c5.field);
+ c5.field = 124;
+ expect(124, c5.field);
+}
+
+test2() {
+ var c1 = new Subclass.constructor1();
+ expect(10, c1.field);
+ c1.field = 16;
+ expect(16, c1.field);
+
+ var c2 = new Subclass.constructor2(42);
+ expect(42, c2.field);
+ c2.field = 43;
+ expect(43, c2.field);
+
+ var c3 = new Subclass.constructor3(87);
+ expect(88, c3.field);
+ c3.field = 89;
+ expect(89, c3.field);
+
+ var c4 = new Subclass.constructor4();
+ expect(87, c4.field);
+ c4.field = 88;
+ expect(88, c4.field);
+
+ var c5 = new Subclass.constructor4(123);
+ expect(123, c5.field);
+ c5.field = 124;
+ expect(124, c5.field);
+}
+
+main() {
+ test1();
+ test2();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.outline.expect
new file mode 100644
index 0000000..395faa3
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.outline.expect
@@ -0,0 +1,38 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field;
+ field dynamic _#field#isSet;
+ constructor constructor1() → self::Class
+ ;
+ constructor constructor2(core::int field) → self::Class
+ ;
+ constructor constructor3(core::int value) → self::Class
+ ;
+ constructor constructor4([core::int field]) → self::Class
+ ;
+ get field() → core::int?;
+ set field(core::int? #t1) → void;
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ ;
+ constructor constructor4([core::int value]) → self::Subclass
+ ;
+}
+static method initField() → core::int?
+ ;
+static method test1() → dynamic
+ ;
+static method test2() → dynamic
+ ;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect
new file mode 100644
index 0000000..b7e7998
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.expect
@@ -0,0 +1,104 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ field dynamic _#field#isSet = false;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int? {
+ if(!this.{self::Class::_#field#isSet}) {
+ this.{self::Class::_#field#isSet} = true;
+ this.{self::Class::_#field} = self::initField();
+ }
+ return this.{self::Class::_#field};
+ }
+ set field(core::int? #t1) → void {
+ this.{self::Class::_#field#isSet} = true;
+ this.{self::Class::_#field} = #t1;
+ }
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method initField() → core::int?
+ return 10;
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::expect(10, c1.{self::Class::field});
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ c4.{self::Class::field} = 43;
+ self::expect(43, c4.{self::Class::field});
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::expect(10, c1.{self::Class::field});
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ c4.{self::Class::field} = 88;
+ self::expect(88, c4.{self::Class::field});
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..b7e7998
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -0,0 +1,104 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ field dynamic _#field#isSet = false;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int? {
+ if(!this.{self::Class::_#field#isSet}) {
+ this.{self::Class::_#field#isSet} = true;
+ this.{self::Class::_#field} = self::initField();
+ }
+ return this.{self::Class::_#field};
+ }
+ set field(core::int? #t1) → void {
+ this.{self::Class::_#field#isSet} = true;
+ this.{self::Class::_#field} = #t1;
+ }
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method initField() → core::int?
+ return 10;
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::expect(10, c1.{self::Class::field});
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ c4.{self::Class::field} = 43;
+ self::expect(43, c4.{self::Class::field});
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::expect(10, c1.{self::Class::field});
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ c4.{self::Class::field} = 88;
+ self::expect(88, c4.{self::Class::field});
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart
new file mode 100644
index 0000000..f3497a1
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2019, 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.
+
+class Class {
+ late int? field;
+
+ Class.constructor1();
+ Class.constructor2(int this.field);
+ Class.constructor3(int value) : this.field = value + 1;
+ Class.constructor4([int this.field = 42]);
+}
+
+class Subclass extends Class {
+ Subclass.constructor1() : super.constructor1();
+ Subclass.constructor2(int value) : super.constructor2(value);
+ Subclass.constructor3(int value) : super.constructor3(value);
+ Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+
+test1() {
+ var c1 = new Class.constructor1();
+ throws(() => c1.field, 'Read value from uninitialized Class.field');
+ c1.field = 16;
+ expect(16, c1.field);
+
+ var c2 = new Class.constructor2(42);
+ expect(42, c2.field);
+ c2.field = 43;
+ expect(43, c2.field);
+
+ var c3 = new Class.constructor3(87);
+ expect(88, c3.field);
+ c3.field = 89;
+ expect(89, c3.field);
+
+ var c4 = new Class.constructor4();
+ expect(42, c4.field);
+ c4.field = 43;
+ expect(43, c4.field);
+
+ var c5 = new Class.constructor4(123);
+ expect(123, c5.field);
+ c5.field = 124;
+ expect(124, c5.field);
+}
+
+test2() {
+ var c1 = new Subclass.constructor1();
+ throws(() => c1.field, 'Read value from uninitialized Class.field');
+ c1.field = 16;
+ expect(16, c1.field);
+
+ var c2 = new Subclass.constructor2(42);
+ expect(42, c2.field);
+ c2.field = 43;
+ expect(43, c2.field);
+
+ var c3 = new Subclass.constructor3(87);
+ expect(88, c3.field);
+ c3.field = 89;
+ expect(89, c3.field);
+
+ var c4 = new Subclass.constructor4();
+ expect(87, c4.field);
+ c4.field = 88;
+ expect(88, c4.field);
+
+ var c5 = new Subclass.constructor4(123);
+ expect(123, c5.field);
+ c5.field = 124;
+ expect(124, c5.field);
+}
+
+main() {
+ test1();
+ test2();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..4a4e3d4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.outline.expect
@@ -0,0 +1,38 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field;
+ field dynamic _#field#isSet;
+ constructor constructor1() → self::Class
+ ;
+ constructor constructor2(core::int field) → self::Class
+ ;
+ constructor constructor3(core::int value) → self::Class
+ ;
+ constructor constructor4([core::int field]) → self::Class
+ ;
+ get field() → core::int?;
+ set field(core::int? #t1) → void;
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ ;
+ constructor constructor4([core::int value]) → self::Subclass
+ ;
+}
+static method test1() → dynamic
+ ;
+static method test2() → dynamic
+ ;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..33b5099
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.expect
@@ -0,0 +1,108 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ field dynamic _#field#isSet = false;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int?
+ return this.{self::Class::_#field#isSet} ?{core::int?} this.{self::Class::_#field} : throw "Field 'field' has not been initialized.";
+ set field(core::int? #t1) → void {
+ this.{self::Class::_#field#isSet} = true;
+ this.{self::Class::_#field} = #t1;
+ }
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::throws(() → core::int? => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ c4.{self::Class::field} = 43;
+ self::expect(43, c4.{self::Class::field});
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::throws(() → core::int? => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ c4.{self::Class::field} = 88;
+ self::expect(88, c4.{self::Class::field});
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..33b5099
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,108 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ field dynamic _#field#isSet = false;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int?
+ return this.{self::Class::_#field#isSet} ?{core::int?} this.{self::Class::_#field} : throw "Field 'field' has not been initialized.";
+ set field(core::int? #t1) → void {
+ this.{self::Class::_#field#isSet} = true;
+ this.{self::Class::_#field} = #t1;
+ }
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::throws(() → core::int? => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ c4.{self::Class::field} = 43;
+ self::expect(43, c4.{self::Class::field});
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::throws(() → core::int? => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ c2.{self::Class::field} = 43;
+ self::expect(43, c2.{self::Class::field});
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ c3.{self::Class::field} = 89;
+ self::expect(89, c3.{self::Class::field});
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ c4.{self::Class::field} = 88;
+ self::expect(88, c4.{self::Class::field});
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ c5.{self::Class::field} = 124;
+ self::expect(124, c5.{self::Class::field});
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart
new file mode 100644
index 0000000..7a79d4a
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2019, 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.
+
+class Class {
+ late final int? field;
+
+ Class.constructor1();
+ Class.constructor2(int this.field);
+ Class.constructor3(int value) : this.field = value + 1;
+ Class.constructor4([int this.field = 42]);
+}
+
+class Subclass extends Class {
+ Subclass.constructor1() : super.constructor1();
+ Subclass.constructor2(int value) : super.constructor2(value);
+ Subclass.constructor3(int value) : super.constructor3(value);
+ Subclass.constructor4([int value = 87]) : super.constructor4(value);
+}
+
+test1() {
+ var c1 = new Class.constructor1();
+ throws(() => c1.field, 'Read value from uninitialized Class.field');
+ c1.field = 16;
+ expect(16, c1.field);
+ throws(() => c1.field = 17, 'Write value to initialized Class.field');
+
+ var c2 = new Class.constructor2(42);
+ expect(42, c2.field);
+ throws(() => c2.field = 43, 'Write value to initialized Class.field');
+
+ var c3 = new Class.constructor3(87);
+ expect(88, c3.field);
+ throws(() => c3.field = 89, 'Write value to initialized Class.field');
+
+ var c4 = new Class.constructor4();
+ expect(42, c4.field);
+ throws(() => c4.field = 43, 'Write value to initialized Class.field');
+
+ var c5 = new Class.constructor4(123);
+ expect(123, c5.field);
+ throws(() => c5.field = 124, 'Write value to initialized Class.field');
+
+ var c6 = new Class.constructor1();
+ c6.field = 32;
+ expect(32, c6.field);
+ throws(() => c6.field = 32, 'Write value to initialized Class.field');
+}
+
+test2() {
+ var c1 = new Subclass.constructor1();
+ throws(() => c1.field, 'Read value from uninitialized Class1.field');
+ c1.field = 16;
+ expect(16, c1.field);
+ throws(() => c1.field = 17, 'Write value to initialized Class.field');
+
+ var c2 = new Subclass.constructor2(42);
+ expect(42, c2.field);
+ throws(() => c2.field = 43, 'Write value to initialized Class.field');
+
+ var c3 = new Subclass.constructor3(87);
+ expect(88, c3.field);
+ throws(() => c3.field = 89, 'Write value to initialized Class.field');
+
+ var c4 = new Subclass.constructor4();
+ expect(87, c4.field);
+ throws(() => c4.field = 88, 'Write value to initialized Class.field');
+
+ var c5 = new Subclass.constructor4(123);
+ expect(123, c5.field);
+ throws(() => c5.field = 124, 'Write value to initialized Class.field');
+
+ var c6 = new Subclass.constructor1();
+ c6.field = 32;
+ expect(32, c6.field);
+ throws(() => c6.field = 32, 'Write value to initialized Class.field');
+}
+
+main() {
+ test1();
+ test2();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..4a4e3d4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.outline.expect
@@ -0,0 +1,38 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field;
+ field dynamic _#field#isSet;
+ constructor constructor1() → self::Class
+ ;
+ constructor constructor2(core::int field) → self::Class
+ ;
+ constructor constructor3(core::int value) → self::Class
+ ;
+ constructor constructor4([core::int field]) → self::Class
+ ;
+ get field() → core::int?;
+ set field(core::int? #t1) → void;
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ ;
+ constructor constructor4([core::int value]) → self::Subclass
+ ;
+}
+static method test1() → dynamic
+ ;
+static method test2() → dynamic
+ ;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..f4ff248
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.expect
@@ -0,0 +1,113 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ field dynamic _#field#isSet = false;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int?
+ return this.{self::Class::_#field#isSet} ?{core::int?} this.{self::Class::_#field} : throw "Field 'field' has not been initialized.";
+ set field(core::int? #t1) → void
+ if(this.{self::Class::_#field#isSet})
+ throw "Field 'field' has already been initialized.";
+ else {
+ this.{self::Class::_#field#isSet} = true;
+ this.{self::Class::_#field} = #t1;
+ }
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::throws(() → core::int? => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::throws(() → core::int => c1.{self::Class::field} = 17, "Write value to initialized Class.field");
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ self::throws(() → core::int => c2.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ self::throws(() → core::int => c3.{self::Class::field} = 89, "Write value to initialized Class.field");
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ self::throws(() → core::int => c4.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ self::throws(() → core::int => c5.{self::Class::field} = 124, "Write value to initialized Class.field");
+ self::Class c6 = new self::Class::constructor1();
+ c6.{self::Class::field} = 32;
+ self::expect(32, c6.{self::Class::field});
+ self::throws(() → core::int => c6.{self::Class::field} = 32, "Write value to initialized Class.field");
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::throws(() → core::int? => c1.{self::Class::field}, "Read value from uninitialized Class1.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::throws(() → core::int => c1.{self::Class::field} = 17, "Write value to initialized Class.field");
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ self::throws(() → core::int => c2.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ self::throws(() → core::int => c3.{self::Class::field} = 89, "Write value to initialized Class.field");
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ self::throws(() → core::int => c4.{self::Class::field} = 88, "Write value to initialized Class.field");
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ self::throws(() → core::int => c5.{self::Class::field} = 124, "Write value to initialized Class.field");
+ self::Subclass c6 = new self::Subclass::constructor1();
+ c6.{self::Class::field} = 32;
+ self::expect(32, c6.{self::Class::field});
+ self::throws(() → core::int => c6.{self::Class::field} = 32, "Write value to initialized Class.field");
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..f4ff248
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/instance_nullable_final_field_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,113 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ field core::int? _#field = null;
+ field dynamic _#field#isSet = false;
+ constructor constructor1() → self::Class
+ : super core::Object::•()
+ ;
+ constructor constructor2(core::int field) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ constructor constructor3(core::int value) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = value.{core::num::+}(1), super core::Object::•()
+ ;
+ constructor constructor4([core::int field = #C1]) → self::Class
+ : self::Class::_#field#isSet = true, self::Class::_#field = field, super core::Object::•()
+ ;
+ get field() → core::int?
+ return this.{self::Class::_#field#isSet} ?{core::int?} this.{self::Class::_#field} : throw "Field 'field' has not been initialized.";
+ set field(core::int? #t1) → void
+ if(this.{self::Class::_#field#isSet})
+ throw "Field 'field' has already been initialized.";
+ else {
+ this.{self::Class::_#field#isSet} = true;
+ this.{self::Class::_#field} = #t1;
+ }
+}
+class Subclass extends self::Class {
+ constructor constructor1() → self::Subclass
+ : super self::Class::constructor1()
+ ;
+ constructor constructor2(core::int value) → self::Subclass
+ : super self::Class::constructor2(value)
+ ;
+ constructor constructor3(core::int value) → self::Subclass
+ : super self::Class::constructor3(value)
+ ;
+ constructor constructor4([core::int value = #C2]) → self::Subclass
+ : super self::Class::constructor4(value)
+ ;
+}
+static method test1() → dynamic {
+ self::Class c1 = new self::Class::constructor1();
+ self::throws(() → core::int? => c1.{self::Class::field}, "Read value from uninitialized Class.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::throws(() → core::int => c1.{self::Class::field} = 17, "Write value to initialized Class.field");
+ self::Class c2 = new self::Class::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ self::throws(() → core::int => c2.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Class c3 = new self::Class::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ self::throws(() → core::int => c3.{self::Class::field} = 89, "Write value to initialized Class.field");
+ self::Class c4 = new self::Class::constructor4();
+ self::expect(42, c4.{self::Class::field});
+ self::throws(() → core::int => c4.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Class c5 = new self::Class::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ self::throws(() → core::int => c5.{self::Class::field} = 124, "Write value to initialized Class.field");
+ self::Class c6 = new self::Class::constructor1();
+ c6.{self::Class::field} = 32;
+ self::expect(32, c6.{self::Class::field});
+ self::throws(() → core::int => c6.{self::Class::field} = 32, "Write value to initialized Class.field");
+}
+static method test2() → dynamic {
+ self::Subclass c1 = new self::Subclass::constructor1();
+ self::throws(() → core::int? => c1.{self::Class::field}, "Read value from uninitialized Class1.field");
+ c1.{self::Class::field} = 16;
+ self::expect(16, c1.{self::Class::field});
+ self::throws(() → core::int => c1.{self::Class::field} = 17, "Write value to initialized Class.field");
+ self::Subclass c2 = new self::Subclass::constructor2(42);
+ self::expect(42, c2.{self::Class::field});
+ self::throws(() → core::int => c2.{self::Class::field} = 43, "Write value to initialized Class.field");
+ self::Subclass c3 = new self::Subclass::constructor3(87);
+ self::expect(88, c3.{self::Class::field});
+ self::throws(() → core::int => c3.{self::Class::field} = 89, "Write value to initialized Class.field");
+ self::Subclass c4 = new self::Subclass::constructor4();
+ self::expect(87, c4.{self::Class::field});
+ self::throws(() → core::int => c4.{self::Class::field} = 88, "Write value to initialized Class.field");
+ self::Subclass c5 = new self::Subclass::constructor4(123);
+ self::expect(123, c5.{self::Class::field});
+ self::throws(() → core::int => c5.{self::Class::field} = 124, "Write value to initialized Class.field");
+ self::Subclass c6 = new self::Subclass::constructor1();
+ c6.{self::Class::field} = 32;
+ self::expect(32, c6.{self::Class::field});
+ self::throws(() → core::int => c6.{self::Class::field} = 32, "Write value to initialized Class.field");
+}
+static method main() → dynamic {
+ self::test1();
+ self::test2();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
+
+constants {
+ #C1 = 42
+ #C2 = 87
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart
new file mode 100644
index 0000000..ba5046c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2019, 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.
+
+late int lateTopLevelField1 = 123;
+
+class Class {
+ static late int lateStaticField1 = 87;
+ static late int lateStaticField2 = 42;
+
+ static staticMethod() {
+ expect(42, lateStaticField2);
+ lateStaticField2 = 43;
+ expect(43, lateStaticField2);
+ }
+
+ late int lateInstanceField = 16;
+
+ instanceMethod() {
+ expect(16, lateInstanceField);
+ lateInstanceField = 17;
+ expect(17, lateInstanceField);
+ }
+}
+
+main() {
+ expect(123, lateTopLevelField1);
+ lateTopLevelField1 = 124;
+ expect(124, lateTopLevelField1);
+
+ expect(87, Class.lateStaticField1);
+ Class.lateStaticField1 = 88;
+ expect(88, Class.lateStaticField1);
+
+ Class.staticMethod();
+ new Class().instanceMethod();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
new file mode 100644
index 0000000..dff7386
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1;
+ static field core::int? _#lateStaticField2;
+ field core::int? _#lateInstanceField;
+ synthetic constructor •() → self::Class*
+ ;
+ static get lateStaticField1() → core::int;
+ static set lateStaticField1(core::int #t1) → void;
+ static get lateStaticField2() → core::int;
+ static set lateStaticField2(core::int #t2) → void;
+ static method staticMethod() → dynamic
+ ;
+ get lateInstanceField() → core::int;
+ set lateInstanceField(core::int #t3) → void;
+ method instanceMethod() → dynamic
+ ;
+}
+static field core::int? _#lateTopLevelField1;
+static get lateTopLevelField1() → core::int;
+static set lateTopLevelField1(core::int #t4) → void;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
new file mode 100644
index 0000000..f873e75
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
@@ -0,0 +1,53 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field core::int? _#lateStaticField2 = null;
+ field core::int? _#lateInstanceField = null;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static get lateStaticField1() → core::int
+ return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} self::Class::_#lateStaticField1 = 87 : #t1{core::int};
+ static set lateStaticField1(core::int #t2) → void
+ self::Class::_#lateStaticField1 = #t2;
+ static get lateStaticField2() → core::int
+ return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} self::Class::_#lateStaticField2 = 42 : #t3{core::int};
+ static set lateStaticField2(core::int #t4) → void
+ self::Class::_#lateStaticField2 = #t4;
+ static method staticMethod() → dynamic {
+ self::expect(42, self::Class::lateStaticField2);
+ self::Class::lateStaticField2 = 43;
+ self::expect(43, self::Class::lateStaticField2);
+ }
+ get lateInstanceField() → core::int
+ return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = 16 : #t5{core::int};
+ set lateInstanceField(core::int #t6) → void
+ this.{self::Class::_#lateInstanceField} = #t6;
+ method instanceMethod() → dynamic {
+ self::expect(16, this.{self::Class::lateInstanceField});
+ this.{self::Class::lateInstanceField} = 17;
+ self::expect(17, this.{self::Class::lateInstanceField});
+ }
+}
+static field core::int? _#lateTopLevelField1 = null;
+static get lateTopLevelField1() → core::int
+ return let final core::int? #t7 = self::_#lateTopLevelField1 in #t7.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t7{core::int};
+static set lateTopLevelField1(core::int #t8) → void
+ self::_#lateTopLevelField1 = #t8;
+static method main() → dynamic {
+ self::expect(123, self::lateTopLevelField1);
+ self::lateTopLevelField1 = 124;
+ self::expect(124, self::lateTopLevelField1);
+ self::expect(87, self::Class::lateStaticField1);
+ self::Class::lateStaticField1 = 88;
+ self::expect(88, self::Class::lateStaticField1);
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..f873e75
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
@@ -0,0 +1,53 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field core::int? _#lateStaticField2 = null;
+ field core::int? _#lateInstanceField = null;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static get lateStaticField1() → core::int
+ return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} self::Class::_#lateStaticField1 = 87 : #t1{core::int};
+ static set lateStaticField1(core::int #t2) → void
+ self::Class::_#lateStaticField1 = #t2;
+ static get lateStaticField2() → core::int
+ return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} self::Class::_#lateStaticField2 = 42 : #t3{core::int};
+ static set lateStaticField2(core::int #t4) → void
+ self::Class::_#lateStaticField2 = #t4;
+ static method staticMethod() → dynamic {
+ self::expect(42, self::Class::lateStaticField2);
+ self::Class::lateStaticField2 = 43;
+ self::expect(43, self::Class::lateStaticField2);
+ }
+ get lateInstanceField() → core::int
+ return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = 16 : #t5{core::int};
+ set lateInstanceField(core::int #t6) → void
+ this.{self::Class::_#lateInstanceField} = #t6;
+ method instanceMethod() → dynamic {
+ self::expect(16, this.{self::Class::lateInstanceField});
+ this.{self::Class::lateInstanceField} = 17;
+ self::expect(17, this.{self::Class::lateInstanceField});
+ }
+}
+static field core::int? _#lateTopLevelField1 = null;
+static get lateTopLevelField1() → core::int
+ return let final core::int? #t7 = self::_#lateTopLevelField1 in #t7.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t7{core::int};
+static set lateTopLevelField1(core::int #t8) → void
+ self::_#lateTopLevelField1 = #t8;
+static method main() → dynamic {
+ self::expect(123, self::lateTopLevelField1);
+ self::lateTopLevelField1 = 124;
+ self::expect(124, self::lateTopLevelField1);
+ self::expect(87, self::Class::lateStaticField1);
+ self::Class::lateStaticField1 = 88;
+ self::expect(88, self::Class::lateStaticField1);
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart
new file mode 100644
index 0000000..e1b36a4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2019, 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.
+
+late int lateTopLevelField;
+
+class Class {
+ static late int lateStaticField1;
+ static late int lateStaticField2;
+
+ static staticMethod() {
+ throws(() => lateStaticField2,
+ 'Read value from uninitialized Class.lateStaticField2');
+ lateStaticField2 = 42;
+ expect(42, lateStaticField2);
+ }
+
+ late int lateInstanceField;
+
+ instanceMethod() {
+ throws(() => lateInstanceField,
+ 'Read value from uninitialized Class.lateInstanceField');
+ lateInstanceField = 16;
+ expect(16, lateInstanceField);
+ }
+}
+
+main() {
+ throws(() => lateTopLevelField,
+ 'Read value from uninitialized lateTopLevelField');
+ lateTopLevelField = 123;
+ expect(123, lateTopLevelField);
+
+ throws(() => Class.lateStaticField1,
+ 'Read value from uninitialized Class.lateStaticField1');
+ Class.lateStaticField1 = 87;
+ expect(87, Class.lateStaticField1);
+
+ Class.staticMethod();
+ new Class().instanceMethod();
+
+ var c = new Class();
+ throws(() => c.lateInstanceField,
+ 'Read value from uninitialized Class.lateInstanceField');
+ c.lateInstanceField = 16;
+ expect(16, c.lateInstanceField);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..553fa89
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1;
+ static field core::int? _#lateStaticField2;
+ field core::int? _#lateInstanceField;
+ synthetic constructor •() → self::Class*
+ ;
+ static get lateStaticField1() → core::int;
+ static set lateStaticField1(core::int #t1) → void;
+ static get lateStaticField2() → core::int;
+ static set lateStaticField2(core::int #t2) → void;
+ static method staticMethod() → dynamic
+ ;
+ get lateInstanceField() → core::int;
+ set lateInstanceField(core::int #t3) → void;
+ method instanceMethod() → dynamic
+ ;
+}
+static field core::int? _#lateTopLevelField;
+static get lateTopLevelField() → core::int;
+static set lateTopLevelField(core::int #t4) → void;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..a61fbc2
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
@@ -0,0 +1,68 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field core::int? _#lateStaticField2 = null;
+ field core::int? _#lateInstanceField = null;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static get lateStaticField1() → core::int
+ return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} throw "Field 'lateStaticField1' has not been initialized." : #t1{core::int};
+ static set lateStaticField1(core::int #t2) → void
+ self::Class::_#lateStaticField1 = #t2;
+ static get lateStaticField2() → core::int
+ return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} throw "Field 'lateStaticField2' has not been initialized." : #t3{core::int};
+ static set lateStaticField2(core::int #t4) → void
+ self::Class::_#lateStaticField2 = #t4;
+ static method staticMethod() → dynamic {
+ self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
+ self::Class::lateStaticField2 = 42;
+ self::expect(42, self::Class::lateStaticField2);
+ }
+ get lateInstanceField() → core::int
+ return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} throw "Field 'lateInstanceField' has not been initialized." : #t5{core::int};
+ set lateInstanceField(core::int #t6) → void
+ this.{self::Class::_#lateInstanceField} = #t6;
+ method instanceMethod() → dynamic {
+ self::throws(() → core::int => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
+ this.{self::Class::lateInstanceField} = 16;
+ self::expect(16, this.{self::Class::lateInstanceField});
+ }
+}
+static field core::int? _#lateTopLevelField = null;
+static get lateTopLevelField() → core::int
+ return let final core::int? #t7 = self::_#lateTopLevelField in #t7.==(null) ?{core::int} throw "Field 'lateTopLevelField' has not been initialized." : #t7{core::int};
+static set lateTopLevelField(core::int #t8) → void
+ self::_#lateTopLevelField = #t8;
+static method main() → dynamic {
+ self::throws(() → core::int => self::lateTopLevelField, "Read value from uninitialized lateTopLevelField");
+ self::lateTopLevelField = 123;
+ self::expect(123, self::lateTopLevelField);
+ self::throws(() → core::int => self::Class::lateStaticField1, "Read value from uninitialized Class.lateStaticField1");
+ self::Class::lateStaticField1 = 87;
+ self::expect(87, self::Class::lateStaticField1);
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+ self::Class c = new self::Class::•();
+ self::throws(() → core::int => c.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
+ c.{self::Class::lateInstanceField} = 16;
+ self::expect(16, c.{self::Class::lateInstanceField});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..a61fbc2
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,68 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field core::int? _#lateStaticField2 = null;
+ field core::int? _#lateInstanceField = null;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static get lateStaticField1() → core::int
+ return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} throw "Field 'lateStaticField1' has not been initialized." : #t1{core::int};
+ static set lateStaticField1(core::int #t2) → void
+ self::Class::_#lateStaticField1 = #t2;
+ static get lateStaticField2() → core::int
+ return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} throw "Field 'lateStaticField2' has not been initialized." : #t3{core::int};
+ static set lateStaticField2(core::int #t4) → void
+ self::Class::_#lateStaticField2 = #t4;
+ static method staticMethod() → dynamic {
+ self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
+ self::Class::lateStaticField2 = 42;
+ self::expect(42, self::Class::lateStaticField2);
+ }
+ get lateInstanceField() → core::int
+ return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} throw "Field 'lateInstanceField' has not been initialized." : #t5{core::int};
+ set lateInstanceField(core::int #t6) → void
+ this.{self::Class::_#lateInstanceField} = #t6;
+ method instanceMethod() → dynamic {
+ self::throws(() → core::int => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
+ this.{self::Class::lateInstanceField} = 16;
+ self::expect(16, this.{self::Class::lateInstanceField});
+ }
+}
+static field core::int? _#lateTopLevelField = null;
+static get lateTopLevelField() → core::int
+ return let final core::int? #t7 = self::_#lateTopLevelField in #t7.==(null) ?{core::int} throw "Field 'lateTopLevelField' has not been initialized." : #t7{core::int};
+static set lateTopLevelField(core::int #t8) → void
+ self::_#lateTopLevelField = #t8;
+static method main() → dynamic {
+ self::throws(() → core::int => self::lateTopLevelField, "Read value from uninitialized lateTopLevelField");
+ self::lateTopLevelField = 123;
+ self::expect(123, self::lateTopLevelField);
+ self::throws(() → core::int => self::Class::lateStaticField1, "Read value from uninitialized Class.lateStaticField1");
+ self::Class::lateStaticField1 = 87;
+ self::expect(87, self::Class::lateStaticField1);
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+ self::Class c = new self::Class::•();
+ self::throws(() → core::int => c.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
+ c.{self::Class::lateInstanceField} = 16;
+ self::expect(16, c.{self::Class::lateInstanceField});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.type_promotion.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.type_promotion.expect
new file mode 100644
index 0000000..8fd2b5a
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart:40:11: Context: Write to value@1029
+ value = f();
+ ^
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart
new file mode 100644
index 0000000..0fba375
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2019, 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.
+
+int? lateTopLevelField1Init;
+int initLateTopLevelField1(int value) {
+ return lateTopLevelField1Init = value;
+}
+
+late final int lateTopLevelField1 = initLateTopLevelField1(123);
+
+class Class {
+ static int? lateStaticField1Init;
+ static int initLateStaticField1(int value) {
+ return lateStaticField1Init = value;
+ }
+
+ static late final int lateStaticField1 = initLateStaticField1(87);
+
+ static int? lateStaticField2Init;
+ static int initLateStaticField2(int value) {
+ return lateStaticField2Init = value;
+ }
+
+ static late final int lateStaticField2 = initLateStaticField2(42);
+
+ static staticMethod() {
+ expect(null, lateStaticField2Init);
+ expect(42, lateStaticField2);
+ expect(42, lateStaticField2Init);
+ }
+
+ int? lateInstanceFieldInit;
+ int initLateInstanceField(int value) {
+ return lateInstanceFieldInit = value;
+ }
+
+ late final int lateInstanceField = initLateInstanceField(16);
+
+ instanceMethod() {
+ expect(null, lateInstanceFieldInit);
+ expect(16, lateInstanceField);
+ expect(16, lateInstanceFieldInit);
+ }
+}
+
+main() {
+ expect(null, lateTopLevelField1Init);
+ expect(123, lateTopLevelField1);
+ expect(123, lateTopLevelField1Init);
+
+ expect(null, Class.lateStaticField1Init);
+ expect(87, Class.lateStaticField1);
+ expect(87, Class.lateStaticField1Init);
+
+ Class.staticMethod();
+ new Class().instanceMethod();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect
new file mode 100644
index 0000000..42bc15e
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.outline.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? lateStaticField1Init;
+ static field core::int? _#lateStaticField1;
+ static field core::int? lateStaticField2Init;
+ static field core::int? _#lateStaticField2;
+ field core::int? lateInstanceFieldInit;
+ field core::int? _#lateInstanceField;
+ synthetic constructor •() → self::Class*
+ ;
+ static method initLateStaticField1(core::int value) → core::int
+ ;
+ static get lateStaticField1() → core::int;
+ static method initLateStaticField2(core::int value) → core::int
+ ;
+ static get lateStaticField2() → core::int;
+ static method staticMethod() → dynamic
+ ;
+ method initLateInstanceField(core::int value) → core::int
+ ;
+ get lateInstanceField() → core::int;
+ method instanceMethod() → dynamic
+ ;
+}
+static field core::int? lateTopLevelField1Init;
+static field core::int? _#lateTopLevelField1;
+static method initLateTopLevelField1(core::int value) → core::int
+ ;
+static get lateTopLevelField1() → core::int;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect
new file mode 100644
index 0000000..69ddb3c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.expect
@@ -0,0 +1,61 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? lateStaticField1Init = null;
+ static field core::int? _#lateStaticField1 = null;
+ static field core::int? lateStaticField2Init = null;
+ static field core::int? _#lateStaticField2 = null;
+ field core::int? lateInstanceFieldInit = null;
+ field core::int? _#lateInstanceField = null;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static method initLateStaticField1(core::int value) → core::int {
+ return self::Class::lateStaticField1Init = value;
+ }
+ static get lateStaticField1() → core::int
+ return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} self::Class::_#lateStaticField1 = self::Class::initLateStaticField1(87) : #t1{core::int};
+ static method initLateStaticField2(core::int value) → core::int {
+ return self::Class::lateStaticField2Init = value;
+ }
+ static get lateStaticField2() → core::int
+ return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2.==(null) ?{core::int} self::Class::_#lateStaticField2 = self::Class::initLateStaticField2(42) : #t2{core::int};
+ static method staticMethod() → dynamic {
+ self::expect(null, self::Class::lateStaticField2Init);
+ self::expect(42, self::Class::lateStaticField2);
+ self::expect(42, self::Class::lateStaticField2Init);
+ }
+ method initLateInstanceField(core::int value) → core::int {
+ return this.{self::Class::lateInstanceFieldInit} = value;
+ }
+ get lateInstanceField() → core::int
+ return let final core::int? #t3 = this.{self::Class::_#lateInstanceField} in #t3.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = this.{self::Class::initLateInstanceField}(16) : #t3{core::int};
+ method instanceMethod() → dynamic {
+ self::expect(null, this.{self::Class::lateInstanceFieldInit});
+ self::expect(16, this.{self::Class::lateInstanceField});
+ self::expect(16, this.{self::Class::lateInstanceFieldInit});
+ }
+}
+static field core::int? lateTopLevelField1Init;
+static field core::int? _#lateTopLevelField1 = null;
+static method initLateTopLevelField1(core::int value) → core::int {
+ return self::lateTopLevelField1Init = value;
+}
+static get lateTopLevelField1() → core::int
+ return let final core::int? #t4 = self::_#lateTopLevelField1 in #t4.==(null) ?{core::int} self::_#lateTopLevelField1 = self::initLateTopLevelField1(123) : #t4{core::int};
+static method main() → dynamic {
+ self::expect(null, self::lateTopLevelField1Init);
+ self::expect(123, self::lateTopLevelField1);
+ self::expect(123, self::lateTopLevelField1Init);
+ self::expect(null, self::Class::lateStaticField1Init);
+ self::expect(87, self::Class::lateStaticField1);
+ self::expect(87, self::Class::lateStaticField1Init);
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..69ddb3c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.strong.transformed.expect
@@ -0,0 +1,61 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? lateStaticField1Init = null;
+ static field core::int? _#lateStaticField1 = null;
+ static field core::int? lateStaticField2Init = null;
+ static field core::int? _#lateStaticField2 = null;
+ field core::int? lateInstanceFieldInit = null;
+ field core::int? _#lateInstanceField = null;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static method initLateStaticField1(core::int value) → core::int {
+ return self::Class::lateStaticField1Init = value;
+ }
+ static get lateStaticField1() → core::int
+ return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} self::Class::_#lateStaticField1 = self::Class::initLateStaticField1(87) : #t1{core::int};
+ static method initLateStaticField2(core::int value) → core::int {
+ return self::Class::lateStaticField2Init = value;
+ }
+ static get lateStaticField2() → core::int
+ return let final core::int? #t2 = self::Class::_#lateStaticField2 in #t2.==(null) ?{core::int} self::Class::_#lateStaticField2 = self::Class::initLateStaticField2(42) : #t2{core::int};
+ static method staticMethod() → dynamic {
+ self::expect(null, self::Class::lateStaticField2Init);
+ self::expect(42, self::Class::lateStaticField2);
+ self::expect(42, self::Class::lateStaticField2Init);
+ }
+ method initLateInstanceField(core::int value) → core::int {
+ return this.{self::Class::lateInstanceFieldInit} = value;
+ }
+ get lateInstanceField() → core::int
+ return let final core::int? #t3 = this.{self::Class::_#lateInstanceField} in #t3.==(null) ?{core::int} this.{self::Class::_#lateInstanceField} = this.{self::Class::initLateInstanceField}(16) : #t3{core::int};
+ method instanceMethod() → dynamic {
+ self::expect(null, this.{self::Class::lateInstanceFieldInit});
+ self::expect(16, this.{self::Class::lateInstanceField});
+ self::expect(16, this.{self::Class::lateInstanceFieldInit});
+ }
+}
+static field core::int? lateTopLevelField1Init;
+static field core::int? _#lateTopLevelField1 = null;
+static method initLateTopLevelField1(core::int value) → core::int {
+ return self::lateTopLevelField1Init = value;
+}
+static get lateTopLevelField1() → core::int
+ return let final core::int? #t4 = self::_#lateTopLevelField1 in #t4.==(null) ?{core::int} self::_#lateTopLevelField1 = self::initLateTopLevelField1(123) : #t4{core::int};
+static method main() → dynamic {
+ self::expect(null, self::lateTopLevelField1Init);
+ self::expect(123, self::lateTopLevelField1);
+ self::expect(123, self::lateTopLevelField1Init);
+ self::expect(null, self::Class::lateStaticField1Init);
+ self::expect(87, self::Class::lateStaticField1);
+ self::expect(87, self::Class::lateStaticField1Init);
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart
new file mode 100644
index 0000000..b209f6f
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2019, 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.
+
+late final int lateTopLevelField;
+
+class Class {
+ static late final int lateStaticField1;
+ static late final int lateStaticField2;
+
+ static staticMethod() {
+ throws(() => lateStaticField2,
+ 'Read value from uninitialized Class.lateStaticField2');
+ lateStaticField2 = 42;
+ expect(42, lateStaticField2);
+ throws(() => lateStaticField2 = 43,
+ 'Write value to initialized Class.lateStaticField2');
+ }
+
+ late final int lateInstanceField;
+
+ instanceMethod() {
+ throws(() => lateInstanceField,
+ 'Read value from uninitialized Class.lateInstanceField');
+ lateInstanceField = 16;
+ expect(16, lateInstanceField);
+ throws(() => lateInstanceField = 17,
+ 'Write value to initialized Class.lateInstanceField');
+ }
+}
+
+main() {
+ throws(() => lateTopLevelField,
+ 'Read value from uninitialized lateTopLevelField');
+ lateTopLevelField = 123;
+ expect(123, lateTopLevelField);
+ throws(() => lateTopLevelField = 124,
+ 'Write value to initialized lateTopLevelField');
+
+ throws(() => Class.lateStaticField1,
+ 'Read value from uninitialized Class.lateStaticField1');
+ Class.lateStaticField1 = 87;
+ expect(87, Class.lateStaticField1);
+ throws(() => Class.lateStaticField1 = 88,
+ 'Write value to initialized Class.lateStaticField1');
+
+ Class.staticMethod();
+ new Class().instanceMethod();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..553fa89
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.outline.expect
@@ -0,0 +1,30 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1;
+ static field core::int? _#lateStaticField2;
+ field core::int? _#lateInstanceField;
+ synthetic constructor •() → self::Class*
+ ;
+ static get lateStaticField1() → core::int;
+ static set lateStaticField1(core::int #t1) → void;
+ static get lateStaticField2() → core::int;
+ static set lateStaticField2(core::int #t2) → void;
+ static method staticMethod() → dynamic
+ ;
+ get lateInstanceField() → core::int;
+ set lateInstanceField(core::int #t3) → void;
+ method instanceMethod() → dynamic
+ ;
+}
+static field core::int? _#lateTopLevelField;
+static get lateTopLevelField() → core::int;
+static set lateTopLevelField(core::int #t4) → void;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..0617737
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.expect
@@ -0,0 +1,80 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field core::int? _#lateStaticField2 = null;
+ field core::int? _#lateInstanceField = null;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static get lateStaticField1() → core::int
+ return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} throw "Field 'lateStaticField1' has not been initialized." : #t1{core::int};
+ static set lateStaticField1(core::int #t2) → void
+ if(self::Class::_#lateStaticField1.==(null))
+ self::Class::_#lateStaticField1 = #t2;
+ else
+ throw "Field 'lateStaticField1' has already been initialized.";
+ static get lateStaticField2() → core::int
+ return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} throw "Field 'lateStaticField2' has not been initialized." : #t3{core::int};
+ static set lateStaticField2(core::int #t4) → void
+ if(self::Class::_#lateStaticField2.==(null))
+ self::Class::_#lateStaticField2 = #t4;
+ else
+ throw "Field 'lateStaticField2' has already been initialized.";
+ static method staticMethod() → dynamic {
+ self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
+ self::Class::lateStaticField2 = 42;
+ self::expect(42, self::Class::lateStaticField2);
+ self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
+ }
+ get lateInstanceField() → core::int
+ return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} throw "Field 'lateInstanceField' has not been initialized." : #t5{core::int};
+ set lateInstanceField(core::int #t6) → void
+ if(this.{self::Class::_#lateInstanceField}.==(null))
+ this.{self::Class::_#lateInstanceField} = #t6;
+ else
+ throw "Field 'lateInstanceField' has already been initialized.";
+ method instanceMethod() → dynamic {
+ self::throws(() → core::int => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
+ this.{self::Class::lateInstanceField} = 16;
+ self::expect(16, this.{self::Class::lateInstanceField});
+ self::throws(() → core::int => this.{self::Class::lateInstanceField} = 17, "Write value to initialized Class.lateInstanceField");
+ }
+}
+static field core::int? _#lateTopLevelField = null;
+static get lateTopLevelField() → core::int
+ return let final core::int? #t7 = self::_#lateTopLevelField in #t7.==(null) ?{core::int} throw "Field 'lateTopLevelField' has not been initialized." : #t7{core::int};
+static set lateTopLevelField(core::int #t8) → void
+ if(self::_#lateTopLevelField.==(null))
+ self::_#lateTopLevelField = #t8;
+ else
+ throw "Field 'lateTopLevelField' has already been initialized.";
+static method main() → dynamic {
+ self::throws(() → core::int => self::lateTopLevelField, "Read value from uninitialized lateTopLevelField");
+ self::lateTopLevelField = 123;
+ self::expect(123, self::lateTopLevelField);
+ self::throws(() → core::int => self::lateTopLevelField = 124, "Write value to initialized lateTopLevelField");
+ self::throws(() → core::int => self::Class::lateStaticField1, "Read value from uninitialized Class.lateStaticField1");
+ self::Class::lateStaticField1 = 87;
+ self::expect(87, self::Class::lateStaticField1);
+ self::throws(() → core::int => self::Class::lateStaticField1 = 88, "Write value to initialized Class.lateStaticField1");
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..0617737
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,80 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field core::int? _#lateStaticField2 = null;
+ field core::int? _#lateInstanceField = null;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static get lateStaticField1() → core::int
+ return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} throw "Field 'lateStaticField1' has not been initialized." : #t1{core::int};
+ static set lateStaticField1(core::int #t2) → void
+ if(self::Class::_#lateStaticField1.==(null))
+ self::Class::_#lateStaticField1 = #t2;
+ else
+ throw "Field 'lateStaticField1' has already been initialized.";
+ static get lateStaticField2() → core::int
+ return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} throw "Field 'lateStaticField2' has not been initialized." : #t3{core::int};
+ static set lateStaticField2(core::int #t4) → void
+ if(self::Class::_#lateStaticField2.==(null))
+ self::Class::_#lateStaticField2 = #t4;
+ else
+ throw "Field 'lateStaticField2' has already been initialized.";
+ static method staticMethod() → dynamic {
+ self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
+ self::Class::lateStaticField2 = 42;
+ self::expect(42, self::Class::lateStaticField2);
+ self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
+ }
+ get lateInstanceField() → core::int
+ return let final core::int? #t5 = this.{self::Class::_#lateInstanceField} in #t5.==(null) ?{core::int} throw "Field 'lateInstanceField' has not been initialized." : #t5{core::int};
+ set lateInstanceField(core::int #t6) → void
+ if(this.{self::Class::_#lateInstanceField}.==(null))
+ this.{self::Class::_#lateInstanceField} = #t6;
+ else
+ throw "Field 'lateInstanceField' has already been initialized.";
+ method instanceMethod() → dynamic {
+ self::throws(() → core::int => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
+ this.{self::Class::lateInstanceField} = 16;
+ self::expect(16, this.{self::Class::lateInstanceField});
+ self::throws(() → core::int => this.{self::Class::lateInstanceField} = 17, "Write value to initialized Class.lateInstanceField");
+ }
+}
+static field core::int? _#lateTopLevelField = null;
+static get lateTopLevelField() → core::int
+ return let final core::int? #t7 = self::_#lateTopLevelField in #t7.==(null) ?{core::int} throw "Field 'lateTopLevelField' has not been initialized." : #t7{core::int};
+static set lateTopLevelField(core::int #t8) → void
+ if(self::_#lateTopLevelField.==(null))
+ self::_#lateTopLevelField = #t8;
+ else
+ throw "Field 'lateTopLevelField' has already been initialized.";
+static method main() → dynamic {
+ self::throws(() → core::int => self::lateTopLevelField, "Read value from uninitialized lateTopLevelField");
+ self::lateTopLevelField = 123;
+ self::expect(123, self::lateTopLevelField);
+ self::throws(() → core::int => self::lateTopLevelField = 124, "Write value to initialized lateTopLevelField");
+ self::throws(() → core::int => self::Class::lateStaticField1, "Read value from uninitialized Class.lateStaticField1");
+ self::Class::lateStaticField1 = 87;
+ self::expect(87, self::Class::lateStaticField1);
+ self::throws(() → core::int => self::Class::lateStaticField1 = 88, "Write value to initialized Class.lateStaticField1");
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.type_promotion.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.type_promotion.expect
new file mode 100644
index 0000000..1f84ecc
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart:46:11: Context: Write to value@1348
+ value = f();
+ ^
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart
new file mode 100644
index 0000000..d2a2bd7
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+main() {
+ int? lateLocalInit;
+ int initLateLocal(int value) {
+ return lateLocalInit = value;
+ }
+
+ late final int lateLocal = initLateLocal(123);
+
+ expect(null, lateLocalInit);
+ expect(123, lateLocal);
+ expect(123, lateLocalInit);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.outline.expect
new file mode 100644
index 0000000..81d34cf
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
new file mode 100644
index 0000000..3c9d2c6
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ core::int? lateLocalInit;
+ function initLateLocal(core::int value) → core::int {
+ return lateLocalInit = value;
+ }
+ final core::int? lateLocal;
+ function #lateLocal#get() → core::int
+ return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} lateLocal = initLateLocal.call(123) : #t1{core::int};
+ self::expect(null, lateLocalInit);
+ self::expect(123, #lateLocal#get.call());
+ self::expect(123, lateLocalInit);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..3c9d2c6
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.strong.transformed.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ core::int? lateLocalInit;
+ function initLateLocal(core::int value) → core::int {
+ return lateLocalInit = value;
+ }
+ final core::int? lateLocal;
+ function #lateLocal#get() → core::int
+ return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} lateLocal = initLateLocal.call(123) : #t1{core::int};
+ self::expect(null, lateLocalInit);
+ self::expect(123, #lateLocal#get.call());
+ self::expect(123, lateLocalInit);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart
new file mode 100644
index 0000000..33f43cb
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+main() {
+ late final int lateLocal;
+
+ throws(() => lateLocal, 'Read value from uninitialized lateLocal');
+ expect(123, lateLocal = 123);
+ expect(123, lateLocal);
+ throws(() => lateLocal = 124, 'Write value to initialized lateLocal');
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..9cba406
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.outline.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..904b411
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ final core::int? lateLocal;
+ function #lateLocal#get() → core::int
+ return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} throw "Local 'lateLocal' has not been initialized." : #t1{core::int};
+ function #lateLocal#set(core::int #t2) → dynamic
+ if(lateLocal.==(null))
+ return lateLocal = #t2;
+ else
+ throw "Local 'lateLocal' has already been initialized.";
+ self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
+ self::expect(123, #lateLocal#set.call(123));
+ self::expect(123, #lateLocal#get.call());
+ self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..904b411
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ final core::int? lateLocal;
+ function #lateLocal#get() → core::int
+ return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} throw "Local 'lateLocal' has not been initialized." : #t1{core::int};
+ function #lateLocal#set(core::int #t2) → dynamic
+ if(lateLocal.==(null))
+ return lateLocal = #t2;
+ else
+ throw "Local 'lateLocal' has already been initialized.";
+ self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
+ self::expect(123, #lateLocal#set.call(123));
+ self::expect(123, #lateLocal#get.call());
+ self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart
new file mode 100644
index 0000000..ff68189
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2019, 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.
+
+int? lateTopLevelField1Init;
+int? initLateTopLevelField1(int value) {
+ return lateTopLevelField1Init = value;
+}
+
+late final int? lateTopLevelField1 = initLateTopLevelField1(123);
+
+class Class {
+ static int? lateStaticField1Init;
+ static int? initLateStaticField1(int value) {
+ return lateStaticField1Init = value;
+ }
+
+ static late final int? lateStaticField1 = initLateStaticField1(87);
+
+ static int? lateStaticField2Init;
+ static int? initLateStaticField2(int value) {
+ return lateStaticField2Init = value;
+ }
+
+ static late final int? lateStaticField2 = initLateStaticField2(42);
+
+ static staticMethod() {
+ expect(null, lateStaticField2Init);
+ expect(42, lateStaticField2);
+ expect(42, lateStaticField2Init);
+ }
+
+ int? lateInstanceFieldInit;
+ int? initLateInstanceField(int value) {
+ return lateInstanceFieldInit = value;
+ }
+
+ late final int? lateInstanceField = initLateInstanceField(16);
+
+ instanceMethod() {
+ expect(null, lateInstanceFieldInit);
+ expect(16, lateInstanceField);
+ expect(16, lateInstanceFieldInit);
+ }
+}
+
+main() {
+ expect(null, lateTopLevelField1Init);
+ expect(123, lateTopLevelField1);
+ expect(123, lateTopLevelField1Init);
+
+ expect(null, Class.lateStaticField1Init);
+ expect(87, Class.lateStaticField1);
+ expect(87, Class.lateStaticField1Init);
+
+ Class.staticMethod();
+ new Class().instanceMethod();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect
new file mode 100644
index 0000000..d9b8c23
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.outline.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? lateStaticField1Init;
+ static field core::int? _#lateStaticField1;
+ static field dynamic _#lateStaticField1#isSet;
+ static field core::int? lateStaticField2Init;
+ static field core::int? _#lateStaticField2;
+ static field dynamic _#lateStaticField2#isSet;
+ field core::int? lateInstanceFieldInit;
+ field core::int? _#lateInstanceField;
+ field dynamic _#lateInstanceField#isSet;
+ synthetic constructor •() → self::Class*
+ ;
+ static method initLateStaticField1(core::int value) → core::int?
+ ;
+ static get lateStaticField1() → core::int?;
+ static method initLateStaticField2(core::int value) → core::int?
+ ;
+ static get lateStaticField2() → core::int?;
+ static method staticMethod() → dynamic
+ ;
+ method initLateInstanceField(core::int value) → core::int?
+ ;
+ get lateInstanceField() → core::int?;
+ method instanceMethod() → dynamic
+ ;
+}
+static field core::int? lateTopLevelField1Init;
+static field core::int? _#lateTopLevelField1;
+static field dynamic _#lateTopLevelField1#isSet;
+static method initLateTopLevelField1(core::int value) → core::int?
+ ;
+static get lateTopLevelField1() → core::int?;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect
new file mode 100644
index 0000000..d26702c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.expect
@@ -0,0 +1,85 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? lateStaticField1Init = null;
+ static field core::int? _#lateStaticField1 = null;
+ static field dynamic _#lateStaticField1#isSet = false;
+ static field core::int? lateStaticField2Init = null;
+ static field core::int? _#lateStaticField2 = null;
+ static field dynamic _#lateStaticField2#isSet = false;
+ field core::int? lateInstanceFieldInit = null;
+ field core::int? _#lateInstanceField = null;
+ field dynamic _#lateInstanceField#isSet = false;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static method initLateStaticField1(core::int value) → core::int? {
+ return self::Class::lateStaticField1Init = value;
+ }
+ static get lateStaticField1() → core::int? {
+ if(!self::Class::_#lateStaticField1#isSet) {
+ self::Class::_#lateStaticField1#isSet = true;
+ self::Class::_#lateStaticField1 = self::Class::initLateStaticField1(87);
+ }
+ return self::Class::_#lateStaticField1;
+ }
+ static method initLateStaticField2(core::int value) → core::int? {
+ return self::Class::lateStaticField2Init = value;
+ }
+ static get lateStaticField2() → core::int? {
+ if(!self::Class::_#lateStaticField2#isSet) {
+ self::Class::_#lateStaticField2#isSet = true;
+ self::Class::_#lateStaticField2 = self::Class::initLateStaticField2(42);
+ }
+ return self::Class::_#lateStaticField2;
+ }
+ static method staticMethod() → dynamic {
+ self::expect(null, self::Class::lateStaticField2Init);
+ self::expect(42, self::Class::lateStaticField2);
+ self::expect(42, self::Class::lateStaticField2Init);
+ }
+ method initLateInstanceField(core::int value) → core::int? {
+ return this.{self::Class::lateInstanceFieldInit} = value;
+ }
+ get lateInstanceField() → core::int? {
+ if(!this.{self::Class::_#lateInstanceField#isSet}) {
+ this.{self::Class::_#lateInstanceField#isSet} = true;
+ this.{self::Class::_#lateInstanceField} = this.{self::Class::initLateInstanceField}(16);
+ }
+ return this.{self::Class::_#lateInstanceField};
+ }
+ method instanceMethod() → dynamic {
+ self::expect(null, this.{self::Class::lateInstanceFieldInit});
+ self::expect(16, this.{self::Class::lateInstanceField});
+ self::expect(16, this.{self::Class::lateInstanceFieldInit});
+ }
+}
+static field core::int? lateTopLevelField1Init;
+static field core::int? _#lateTopLevelField1 = null;
+static field dynamic _#lateTopLevelField1#isSet = false;
+static method initLateTopLevelField1(core::int value) → core::int? {
+ return self::lateTopLevelField1Init = value;
+}
+static get lateTopLevelField1() → core::int? {
+ if(!self::_#lateTopLevelField1#isSet) {
+ self::_#lateTopLevelField1#isSet = true;
+ self::_#lateTopLevelField1 = self::initLateTopLevelField1(123);
+ }
+ return self::_#lateTopLevelField1;
+}
+static method main() → dynamic {
+ self::expect(null, self::lateTopLevelField1Init);
+ self::expect(123, self::lateTopLevelField1);
+ self::expect(123, self::lateTopLevelField1Init);
+ self::expect(null, self::Class::lateStaticField1Init);
+ self::expect(87, self::Class::lateStaticField1);
+ self::expect(87, self::Class::lateStaticField1Init);
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..d26702c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -0,0 +1,85 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? lateStaticField1Init = null;
+ static field core::int? _#lateStaticField1 = null;
+ static field dynamic _#lateStaticField1#isSet = false;
+ static field core::int? lateStaticField2Init = null;
+ static field core::int? _#lateStaticField2 = null;
+ static field dynamic _#lateStaticField2#isSet = false;
+ field core::int? lateInstanceFieldInit = null;
+ field core::int? _#lateInstanceField = null;
+ field dynamic _#lateInstanceField#isSet = false;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static method initLateStaticField1(core::int value) → core::int? {
+ return self::Class::lateStaticField1Init = value;
+ }
+ static get lateStaticField1() → core::int? {
+ if(!self::Class::_#lateStaticField1#isSet) {
+ self::Class::_#lateStaticField1#isSet = true;
+ self::Class::_#lateStaticField1 = self::Class::initLateStaticField1(87);
+ }
+ return self::Class::_#lateStaticField1;
+ }
+ static method initLateStaticField2(core::int value) → core::int? {
+ return self::Class::lateStaticField2Init = value;
+ }
+ static get lateStaticField2() → core::int? {
+ if(!self::Class::_#lateStaticField2#isSet) {
+ self::Class::_#lateStaticField2#isSet = true;
+ self::Class::_#lateStaticField2 = self::Class::initLateStaticField2(42);
+ }
+ return self::Class::_#lateStaticField2;
+ }
+ static method staticMethod() → dynamic {
+ self::expect(null, self::Class::lateStaticField2Init);
+ self::expect(42, self::Class::lateStaticField2);
+ self::expect(42, self::Class::lateStaticField2Init);
+ }
+ method initLateInstanceField(core::int value) → core::int? {
+ return this.{self::Class::lateInstanceFieldInit} = value;
+ }
+ get lateInstanceField() → core::int? {
+ if(!this.{self::Class::_#lateInstanceField#isSet}) {
+ this.{self::Class::_#lateInstanceField#isSet} = true;
+ this.{self::Class::_#lateInstanceField} = this.{self::Class::initLateInstanceField}(16);
+ }
+ return this.{self::Class::_#lateInstanceField};
+ }
+ method instanceMethod() → dynamic {
+ self::expect(null, this.{self::Class::lateInstanceFieldInit});
+ self::expect(16, this.{self::Class::lateInstanceField});
+ self::expect(16, this.{self::Class::lateInstanceFieldInit});
+ }
+}
+static field core::int? lateTopLevelField1Init;
+static field core::int? _#lateTopLevelField1 = null;
+static field dynamic _#lateTopLevelField1#isSet = false;
+static method initLateTopLevelField1(core::int value) → core::int? {
+ return self::lateTopLevelField1Init = value;
+}
+static get lateTopLevelField1() → core::int? {
+ if(!self::_#lateTopLevelField1#isSet) {
+ self::_#lateTopLevelField1#isSet = true;
+ self::_#lateTopLevelField1 = self::initLateTopLevelField1(123);
+ }
+ return self::_#lateTopLevelField1;
+}
+static method main() → dynamic {
+ self::expect(null, self::lateTopLevelField1Init);
+ self::expect(123, self::lateTopLevelField1);
+ self::expect(123, self::lateTopLevelField1Init);
+ self::expect(null, self::Class::lateStaticField1Init);
+ self::expect(87, self::Class::lateStaticField1);
+ self::expect(87, self::Class::lateStaticField1Init);
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart
new file mode 100644
index 0000000..98dcf57
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2019, 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.
+
+late final int? lateTopLevelField;
+
+class Class {
+ static late final int? lateStaticField1;
+ static late final int? lateStaticField2;
+
+ static staticMethod() {
+ throws(() => lateStaticField2,
+ 'Read value from uninitialized Class.lateStaticField2');
+ lateStaticField2 = 42;
+ expect(42, lateStaticField2);
+ throws(() => lateStaticField2 = 43,
+ 'Write value to initialized Class.lateStaticField2');
+ }
+
+ late final int? lateInstanceField;
+
+ instanceMethod() {
+ throws(() => lateInstanceField,
+ 'Read value from uninitialized Class.lateInstanceField');
+ lateInstanceField = 16;
+ expect(16, lateInstanceField);
+ throws(() => lateInstanceField = 17,
+ 'Write value to initialized Class.lateInstanceField');
+ }
+}
+
+main() {
+ throws(() => lateTopLevelField,
+ 'Read value from uninitialized lateTopLevelField');
+ lateTopLevelField = 123;
+ expect(123, lateTopLevelField);
+ throws(() => lateTopLevelField = 124,
+ 'Write value to initialized lateTopLevelField');
+
+ throws(() => Class.lateStaticField1,
+ 'Read value from uninitialized Class.lateStaticField1');
+ Class.lateStaticField1 = 87;
+ expect(87, Class.lateStaticField1);
+ throws(() => Class.lateStaticField1 = 88,
+ 'Write value to initialized Class.lateStaticField1');
+
+ Class.staticMethod();
+ new Class().instanceMethod();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..9dc7c80
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.outline.expect
@@ -0,0 +1,34 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1;
+ static field dynamic _#lateStaticField1#isSet;
+ static field core::int? _#lateStaticField2;
+ static field dynamic _#lateStaticField2#isSet;
+ field core::int? _#lateInstanceField;
+ field dynamic _#lateInstanceField#isSet;
+ synthetic constructor •() → self::Class*
+ ;
+ static get lateStaticField1() → core::int?;
+ static set lateStaticField1(core::int? #t1) → void;
+ static get lateStaticField2() → core::int?;
+ static set lateStaticField2(core::int? #t2) → void;
+ static method staticMethod() → dynamic
+ ;
+ get lateInstanceField() → core::int?;
+ set lateInstanceField(core::int? #t3) → void;
+ method instanceMethod() → dynamic
+ ;
+}
+static field core::int? _#lateTopLevelField;
+static field dynamic _#lateTopLevelField#isSet;
+static get lateTopLevelField() → core::int?;
+static set lateTopLevelField(core::int? #t4) → void;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..fff7e44
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.expect
@@ -0,0 +1,92 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field dynamic _#lateStaticField1#isSet = false;
+ static field core::int? _#lateStaticField2 = null;
+ static field dynamic _#lateStaticField2#isSet = false;
+ field core::int? _#lateInstanceField = null;
+ field dynamic _#lateInstanceField#isSet = false;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static get lateStaticField1() → core::int?
+ return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw "Field 'lateStaticField1' has not been initialized.";
+ static set lateStaticField1(core::int? #t1) → void
+ if(self::Class::_#lateStaticField1#isSet)
+ throw "Field 'lateStaticField1' has already been initialized.";
+ else {
+ self::Class::_#lateStaticField1#isSet = true;
+ self::Class::_#lateStaticField1 = #t1;
+ }
+ static get lateStaticField2() → core::int?
+ return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw "Field 'lateStaticField2' has not been initialized.";
+ static set lateStaticField2(core::int? #t2) → void
+ if(self::Class::_#lateStaticField2#isSet)
+ throw "Field 'lateStaticField2' has already been initialized.";
+ else {
+ self::Class::_#lateStaticField2#isSet = true;
+ self::Class::_#lateStaticField2 = #t2;
+ }
+ static method staticMethod() → dynamic {
+ self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
+ self::Class::lateStaticField2 = 42;
+ self::expect(42, self::Class::lateStaticField2);
+ self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
+ }
+ get lateInstanceField() → core::int?
+ return this.{self::Class::_#lateInstanceField#isSet} ?{core::int?} this.{self::Class::_#lateInstanceField} : throw "Field 'lateInstanceField' has not been initialized.";
+ set lateInstanceField(core::int? #t3) → void
+ if(this.{self::Class::_#lateInstanceField#isSet})
+ throw "Field 'lateInstanceField' has already been initialized.";
+ else {
+ this.{self::Class::_#lateInstanceField#isSet} = true;
+ this.{self::Class::_#lateInstanceField} = #t3;
+ }
+ method instanceMethod() → dynamic {
+ self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
+ this.{self::Class::lateInstanceField} = 16;
+ self::expect(16, this.{self::Class::lateInstanceField});
+ self::throws(() → core::int => this.{self::Class::lateInstanceField} = 17, "Write value to initialized Class.lateInstanceField");
+ }
+}
+static field core::int? _#lateTopLevelField = null;
+static field dynamic _#lateTopLevelField#isSet = false;
+static get lateTopLevelField() → core::int?
+ return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw "Field 'lateTopLevelField' has not been initialized.";
+static set lateTopLevelField(core::int? #t4) → void
+ if(self::_#lateTopLevelField#isSet)
+ throw "Field 'lateTopLevelField' has already been initialized.";
+ else {
+ self::_#lateTopLevelField#isSet = true;
+ self::_#lateTopLevelField = #t4;
+ }
+static method main() → dynamic {
+ self::throws(() → core::int? => self::lateTopLevelField, "Read value from uninitialized lateTopLevelField");
+ self::lateTopLevelField = 123;
+ self::expect(123, self::lateTopLevelField);
+ self::throws(() → core::int => self::lateTopLevelField = 124, "Write value to initialized lateTopLevelField");
+ self::throws(() → core::int? => self::Class::lateStaticField1, "Read value from uninitialized Class.lateStaticField1");
+ self::Class::lateStaticField1 = 87;
+ self::expect(87, self::Class::lateStaticField1);
+ self::throws(() → core::int => self::Class::lateStaticField1 = 88, "Write value to initialized Class.lateStaticField1");
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..fff7e44
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,92 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field dynamic _#lateStaticField1#isSet = false;
+ static field core::int? _#lateStaticField2 = null;
+ static field dynamic _#lateStaticField2#isSet = false;
+ field core::int? _#lateInstanceField = null;
+ field dynamic _#lateInstanceField#isSet = false;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static get lateStaticField1() → core::int?
+ return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw "Field 'lateStaticField1' has not been initialized.";
+ static set lateStaticField1(core::int? #t1) → void
+ if(self::Class::_#lateStaticField1#isSet)
+ throw "Field 'lateStaticField1' has already been initialized.";
+ else {
+ self::Class::_#lateStaticField1#isSet = true;
+ self::Class::_#lateStaticField1 = #t1;
+ }
+ static get lateStaticField2() → core::int?
+ return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw "Field 'lateStaticField2' has not been initialized.";
+ static set lateStaticField2(core::int? #t2) → void
+ if(self::Class::_#lateStaticField2#isSet)
+ throw "Field 'lateStaticField2' has already been initialized.";
+ else {
+ self::Class::_#lateStaticField2#isSet = true;
+ self::Class::_#lateStaticField2 = #t2;
+ }
+ static method staticMethod() → dynamic {
+ self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
+ self::Class::lateStaticField2 = 42;
+ self::expect(42, self::Class::lateStaticField2);
+ self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
+ }
+ get lateInstanceField() → core::int?
+ return this.{self::Class::_#lateInstanceField#isSet} ?{core::int?} this.{self::Class::_#lateInstanceField} : throw "Field 'lateInstanceField' has not been initialized.";
+ set lateInstanceField(core::int? #t3) → void
+ if(this.{self::Class::_#lateInstanceField#isSet})
+ throw "Field 'lateInstanceField' has already been initialized.";
+ else {
+ this.{self::Class::_#lateInstanceField#isSet} = true;
+ this.{self::Class::_#lateInstanceField} = #t3;
+ }
+ method instanceMethod() → dynamic {
+ self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
+ this.{self::Class::lateInstanceField} = 16;
+ self::expect(16, this.{self::Class::lateInstanceField});
+ self::throws(() → core::int => this.{self::Class::lateInstanceField} = 17, "Write value to initialized Class.lateInstanceField");
+ }
+}
+static field core::int? _#lateTopLevelField = null;
+static field dynamic _#lateTopLevelField#isSet = false;
+static get lateTopLevelField() → core::int?
+ return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw "Field 'lateTopLevelField' has not been initialized.";
+static set lateTopLevelField(core::int? #t4) → void
+ if(self::_#lateTopLevelField#isSet)
+ throw "Field 'lateTopLevelField' has already been initialized.";
+ else {
+ self::_#lateTopLevelField#isSet = true;
+ self::_#lateTopLevelField = #t4;
+ }
+static method main() → dynamic {
+ self::throws(() → core::int? => self::lateTopLevelField, "Read value from uninitialized lateTopLevelField");
+ self::lateTopLevelField = 123;
+ self::expect(123, self::lateTopLevelField);
+ self::throws(() → core::int => self::lateTopLevelField = 124, "Write value to initialized lateTopLevelField");
+ self::throws(() → core::int? => self::Class::lateStaticField1, "Read value from uninitialized Class.lateStaticField1");
+ self::Class::lateStaticField1 = 87;
+ self::expect(87, self::Class::lateStaticField1);
+ self::throws(() → core::int => self::Class::lateStaticField1 = 88, "Write value to initialized Class.lateStaticField1");
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.type_promotion.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.type_promotion.expect
new file mode 100644
index 0000000..96b2d9f
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.type_promotion.expect
@@ -0,0 +1,3 @@
+pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart:46:11: Context: Write to value@1351
+ value = f();
+ ^
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart
new file mode 100644
index 0000000..778e612
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+main() {
+ int? lateLocalInit;
+ int? initLateLocal(int? value) {
+ return lateLocalInit = value;
+ }
+
+ late final int? lateLocal = initLateLocal(123);
+
+ expect(null, lateLocalInit);
+ expect(123, lateLocal);
+ expect(123, lateLocalInit);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.outline.expect
new file mode 100644
index 0000000..81d34cf
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
new file mode 100644
index 0000000..f019032
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ core::int? lateLocalInit;
+ function initLateLocal(core::int? value) → core::int? {
+ return lateLocalInit = value;
+ }
+ final core::int? lateLocal;
+ core::bool #lateLocal#isSet = false;
+ function #lateLocal#get() → core::int? {
+ if(!#lateLocal#isSet) {
+ #lateLocal#isSet = true;
+ lateLocal = initLateLocal.call(123);
+ }
+ return lateLocal;
+ }
+ self::expect(null, lateLocalInit);
+ self::expect(123, #lateLocal#get.call());
+ self::expect(123, lateLocalInit);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..f019032
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_with_initializer.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ core::int? lateLocalInit;
+ function initLateLocal(core::int? value) → core::int? {
+ return lateLocalInit = value;
+ }
+ final core::int? lateLocal;
+ core::bool #lateLocal#isSet = false;
+ function #lateLocal#get() → core::int? {
+ if(!#lateLocal#isSet) {
+ #lateLocal#isSet = true;
+ lateLocal = initLateLocal.call(123);
+ }
+ return lateLocal;
+ }
+ self::expect(null, lateLocalInit);
+ self::expect(123, #lateLocal#get.call());
+ self::expect(123, lateLocalInit);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
new file mode 100644
index 0000000..cfa53bc
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+main() {
+ late final int? lateLocal;
+
+ throws(() => lateLocal, 'Read value from uninitialized lateLocal');
+ expect(123, lateLocal = 123);
+ expect(123, lateLocal);
+ throws(() => lateLocal = 124, 'Write value to initialized lateLocal');
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..9cba406
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.outline.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..97cbe14
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ final core::int? lateLocal;
+ core::bool #lateLocal#isSet = false;
+ function #lateLocal#get() → core::int?
+ return #lateLocal#isSet ?{core::int?} lateLocal : throw "Local 'lateLocal' has not been initialized.";
+ function #lateLocal#set(core::int? #t1) → dynamic
+ if(#lateLocal#isSet)
+ throw "Local 'lateLocal' has already been initialized.";
+ else {
+ #lateLocal#isSet = true;
+ return lateLocal = #t1;
+ }
+ self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
+ self::expect(123, #lateLocal#set.call(123));
+ self::expect(123, #lateLocal#get.call());
+ self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..97cbe14
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ final core::int? lateLocal;
+ core::bool #lateLocal#isSet = false;
+ function #lateLocal#get() → core::int?
+ return #lateLocal#isSet ?{core::int?} lateLocal : throw "Local 'lateLocal' has not been initialized.";
+ function #lateLocal#set(core::int? #t1) → dynamic
+ if(#lateLocal#isSet)
+ throw "Local 'lateLocal' has already been initialized.";
+ else {
+ #lateLocal#isSet = true;
+ return lateLocal = #t1;
+ }
+ self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
+ self::expect(123, #lateLocal#set.call(123));
+ self::expect(123, #lateLocal#get.call());
+ self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart
new file mode 100644
index 0000000..6363618
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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.
+
+main() {
+ late int lateLocal = 123;
+
+ expect(123, lateLocal);
+ expect(124, lateLocal = 124);
+ expect(124, lateLocal);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.outline.expect
new file mode 100644
index 0000000..81d34cf
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.outline.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
new file mode 100644
index 0000000..5633dbf
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ core::int? lateLocal;
+ function #lateLocal#get() → core::int
+ return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} lateLocal = 123 : #t1{core::int};
+ function #lateLocal#set(core::int #t2) → dynamic
+ return lateLocal = #t2;
+ self::expect(123, #lateLocal#get.call());
+ self::expect(124, #lateLocal#set.call(124));
+ self::expect(124, #lateLocal#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..5633dbf
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.strong.transformed.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ core::int? lateLocal;
+ function #lateLocal#get() → core::int
+ return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} lateLocal = 123 : #t1{core::int};
+ function #lateLocal#set(core::int #t2) → dynamic
+ return lateLocal = #t2;
+ self::expect(123, #lateLocal#get.call());
+ self::expect(124, #lateLocal#set.call(124));
+ self::expect(124, #lateLocal#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart
new file mode 100644
index 0000000..0cb0e98
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, 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.
+
+main() {
+ late int lateLocal;
+ throws(() => lateLocal, 'Read value from uninitialized lateLocal');
+ expect(123, lateLocal = 123);
+ expect(123, lateLocal);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..9cba406
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.outline.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..7f10865
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.expect
@@ -0,0 +1,29 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ core::int? lateLocal;
+ function #lateLocal#get() → core::int
+ return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} throw "Local 'lateLocal' has not been initialized." : #t1{core::int};
+ function #lateLocal#set(core::int #t2) → dynamic
+ return lateLocal = #t2;
+ self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
+ self::expect(123, #lateLocal#set.call(123));
+ self::expect(123, #lateLocal#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..7f10865
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,29 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ core::int? lateLocal;
+ function #lateLocal#get() → core::int
+ return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} throw "Local 'lateLocal' has not been initialized." : #t1{core::int};
+ function #lateLocal#set(core::int #t2) → dynamic
+ return lateLocal = #t2;
+ self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
+ self::expect(123, #lateLocal#set.call(123));
+ self::expect(123, #lateLocal#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart
new file mode 100644
index 0000000..fcb7572
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, 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.
+
+int? lateTopLevelField1Init() => 123;
+late int? lateTopLevelField1 = lateTopLevelField1Init();
+
+class Class {
+ static int? lateStaticField1Init() => 87;
+ static late int? lateStaticField1 = lateStaticField1Init();
+ static int? lateStaticField2Init() => 42;
+ static late int? lateStaticField2 = lateStaticField2Init();
+
+ static staticMethod() {
+ expect(42, lateStaticField2);
+ lateStaticField2 = 43;
+ expect(43, lateStaticField2);
+ }
+
+ int? lateInstanceFieldInit() => 16;
+ late int? lateInstanceField = lateInstanceFieldInit();
+
+ instanceMethod() {
+ expect(16, lateInstanceField);
+ lateInstanceField = 17;
+ expect(17, lateInstanceField);
+ }
+}
+
+main() {
+ expect(123, lateTopLevelField1);
+ lateTopLevelField1 = 124;
+ expect(124, lateTopLevelField1);
+
+ expect(87, Class.lateStaticField1);
+ Class.lateStaticField1 = 88;
+ expect(88, Class.lateStaticField1);
+
+ Class.staticMethod();
+ new Class().instanceMethod();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
new file mode 100644
index 0000000..bc10a9a
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
@@ -0,0 +1,40 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1;
+ static field dynamic _#lateStaticField1#isSet;
+ static field core::int? _#lateStaticField2;
+ static field dynamic _#lateStaticField2#isSet;
+ field core::int? _#lateInstanceField;
+ field dynamic _#lateInstanceField#isSet;
+ synthetic constructor •() → self::Class*
+ ;
+ static method lateStaticField1Init() → core::int?
+ ;
+ static get lateStaticField1() → core::int?;
+ static set lateStaticField1(core::int? #t1) → void;
+ static method lateStaticField2Init() → core::int?
+ ;
+ static get lateStaticField2() → core::int?;
+ static set lateStaticField2(core::int? #t2) → void;
+ static method staticMethod() → dynamic
+ ;
+ method lateInstanceFieldInit() → core::int?
+ ;
+ get lateInstanceField() → core::int?;
+ set lateInstanceField(core::int? #t3) → void;
+ method instanceMethod() → dynamic
+ ;
+}
+static field core::int? _#lateTopLevelField1;
+static field dynamic _#lateTopLevelField1#isSet;
+static method lateTopLevelField1Init() → core::int?
+ ;
+static get lateTopLevelField1() → core::int?;
+static set lateTopLevelField1(core::int? #t4) → void;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
new file mode 100644
index 0000000..f0f3d5a
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
@@ -0,0 +1,93 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field dynamic _#lateStaticField1#isSet = false;
+ static field core::int? _#lateStaticField2 = null;
+ static field dynamic _#lateStaticField2#isSet = false;
+ field core::int? _#lateInstanceField = null;
+ field dynamic _#lateInstanceField#isSet = false;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static method lateStaticField1Init() → core::int?
+ return 87;
+ static get lateStaticField1() → core::int? {
+ if(!self::Class::_#lateStaticField1#isSet) {
+ self::Class::_#lateStaticField1#isSet = true;
+ self::Class::_#lateStaticField1 = self::Class::lateStaticField1Init();
+ }
+ return self::Class::_#lateStaticField1;
+ }
+ static set lateStaticField1(core::int? #t1) → void {
+ self::Class::_#lateStaticField1#isSet = true;
+ self::Class::_#lateStaticField1 = #t1;
+ }
+ static method lateStaticField2Init() → core::int?
+ return 42;
+ static get lateStaticField2() → core::int? {
+ if(!self::Class::_#lateStaticField2#isSet) {
+ self::Class::_#lateStaticField2#isSet = true;
+ self::Class::_#lateStaticField2 = self::Class::lateStaticField2Init();
+ }
+ return self::Class::_#lateStaticField2;
+ }
+ static set lateStaticField2(core::int? #t2) → void {
+ self::Class::_#lateStaticField2#isSet = true;
+ self::Class::_#lateStaticField2 = #t2;
+ }
+ static method staticMethod() → dynamic {
+ self::expect(42, self::Class::lateStaticField2);
+ self::Class::lateStaticField2 = 43;
+ self::expect(43, self::Class::lateStaticField2);
+ }
+ method lateInstanceFieldInit() → core::int?
+ return 16;
+ get lateInstanceField() → core::int? {
+ if(!this.{self::Class::_#lateInstanceField#isSet}) {
+ this.{self::Class::_#lateInstanceField#isSet} = true;
+ this.{self::Class::_#lateInstanceField} = this.{self::Class::lateInstanceFieldInit}();
+ }
+ return this.{self::Class::_#lateInstanceField};
+ }
+ set lateInstanceField(core::int? #t3) → void {
+ this.{self::Class::_#lateInstanceField#isSet} = true;
+ this.{self::Class::_#lateInstanceField} = #t3;
+ }
+ method instanceMethod() → dynamic {
+ self::expect(16, this.{self::Class::lateInstanceField});
+ this.{self::Class::lateInstanceField} = 17;
+ self::expect(17, this.{self::Class::lateInstanceField});
+ }
+}
+static field core::int? _#lateTopLevelField1 = null;
+static field dynamic _#lateTopLevelField1#isSet = false;
+static method lateTopLevelField1Init() → core::int?
+ return 123;
+static get lateTopLevelField1() → core::int? {
+ if(!self::_#lateTopLevelField1#isSet) {
+ self::_#lateTopLevelField1#isSet = true;
+ self::_#lateTopLevelField1 = self::lateTopLevelField1Init();
+ }
+ return self::_#lateTopLevelField1;
+}
+static set lateTopLevelField1(core::int? #t4) → void {
+ self::_#lateTopLevelField1#isSet = true;
+ self::_#lateTopLevelField1 = #t4;
+}
+static method main() → dynamic {
+ self::expect(123, self::lateTopLevelField1);
+ self::lateTopLevelField1 = 124;
+ self::expect(124, self::lateTopLevelField1);
+ self::expect(87, self::Class::lateStaticField1);
+ self::Class::lateStaticField1 = 88;
+ self::expect(88, self::Class::lateStaticField1);
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..f0f3d5a
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -0,0 +1,93 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field dynamic _#lateStaticField1#isSet = false;
+ static field core::int? _#lateStaticField2 = null;
+ static field dynamic _#lateStaticField2#isSet = false;
+ field core::int? _#lateInstanceField = null;
+ field dynamic _#lateInstanceField#isSet = false;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static method lateStaticField1Init() → core::int?
+ return 87;
+ static get lateStaticField1() → core::int? {
+ if(!self::Class::_#lateStaticField1#isSet) {
+ self::Class::_#lateStaticField1#isSet = true;
+ self::Class::_#lateStaticField1 = self::Class::lateStaticField1Init();
+ }
+ return self::Class::_#lateStaticField1;
+ }
+ static set lateStaticField1(core::int? #t1) → void {
+ self::Class::_#lateStaticField1#isSet = true;
+ self::Class::_#lateStaticField1 = #t1;
+ }
+ static method lateStaticField2Init() → core::int?
+ return 42;
+ static get lateStaticField2() → core::int? {
+ if(!self::Class::_#lateStaticField2#isSet) {
+ self::Class::_#lateStaticField2#isSet = true;
+ self::Class::_#lateStaticField2 = self::Class::lateStaticField2Init();
+ }
+ return self::Class::_#lateStaticField2;
+ }
+ static set lateStaticField2(core::int? #t2) → void {
+ self::Class::_#lateStaticField2#isSet = true;
+ self::Class::_#lateStaticField2 = #t2;
+ }
+ static method staticMethod() → dynamic {
+ self::expect(42, self::Class::lateStaticField2);
+ self::Class::lateStaticField2 = 43;
+ self::expect(43, self::Class::lateStaticField2);
+ }
+ method lateInstanceFieldInit() → core::int?
+ return 16;
+ get lateInstanceField() → core::int? {
+ if(!this.{self::Class::_#lateInstanceField#isSet}) {
+ this.{self::Class::_#lateInstanceField#isSet} = true;
+ this.{self::Class::_#lateInstanceField} = this.{self::Class::lateInstanceFieldInit}();
+ }
+ return this.{self::Class::_#lateInstanceField};
+ }
+ set lateInstanceField(core::int? #t3) → void {
+ this.{self::Class::_#lateInstanceField#isSet} = true;
+ this.{self::Class::_#lateInstanceField} = #t3;
+ }
+ method instanceMethod() → dynamic {
+ self::expect(16, this.{self::Class::lateInstanceField});
+ this.{self::Class::lateInstanceField} = 17;
+ self::expect(17, this.{self::Class::lateInstanceField});
+ }
+}
+static field core::int? _#lateTopLevelField1 = null;
+static field dynamic _#lateTopLevelField1#isSet = false;
+static method lateTopLevelField1Init() → core::int?
+ return 123;
+static get lateTopLevelField1() → core::int? {
+ if(!self::_#lateTopLevelField1#isSet) {
+ self::_#lateTopLevelField1#isSet = true;
+ self::_#lateTopLevelField1 = self::lateTopLevelField1Init();
+ }
+ return self::_#lateTopLevelField1;
+}
+static set lateTopLevelField1(core::int? #t4) → void {
+ self::_#lateTopLevelField1#isSet = true;
+ self::_#lateTopLevelField1 = #t4;
+}
+static method main() → dynamic {
+ self::expect(123, self::lateTopLevelField1);
+ self::lateTopLevelField1 = 124;
+ self::expect(124, self::lateTopLevelField1);
+ self::expect(87, self::Class::lateStaticField1);
+ self::Class::lateStaticField1 = 88;
+ self::expect(88, self::Class::lateStaticField1);
+ self::Class::staticMethod();
+ new self::Class::•().{self::Class::instanceMethod}();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart
new file mode 100644
index 0000000..10543cc
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, 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.
+
+late int? lateTopLevelField;
+
+class Class {
+ static late int? lateStaticField1;
+ static late int? lateStaticField2;
+
+ static staticMethod() {
+ throws(() => lateStaticField2,
+ 'Read value from uninitialized Class.lateStaticField2');
+ lateStaticField2 = 42;
+ expect(42, lateStaticField2);
+ }
+
+ late int? lateInstanceField;
+
+ instanceMethod() {
+ throws(() => lateInstanceField,
+ 'Read value from uninitialized Class.lateInstanceField');
+ lateInstanceField = 16;
+ expect(16, lateInstanceField);
+ }
+}
+
+main() {
+ throws(() => lateTopLevelField,
+ 'Read value from uninitialized lateTopLevelField');
+ lateTopLevelField = 123;
+ expect(123, lateTopLevelField);
+
+ throws(() => Class.lateStaticField1,
+ 'Read value from uninitialized Class.lateStaticField1');
+ Class.lateStaticField1 = 87;
+ expect(87, Class.lateStaticField1);
+
+ Class.staticMethod();
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..9dc7c80
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
@@ -0,0 +1,34 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1;
+ static field dynamic _#lateStaticField1#isSet;
+ static field core::int? _#lateStaticField2;
+ static field dynamic _#lateStaticField2#isSet;
+ field core::int? _#lateInstanceField;
+ field dynamic _#lateInstanceField#isSet;
+ synthetic constructor •() → self::Class*
+ ;
+ static get lateStaticField1() → core::int?;
+ static set lateStaticField1(core::int? #t1) → void;
+ static get lateStaticField2() → core::int?;
+ static set lateStaticField2(core::int? #t2) → void;
+ static method staticMethod() → dynamic
+ ;
+ get lateInstanceField() → core::int?;
+ set lateInstanceField(core::int? #t3) → void;
+ method instanceMethod() → dynamic
+ ;
+}
+static field core::int? _#lateTopLevelField;
+static field dynamic _#lateTopLevelField#isSet;
+static get lateTopLevelField() → core::int?;
+static set lateTopLevelField(core::int? #t4) → void;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..68e4f55
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
@@ -0,0 +1,75 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field dynamic _#lateStaticField1#isSet = false;
+ static field core::int? _#lateStaticField2 = null;
+ static field dynamic _#lateStaticField2#isSet = false;
+ field core::int? _#lateInstanceField = null;
+ field dynamic _#lateInstanceField#isSet = false;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static get lateStaticField1() → core::int?
+ return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw "Field 'lateStaticField1' has not been initialized.";
+ static set lateStaticField1(core::int? #t1) → void {
+ self::Class::_#lateStaticField1#isSet = true;
+ self::Class::_#lateStaticField1 = #t1;
+ }
+ static get lateStaticField2() → core::int?
+ return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw "Field 'lateStaticField2' has not been initialized.";
+ static set lateStaticField2(core::int? #t2) → void {
+ self::Class::_#lateStaticField2#isSet = true;
+ self::Class::_#lateStaticField2 = #t2;
+ }
+ static method staticMethod() → dynamic {
+ self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
+ self::Class::lateStaticField2 = 42;
+ self::expect(42, self::Class::lateStaticField2);
+ }
+ get lateInstanceField() → core::int?
+ return this.{self::Class::_#lateInstanceField#isSet} ?{core::int?} this.{self::Class::_#lateInstanceField} : throw "Field 'lateInstanceField' has not been initialized.";
+ set lateInstanceField(core::int? #t3) → void {
+ this.{self::Class::_#lateInstanceField#isSet} = true;
+ this.{self::Class::_#lateInstanceField} = #t3;
+ }
+ method instanceMethod() → dynamic {
+ self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
+ this.{self::Class::lateInstanceField} = 16;
+ self::expect(16, this.{self::Class::lateInstanceField});
+ }
+}
+static field core::int? _#lateTopLevelField = null;
+static field dynamic _#lateTopLevelField#isSet = false;
+static get lateTopLevelField() → core::int?
+ return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw "Field 'lateTopLevelField' has not been initialized.";
+static set lateTopLevelField(core::int? #t4) → void {
+ self::_#lateTopLevelField#isSet = true;
+ self::_#lateTopLevelField = #t4;
+}
+static method main() → dynamic {
+ self::throws(() → core::int? => self::lateTopLevelField, "Read value from uninitialized lateTopLevelField");
+ self::lateTopLevelField = 123;
+ self::expect(123, self::lateTopLevelField);
+ self::throws(() → core::int? => self::Class::lateStaticField1, "Read value from uninitialized Class.lateStaticField1");
+ self::Class::lateStaticField1 = 87;
+ self::expect(87, self::Class::lateStaticField1);
+ self::Class::staticMethod();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..68e4f55
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,75 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ static field core::int? _#lateStaticField1 = null;
+ static field dynamic _#lateStaticField1#isSet = false;
+ static field core::int? _#lateStaticField2 = null;
+ static field dynamic _#lateStaticField2#isSet = false;
+ field core::int? _#lateInstanceField = null;
+ field dynamic _#lateInstanceField#isSet = false;
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ static get lateStaticField1() → core::int?
+ return self::Class::_#lateStaticField1#isSet ?{core::int?} self::Class::_#lateStaticField1 : throw "Field 'lateStaticField1' has not been initialized.";
+ static set lateStaticField1(core::int? #t1) → void {
+ self::Class::_#lateStaticField1#isSet = true;
+ self::Class::_#lateStaticField1 = #t1;
+ }
+ static get lateStaticField2() → core::int?
+ return self::Class::_#lateStaticField2#isSet ?{core::int?} self::Class::_#lateStaticField2 : throw "Field 'lateStaticField2' has not been initialized.";
+ static set lateStaticField2(core::int? #t2) → void {
+ self::Class::_#lateStaticField2#isSet = true;
+ self::Class::_#lateStaticField2 = #t2;
+ }
+ static method staticMethod() → dynamic {
+ self::throws(() → core::int? => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
+ self::Class::lateStaticField2 = 42;
+ self::expect(42, self::Class::lateStaticField2);
+ }
+ get lateInstanceField() → core::int?
+ return this.{self::Class::_#lateInstanceField#isSet} ?{core::int?} this.{self::Class::_#lateInstanceField} : throw "Field 'lateInstanceField' has not been initialized.";
+ set lateInstanceField(core::int? #t3) → void {
+ this.{self::Class::_#lateInstanceField#isSet} = true;
+ this.{self::Class::_#lateInstanceField} = #t3;
+ }
+ method instanceMethod() → dynamic {
+ self::throws(() → core::int? => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
+ this.{self::Class::lateInstanceField} = 16;
+ self::expect(16, this.{self::Class::lateInstanceField});
+ }
+}
+static field core::int? _#lateTopLevelField = null;
+static field dynamic _#lateTopLevelField#isSet = false;
+static get lateTopLevelField() → core::int?
+ return self::_#lateTopLevelField#isSet ?{core::int?} self::_#lateTopLevelField : throw "Field 'lateTopLevelField' has not been initialized.";
+static set lateTopLevelField(core::int? #t4) → void {
+ self::_#lateTopLevelField#isSet = true;
+ self::_#lateTopLevelField = #t4;
+}
+static method main() → dynamic {
+ self::throws(() → core::int? => self::lateTopLevelField, "Read value from uninitialized lateTopLevelField");
+ self::lateTopLevelField = 123;
+ self::expect(123, self::lateTopLevelField);
+ self::throws(() → core::int? => self::Class::lateStaticField1, "Read value from uninitialized Class.lateStaticField1");
+ self::Class::lateStaticField1 = 87;
+ self::expect(87, self::Class::lateStaticField1);
+ self::Class::staticMethod();
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart
new file mode 100644
index 0000000..a59e3f2
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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.
+
+int? lateLocalInit() => 123;
+
+main() {
+ late int? lateLocal = lateLocalInit();
+
+ expect(123, lateLocal);
+ expect(124, lateLocal = 124);
+ expect(124, lateLocal);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.outline.expect
new file mode 100644
index 0000000..bccbe28
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.outline.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method lateLocalInit() → core::int?
+ ;
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
new file mode 100644
index 0000000..850613c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method lateLocalInit() → core::int?
+ return 123;
+static method main() → dynamic {
+ core::int? lateLocal;
+ core::bool #lateLocal#isSet = false;
+ function #lateLocal#get() → core::int? {
+ if(!#lateLocal#isSet) {
+ #lateLocal#isSet = true;
+ lateLocal = self::lateLocalInit();
+ }
+ return lateLocal;
+ }
+ function #lateLocal#set(core::int? #t1) → dynamic {
+ #lateLocal#isSet = true;
+ return lateLocal = #t1;
+ }
+ self::expect(123, #lateLocal#get.call());
+ self::expect(124, #lateLocal#set.call(124));
+ self::expect(124, #lateLocal#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..850613c
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_with_initializer.dart.strong.transformed.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method lateLocalInit() → core::int?
+ return 123;
+static method main() → dynamic {
+ core::int? lateLocal;
+ core::bool #lateLocal#isSet = false;
+ function #lateLocal#get() → core::int? {
+ if(!#lateLocal#isSet) {
+ #lateLocal#isSet = true;
+ lateLocal = self::lateLocalInit();
+ }
+ return lateLocal;
+ }
+ function #lateLocal#set(core::int? #t1) → dynamic {
+ #lateLocal#isSet = true;
+ return lateLocal = #t1;
+ }
+ self::expect(123, #lateLocal#get.call());
+ self::expect(124, #lateLocal#set.call(124));
+ self::expect(124, #lateLocal#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart
new file mode 100644
index 0000000..d23214d
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, 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.
+
+main() {
+ late int? lateLocal;
+ throws(() => lateLocal, 'Read value from uninitialized lateLocal');
+ expect(123, lateLocal = 123);
+ expect(123, lateLocal);
+}
+
+expect(expected, actual) {
+ if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(f(), String message) {
+ dynamic value;
+ try {
+ value = f();
+ } catch (e) {
+ print(e);
+ return;
+ }
+ throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.outline.expect
new file mode 100644
index 0000000..9cba406
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.outline.expect
@@ -0,0 +1,10 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic
+ ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+ ;
+static method throws(() → dynamic f, core::String message) → dynamic
+ ;
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
new file mode 100644
index 0000000..7a9b940
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ core::int? lateLocal;
+ core::bool #lateLocal#isSet = false;
+ function #lateLocal#get() → core::int?
+ return #lateLocal#isSet ?{core::int?} lateLocal : throw "Local 'lateLocal' has not been initialized.";
+ function #lateLocal#set(core::int? #t1) → dynamic {
+ #lateLocal#isSet = true;
+ return lateLocal = #t1;
+ }
+ self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
+ self::expect(123, #lateLocal#set.call(123));
+ self::expect(123, #lateLocal#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
new file mode 100644
index 0000000..7a9b940
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+ core::int? lateLocal;
+ core::bool #lateLocal#isSet = false;
+ function #lateLocal#get() → core::int?
+ return #lateLocal#isSet ?{core::int?} lateLocal : throw "Local 'lateLocal' has not been initialized.";
+ function #lateLocal#set(core::int? #t1) → dynamic {
+ #lateLocal#isSet = true;
+ return lateLocal = #t1;
+ }
+ self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
+ self::expect(123, #lateLocal#set.call(123));
+ self::expect(123, #lateLocal#get.call());
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+ if(!expected.{core::Object::==}(actual))
+ throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+ dynamic value;
+ try {
+ value = f.call();
+ }
+ on dynamic catch(final dynamic e) {
+ core::print(e);
+ return;
+ }
+ throw "${message}: ${value}";
+}
diff --git a/pkg/front_end/testcases/late_lowering/test.options b/pkg/front_end/testcases/late_lowering/test.options
new file mode 100644
index 0000000..707afaf
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/test.options
@@ -0,0 +1,2 @@
+--enable-experiment=non-nullable
+--force-late-lowering
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
index 3579c0d..9ebda38 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.outline.expect
@@ -4,7 +4,7 @@
typedef F = () → void;
class A<T extends core::Object? = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::T*>*
+ synthetic constructor •() → self::A<self::A::T%>*
;
}
class B extends self::A<() →? dynamic> {
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
index 588caa0..8aab301 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.expect
@@ -4,7 +4,7 @@
typedef F = () → void;
class A<T extends core::Object? = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::T*>*
+ synthetic constructor •() → self::A<self::A::T%>*
: super core::Object::•()
;
}
diff --git a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
index 588caa0..8aab301 100644
--- a/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/function_types.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
typedef F = () → void;
class A<T extends core::Object? = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::T*>*
+ synthetic constructor •() → self::A<self::A::T%>*
: super core::Object::•()
;
}
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect
index b279e44..8d72534 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.outline.expect
@@ -23,15 +23,15 @@
;
}
class Class2<T extends core::Object? = dynamic> extends inh::LegacyClass2<self::Class2::T%> {
- synthetic constructor •() → self::Class2<self::Class2::T*>*
+ synthetic constructor •() → self::Class2<self::Class2::T%>*
;
}
class Class3a<T extends core::Object? = dynamic> extends inh::LegacyClass3<self::Class3a::T%> {
- synthetic constructor •() → self::Class3a<self::Class3a::T*>*
+ synthetic constructor •() → self::Class3a<self::Class3a::T%>*
;
}
class Class3b<T extends core::Object? = dynamic> extends inh::LegacyClass3<self::Class3b::T%> implements inh::GenericInterface<self::Class3b::T%> {
- synthetic constructor •() → self::Class3b<self::Class3b::T*>*
+ synthetic constructor •() → self::Class3b<self::Class3b::T%>*
;
}
class Class4a extends inh::LegacyClass4 {
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect
index c729feb..3b75a32 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.expect
@@ -24,17 +24,17 @@
;
}
class Class2<T extends core::Object? = dynamic> extends inh::LegacyClass2<self::Class2::T%> {
- synthetic constructor •() → self::Class2<self::Class2::T*>*
+ synthetic constructor •() → self::Class2<self::Class2::T%>*
: super inh::LegacyClass2::•()
;
}
class Class3a<T extends core::Object? = dynamic> extends inh::LegacyClass3<self::Class3a::T%> {
- synthetic constructor •() → self::Class3a<self::Class3a::T*>*
+ synthetic constructor •() → self::Class3a<self::Class3a::T%>*
: super inh::LegacyClass3::•()
;
}
class Class3b<T extends core::Object? = dynamic> extends inh::LegacyClass3<self::Class3b::T%> implements inh::GenericInterface<self::Class3b::T%> {
- synthetic constructor •() → self::Class3b<self::Class3b::T*>*
+ synthetic constructor •() → self::Class3b<self::Class3b::T%>*
: super inh::LegacyClass3::•()
;
}
diff --git a/pkg/front_end/testcases/nnbd/intersection_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/intersection_types.dart.outline.expect
index 26de83e..a1b7bfb 100644
--- a/pkg/front_end/testcases/nnbd/intersection_types.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/intersection_types.dart.outline.expect
@@ -15,7 +15,7 @@
;
}
class Foo<T extends self::A? = self::A?> extends core::Object {
- synthetic constructor •() → self::Foo<self::Foo::T*>*
+ synthetic constructor •() → self::Foo<self::Foo::T%>*
;
method doPromotionsToNullable(generic-covariant-impl self::Foo::T% t) → dynamic
;
diff --git a/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.expect
index a65870d3..4f137d3 100644
--- a/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.expect
@@ -18,7 +18,7 @@
;
}
class Foo<T extends self::A? = self::A?> extends core::Object {
- synthetic constructor •() → self::Foo<self::Foo::T*>*
+ synthetic constructor •() → self::Foo<self::Foo::T%>*
: super core::Object::•()
;
method doPromotionsToNullable(generic-covariant-impl self::Foo::T% t) → dynamic {
diff --git a/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.transformed.expect
index a65870d3..4f137d3 100644
--- a/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/intersection_types.dart.strong.transformed.expect
@@ -18,7 +18,7 @@
;
}
class Foo<T extends self::A? = self::A?> extends core::Object {
- synthetic constructor •() → self::Foo<self::Foo::T*>*
+ synthetic constructor •() → self::Foo<self::Foo::T%>*
: super core::Object::•()
;
method doPromotionsToNullable(generic-covariant-impl self::Foo::T% t) → dynamic {
diff --git a/pkg/front_end/testcases/nnbd/late.dart.strong.expect b/pkg/front_end/testcases/nnbd/late.dart.strong.expect
index 190ad8e..f22251a 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.strong.expect
@@ -80,9 +80,9 @@
static method noErrors() → dynamic {
self::lateTopLevelField = 0;
self::lateFinalTopLevelField = 0;
- self::Class* c1 = new self::Class::•();
+ self::Class c1 = new self::Class::•();
c1.{self::Class::method}();
- self::Class* c2 = new self::Class::•();
+ self::Class c2 = new self::Class::•();
c2.{self::Class::lateInstanceField} = 0;
c2.{self::Class::lateFinalInstanceField2} = 0;
self::Class::lateStaticField = 0;
@@ -92,7 +92,7 @@
invalid-expression "pkg/front_end/testcases/nnbd/late.dart:63:3: Error: Setter not found: 'lateFinalTopLevelFieldWithInit'.
lateFinalTopLevelFieldWithInit = 0;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
- self::Class* c = new self::Class::•();
+ self::Class c = new self::Class::•();
invalid-expression "pkg/front_end/testcases/nnbd/late.dart:65:5: Error: The setter 'lateFinalInstanceFieldWithInit' isn't defined for the class 'Class'.
- 'Class' is from 'pkg/front_end/testcases/nnbd/late.dart'.
Try correcting the name to the name of an existing setter, or defining a setter or field named 'lateFinalInstanceFieldWithInit'.
diff --git a/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
index 190ad8e..f22251a 100644
--- a/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/late.dart.strong.transformed.expect
@@ -80,9 +80,9 @@
static method noErrors() → dynamic {
self::lateTopLevelField = 0;
self::lateFinalTopLevelField = 0;
- self::Class* c1 = new self::Class::•();
+ self::Class c1 = new self::Class::•();
c1.{self::Class::method}();
- self::Class* c2 = new self::Class::•();
+ self::Class c2 = new self::Class::•();
c2.{self::Class::lateInstanceField} = 0;
c2.{self::Class::lateFinalInstanceField2} = 0;
self::Class::lateStaticField = 0;
@@ -92,7 +92,7 @@
invalid-expression "pkg/front_end/testcases/nnbd/late.dart:63:3: Error: Setter not found: 'lateFinalTopLevelFieldWithInit'.
lateFinalTopLevelFieldWithInit = 0;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
- self::Class* c = new self::Class::•();
+ self::Class c = new self::Class::•();
invalid-expression "pkg/front_end/testcases/nnbd/late.dart:65:5: Error: The setter 'lateFinalInstanceFieldWithInit' isn't defined for the class 'Class'.
- 'Class' is from 'pkg/front_end/testcases/nnbd/late.dart'.
Try correcting the name to the name of an existing setter, or defining a setter or field named 'lateFinalInstanceFieldWithInit'.
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart b/pkg/front_end/testcases/nnbd/null_shorting.dart
index 681c577..edf2bda 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart
@@ -95,10 +95,9 @@
}
void indexAccess(Class? c) {
- // TODO(johnniwinther): Handle null aware index access.
- //c?.[c];
- //c?.[c] = new Class();
- //c?.[c].method();
+ c?.[c];
+ c?.[c] = new Class();
+ c?.[c].method();
c?.field[c];
c?.field[c] = new Class();
c = c?.field[c] = new Class();
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
index e1af1bb..d50fc22 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
@@ -27,98 +27,101 @@
}
static method propertyAccess(self::Class? c) → void {
let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : #t1.{self::Class::field};
- let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : #t2.{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : #t3.{self::Class::field} = new self::Class::•();
+ let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class} null : #t2.{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class} null : #t3.{self::Class::field} = new self::Class::•();
let final self::Class? #t4 = c in #t4.{core::Object::==}(null) ?{self::Class?} null : #t4.{self::Class::method}();
let final self::Class? #t5 = c in #t5.{core::Object::==}(null) ?{self::Class?} null : #t5.{self::Class::field}.{self::Class::field};
- let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class*} null : #t6.{self::Class::field}.{self::Class::field} = new self::Class::•();
+ let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class} null : #t6.{self::Class::field}.{self::Class::field} = new self::Class::•();
self::throws(() → self::Class? => (let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : #t7.{self::Class::field}).{self::Class::field});
- self::throws(() → self::Class? => (let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : #t8.{self::Class::field} = new self::Class::•()).{self::Class::field});
+ self::throws(() → self::Class? => (let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class} null : #t8.{self::Class::field} = new self::Class::•()).{self::Class::field});
self::throws(() → self::Class? => (let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : #t9.{self::Class::method}()).{self::Class::field});
- c = let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : #t10.{self::Class::field}.{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class} null : #t10.{self::Class::field}.{self::Class::field} = new self::Class::•();
let final self::Class? #t11 = c in #t11.{core::Object::==}(null) ?{self::Class?} null : #t11.{self::Class::field}.{self::Class::method}();
let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : #t12.{self::Class::field} = new self::Class::•().{self::Class::field};
c = let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : #t13.{self::Class::field} = new self::Class::•().{self::Class::field};
- let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : #t14.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t15 = c in #t15.{core::Object::==}(null) ?{self::Class*} null : #t15.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class} null : #t14.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t15 = c in #t15.{core::Object::==}(null) ?{self::Class} null : #t15.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
let final self::Class? #t16 = c in #t16.{core::Object::==}(null) ?{self::Class?} null : #t16.{self::Class::field} = new self::Class::•().{self::Class::method}();
c = let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : #t17.{self::Class::field} = new self::Class::•().{self::Class::method}();
let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : #t18.{self::Class::method}().{self::Class::field};
- let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class*} null : #t19.{self::Class::method}().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class} null : #t19.{self::Class::method}().{self::Class::field} = new self::Class::•();
let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class?} null : #t20.{self::Class::method}().{self::Class::method}();
let final self::Class? #t21 = c in #t21.{core::Object::==}(null) ?{self::Class?} null : #t21.{self::Class::field}.{self::Class::field}.{self::Class::field};
- let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : #t22.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t23 = c in #t23.{core::Object::==}(null) ?{self::Class*} null : #t23.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+ let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class} null : #t22.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t23 = c in #t23.{core::Object::==}(null) ?{self::Class} null : #t23.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
let final self::Class? #t24 = c in #t24.{core::Object::==}(null) ?{self::Class?} null : #t24.{self::Class::field}.{self::Class::field}.{self::Class::method}();
let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : #t25.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : #t26.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
- let final self::Class? #t27 = c in #t27.{core::Object::==}(null) ?{self::Class*} null : #t27.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t28 = c in #t28.{core::Object::==}(null) ?{self::Class*} null : #t28.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+ let final self::Class? #t27 = c in #t27.{core::Object::==}(null) ?{self::Class} null : #t27.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t28 = c in #t28.{core::Object::==}(null) ?{self::Class} null : #t28.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : #t29.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
c = let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : #t30.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : #t31.{self::Class::method}().{self::Class::field}.{self::Class::field};
- let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class*} null : #t32.{self::Class::method}().{self::Class::field}.{self::Class::field} = new self::Class::•();
+ let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class} null : #t32.{self::Class::method}().{self::Class::field}.{self::Class::field} = new self::Class::•();
let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class?} null : #t33.{self::Class::method}().{self::Class::field}.{self::Class::method}();
let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : #t34.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
c = let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class?} null : #t35.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
- let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class*} null : #t36.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class*} null : #t37.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class} null : #t36.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class} null : #t37.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : #t38.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : #t39.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
let final self::Class? #t40 = c in #t40.{core::Object::==}(null) ?{self::Class?} null : #t40.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
c = let final self::Class? #t41 = c in #t41.{core::Object::==}(null) ?{self::Class?} null : #t41.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
- let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : #t42.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class*} null : #t43.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class} null : #t42.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class} null : #t43.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : #t44.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class?} null : #t45.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
let final self::Class? #t46 = c in #t46.{core::Object::==}(null) ?{self::Class?} null : #t46.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
c = let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class?} null : #t47.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
- let final self::Class? #t48 = c in #t48.{core::Object::==}(null) ?{self::Class*} null : #t48.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t49 = c in #t49.{core::Object::==}(null) ?{self::Class*} null : #t49.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t48 = c in #t48.{core::Object::==}(null) ?{self::Class} null : #t48.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t49 = c in #t49.{core::Object::==}(null) ?{self::Class} null : #t49.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : #t50.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : #t51.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
let final self::Class? #t52 = c in #t52.{core::Object::==}(null) ?{self::Class?} null : #t52.{self::Class::field}.{self::Class::method}().{self::Class::field};
- let final self::Class? #t53 = c in #t53.{core::Object::==}(null) ?{self::Class*} null : #t53.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class*} null : #t54.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t53 = c in #t53.{core::Object::==}(null) ?{self::Class} null : #t53.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class} null : #t54.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : #t55.{self::Class::field}.{self::Class::method}().{self::Class::method}();
let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : #t56.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
c = let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : #t57.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
- let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class*} null : #t58.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class*} null : #t59.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class} null : #t58.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class} null : #t59.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class?} null : #t60.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
c = let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : #t61.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : #t62.{self::Class::method}().{self::Class::method}().{self::Class::field};
- let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class*} null : #t63.{self::Class::method}().{self::Class::method}().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class} null : #t63.{self::Class::method}().{self::Class::method}().{self::Class::field} = new self::Class::•();
let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class?} null : #t64.{self::Class::method}().{self::Class::method}().{self::Class::method}();
}
static method indexAccess(self::Class? c) → void {
- let final self::Class? #t65 = c in #t65.{core::Object::==}(null) ?{self::Class?} null : #t65.{self::Class::field}.{self::Class::[]}(c);
- let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : #t66.{self::Class::field}.{self::Class::[]=}(c, new self::Class::•());
- c = let final self::Class? #t67 = c in #t67.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t68 = #t67.{self::Class::field} in let final self::Class? #t69 = c in let final self::Class* #t70 = new self::Class::•() in let final void #t71 = #t68.{self::Class::[]=}(#t69, #t70) in #t70;
- let final self::Class? #t72 = c in #t72.{core::Object::==}(null) ?{self::Class?} null : #t72.{self::Class::field}.{self::Class::[]}(c).{self::Class::method}();
- let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t74 = #t73.{self::Class::field} in let final self::Class? #t75 = c in #t74.{self::Class::[]=}(#t75, #t74.{self::Class::[]}(#t75).{self::Class::+}(0));
- c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = #t76.{self::Class::field} in let final self::Class? #t78 = c in let final self::Class? #t79 = #t77.{self::Class::[]}(#t78).{self::Class::+}(0) in let final void #t80 = #t77.{self::Class::[]=}(#t78, #t79) in #t79;
- let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = #t81.{self::Class::field} in let final self::Class? #t83 = c in #t82.{self::Class::[]=}(#t83, #t82.{self::Class::[]}(#t83).{self::Class::+}(1));
- c = let final self::Class? #t84 = c in #t84.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t85 = #t84.{self::Class::field} in let final self::Class? #t86 = c in let final self::Class? #t87 = #t85.{self::Class::[]}(#t86) in let final void #t88 = #t85.{self::Class::[]=}(#t86, #t87.{self::Class::+}(1)) in #t87;
- let final self::Class? #t89 = c in #t89.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t90 = #t89.{self::Class::field} in let final self::Class? #t91 = c in let final self::Class? #t92 = #t90.{self::Class::[]}(#t91).{self::Class::+}(1) in let final void #t93 = #t90.{self::Class::[]=}(#t91, #t92) in #t92;
- c = let final self::Class? #t94 = c in #t94.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t95 = #t94.{self::Class::field} in let final self::Class? #t96 = c in let final self::Class? #t97 = #t95.{self::Class::[]}(#t96).{self::Class::+}(1) in let final void #t98 = #t95.{self::Class::[]=}(#t96, #t97) in #t97;
+ let final self::Class? #t65 = c in #t65.{core::Object::==}(null) ?{self::Class?} null : #t65.{self::Class::[]}(c);
+ let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class} null : #t66.{self::Class::[]=}(c, new self::Class::•());
+ let final self::Class? #t67 = c in #t67.{core::Object::==}(null) ?{self::Class?} null : #t67.{self::Class::[]}(c).{self::Class::method}();
+ let final self::Class? #t68 = c in #t68.{core::Object::==}(null) ?{self::Class?} null : #t68.{self::Class::field}.{self::Class::[]}(c);
+ let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class} null : #t69.{self::Class::field}.{self::Class::[]=}(c, new self::Class::•());
+ c = let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class} null : let final self::Class? #t71 = #t70.{self::Class::field} in let final self::Class? #t72 = c in let final self::Class #t73 = new self::Class::•() in let final void #t74 = #t71.{self::Class::[]=}(#t72, #t73) in #t73;
+ let final self::Class? #t75 = c in #t75.{core::Object::==}(null) ?{self::Class?} null : #t75.{self::Class::field}.{self::Class::[]}(c).{self::Class::method}();
+ let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = #t76.{self::Class::field} in let final self::Class? #t78 = c in #t77.{self::Class::[]=}(#t78, #t77.{self::Class::[]}(#t78).{self::Class::+}(0));
+ c = let final self::Class? #t79 = c in #t79.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t80 = #t79.{self::Class::field} in let final self::Class? #t81 = c in let final self::Class? #t82 = #t80.{self::Class::[]}(#t81).{self::Class::+}(0) in let final void #t83 = #t80.{self::Class::[]=}(#t81, #t82) in #t82;
+ let final self::Class? #t84 = c in #t84.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t85 = #t84.{self::Class::field} in let final self::Class? #t86 = c in #t85.{self::Class::[]=}(#t86, #t85.{self::Class::[]}(#t86).{self::Class::+}(1));
+ c = let final self::Class? #t87 = c in #t87.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t88 = #t87.{self::Class::field} in let final self::Class? #t89 = c in let final self::Class? #t90 = #t88.{self::Class::[]}(#t89) in let final void #t91 = #t88.{self::Class::[]=}(#t89, #t90.{self::Class::+}(1)) in #t90;
+ let final self::Class? #t92 = c in #t92.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t93 = #t92.{self::Class::field} in let final self::Class? #t94 = c in let final self::Class? #t95 = #t93.{self::Class::[]}(#t94).{self::Class::+}(1) in let final void #t96 = #t93.{self::Class::[]=}(#t94, #t95) in #t95;
+ c = let final self::Class? #t97 = c in #t97.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t98 = #t97.{self::Class::field} in let final self::Class? #t99 = c in let final self::Class? #t100 = #t98.{self::Class::[]}(#t99).{self::Class::+}(1) in let final void #t101 = #t98.{self::Class::[]=}(#t99, #t100) in #t100;
}
static method operatorAccess(self::Class? c) → void {
- self::throws(() → self::Class? => (let final self::Class? #t99 = c in #t99.{core::Object::==}(null) ?{self::Class?} null : #t99.{self::Class::field}).{self::Class::+}(0));
- self::throws(() → self::Class? => (let final self::Class? #t100 = c in #t100.{core::Object::==}(null) ?{self::Class?} null : #t100.{self::Class::field}).{self::Class::unary-}());
- let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : #t101.{self::Class::field} = #t101.{self::Class::field}.{self::Class::+}(0);
- c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = #t102.{self::Class::field}.{self::Class::+}(0) in let final void #t104 = #t102.{self::Class::field} = #t103 in #t103;
- let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t106 = #t105.{self::Class::field} in #t106.{self::Class::field} = #t106.{self::Class::field}.{self::Class::+}(0);
- c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = #t107.{self::Class::field} in #t108.{self::Class::field} = #t108.{self::Class::field}.{self::Class::+}(0);
- let final self::Class? #t109 = c in #t109.{core::Object::==}(null) ?{self::Class?} null : #t109.{self::Class::field} = #t109.{self::Class::field}.{self::Class::+}(1);
- c = let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t111 = #t110.{self::Class::field} in let final void #t112 = #t110.{self::Class::field} = #t111.{self::Class::+}(1) in #t111;
- let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t114 = #t113.{self::Class::field}.{self::Class::+}(1) in let final void #t115 = #t113.{self::Class::field} = #t114 in #t114;
- c = let final self::Class? #t116 = c in #t116.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t117 = #t116.{self::Class::field}.{self::Class::+}(1) in let final void #t118 = #t116.{self::Class::field} = #t117 in #t117;
+ self::throws(() → self::Class? => (let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : #t102.{self::Class::field}).{self::Class::+}(0));
+ self::throws(() → self::Class? => (let final self::Class? #t103 = c in #t103.{core::Object::==}(null) ?{self::Class?} null : #t103.{self::Class::field}).{self::Class::unary-}());
+ let final self::Class? #t104 = c in #t104.{core::Object::==}(null) ?{self::Class?} null : #t104.{self::Class::field} = #t104.{self::Class::field}.{self::Class::+}(0);
+ c = let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t106 = #t105.{self::Class::field}.{self::Class::+}(0) in let final void #t107 = #t105.{self::Class::field} = #t106 in #t106;
+ let final self::Class? #t108 = c in #t108.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t109 = #t108.{self::Class::field} in #t109.{self::Class::field} = #t109.{self::Class::field}.{self::Class::+}(0);
+ c = let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t111 = #t110.{self::Class::field} in #t111.{self::Class::field} = #t111.{self::Class::field}.{self::Class::+}(0);
+ let final self::Class? #t112 = c in #t112.{core::Object::==}(null) ?{self::Class?} null : #t112.{self::Class::field} = #t112.{self::Class::field}.{self::Class::+}(1);
+ c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t114 = #t113.{self::Class::field} in let final void #t115 = #t113.{self::Class::field} = #t114.{self::Class::+}(1) in #t114;
+ let final self::Class? #t116 = c in #t116.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t117 = #t116.{self::Class::field}.{self::Class::+}(1) in let final void #t118 = #t116.{self::Class::field} = #t117 in #t117;
+ c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t120 = #t119.{self::Class::field}.{self::Class::+}(1) in let final void #t121 = #t119.{self::Class::field} = #t120 in #t120;
}
static method ifNull(self::Class? c) → void {
- let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : #t119.{self::Class::field}.{core::Object::==}(null) ?{self::Class?} #t119.{self::Class::field} = c : null;
- c = let final self::Class? #t120 = c in #t120.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t121 = #t120.{self::Class::field} in #t121.{core::Object::==}(null) ?{self::Class?} #t120.{self::Class::field} = c : #t121;
- let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t123 = #t122.{self::Class::field} in let final self::Class? #t124 = c in #t123.{self::Class::[]}(#t124).{core::Object::==}(null) ?{self::Class?} #t123.{self::Class::[]=}(#t124, c) : null;
+ let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : #t122.{self::Class::field}.{core::Object::==}(null) ?{self::Class?} #t122.{self::Class::field} = c : null;
+ c = let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t124 = #t123.{self::Class::field} in #t124.{core::Object::==}(null) ?{self::Class?} #t123.{self::Class::field} = c : #t124;
+ let final self::Class? #t125 = c in #t125.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t126 = #t125.{self::Class::field} in let final self::Class? #t127 = c in #t126.{self::Class::[]}(#t127).{core::Object::==}(null) ?{self::Class?} #t126.{self::Class::[]=}(#t127, c) : null;
}
static method throws(() → void f) → void {
try {
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
index e1af1bb..d50fc22 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
@@ -27,98 +27,101 @@
}
static method propertyAccess(self::Class? c) → void {
let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : #t1.{self::Class::field};
- let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : #t2.{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : #t3.{self::Class::field} = new self::Class::•();
+ let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class} null : #t2.{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class} null : #t3.{self::Class::field} = new self::Class::•();
let final self::Class? #t4 = c in #t4.{core::Object::==}(null) ?{self::Class?} null : #t4.{self::Class::method}();
let final self::Class? #t5 = c in #t5.{core::Object::==}(null) ?{self::Class?} null : #t5.{self::Class::field}.{self::Class::field};
- let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class*} null : #t6.{self::Class::field}.{self::Class::field} = new self::Class::•();
+ let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class} null : #t6.{self::Class::field}.{self::Class::field} = new self::Class::•();
self::throws(() → self::Class? => (let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : #t7.{self::Class::field}).{self::Class::field});
- self::throws(() → self::Class? => (let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : #t8.{self::Class::field} = new self::Class::•()).{self::Class::field});
+ self::throws(() → self::Class? => (let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class} null : #t8.{self::Class::field} = new self::Class::•()).{self::Class::field});
self::throws(() → self::Class? => (let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : #t9.{self::Class::method}()).{self::Class::field});
- c = let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : #t10.{self::Class::field}.{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class} null : #t10.{self::Class::field}.{self::Class::field} = new self::Class::•();
let final self::Class? #t11 = c in #t11.{core::Object::==}(null) ?{self::Class?} null : #t11.{self::Class::field}.{self::Class::method}();
let final self::Class? #t12 = c in #t12.{core::Object::==}(null) ?{self::Class?} null : #t12.{self::Class::field} = new self::Class::•().{self::Class::field};
c = let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : #t13.{self::Class::field} = new self::Class::•().{self::Class::field};
- let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : #t14.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t15 = c in #t15.{core::Object::==}(null) ?{self::Class*} null : #t15.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class} null : #t14.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t15 = c in #t15.{core::Object::==}(null) ?{self::Class} null : #t15.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
let final self::Class? #t16 = c in #t16.{core::Object::==}(null) ?{self::Class?} null : #t16.{self::Class::field} = new self::Class::•().{self::Class::method}();
c = let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : #t17.{self::Class::field} = new self::Class::•().{self::Class::method}();
let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : #t18.{self::Class::method}().{self::Class::field};
- let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class*} null : #t19.{self::Class::method}().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class} null : #t19.{self::Class::method}().{self::Class::field} = new self::Class::•();
let final self::Class? #t20 = c in #t20.{core::Object::==}(null) ?{self::Class?} null : #t20.{self::Class::method}().{self::Class::method}();
let final self::Class? #t21 = c in #t21.{core::Object::==}(null) ?{self::Class?} null : #t21.{self::Class::field}.{self::Class::field}.{self::Class::field};
- let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : #t22.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t23 = c in #t23.{core::Object::==}(null) ?{self::Class*} null : #t23.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+ let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class} null : #t22.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t23 = c in #t23.{core::Object::==}(null) ?{self::Class} null : #t23.{self::Class::field}.{self::Class::field}.{self::Class::field} = new self::Class::•();
let final self::Class? #t24 = c in #t24.{core::Object::==}(null) ?{self::Class?} null : #t24.{self::Class::field}.{self::Class::field}.{self::Class::method}();
let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class?} null : #t25.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
c = let final self::Class? #t26 = c in #t26.{core::Object::==}(null) ?{self::Class?} null : #t26.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field};
- let final self::Class? #t27 = c in #t27.{core::Object::==}(null) ?{self::Class*} null : #t27.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t28 = c in #t28.{core::Object::==}(null) ?{self::Class*} null : #t28.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+ let final self::Class? #t27 = c in #t27.{core::Object::==}(null) ?{self::Class} null : #t27.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t28 = c in #t28.{core::Object::==}(null) ?{self::Class} null : #t28.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::field} = new self::Class::•();
let final self::Class? #t29 = c in #t29.{core::Object::==}(null) ?{self::Class?} null : #t29.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
c = let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : #t30.{self::Class::field} = new self::Class::•().{self::Class::field}.{self::Class::method}();
let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : #t31.{self::Class::method}().{self::Class::field}.{self::Class::field};
- let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class*} null : #t32.{self::Class::method}().{self::Class::field}.{self::Class::field} = new self::Class::•();
+ let final self::Class? #t32 = c in #t32.{core::Object::==}(null) ?{self::Class} null : #t32.{self::Class::method}().{self::Class::field}.{self::Class::field} = new self::Class::•();
let final self::Class? #t33 = c in #t33.{core::Object::==}(null) ?{self::Class?} null : #t33.{self::Class::method}().{self::Class::field}.{self::Class::method}();
let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : #t34.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
c = let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class?} null : #t35.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field};
- let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class*} null : #t36.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class*} null : #t37.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class} null : #t36.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class} null : #t37.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class?} null : #t38.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class?} null : #t39.{self::Class::field}.{self::Class::field} = new self::Class::•().{self::Class::method}();
let final self::Class? #t40 = c in #t40.{core::Object::==}(null) ?{self::Class?} null : #t40.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
c = let final self::Class? #t41 = c in #t41.{core::Object::==}(null) ?{self::Class?} null : #t41.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field};
- let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class*} null : #t42.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class*} null : #t43.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class} null : #t42.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class} null : #t43.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : #t44.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
c = let final self::Class? #t45 = c in #t45.{core::Object::==}(null) ?{self::Class?} null : #t45.{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•().{self::Class::method}();
let final self::Class? #t46 = c in #t46.{core::Object::==}(null) ?{self::Class?} null : #t46.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
c = let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class?} null : #t47.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field};
- let final self::Class? #t48 = c in #t48.{core::Object::==}(null) ?{self::Class*} null : #t48.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t49 = c in #t49.{core::Object::==}(null) ?{self::Class*} null : #t49.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t48 = c in #t48.{core::Object::==}(null) ?{self::Class} null : #t48.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t49 = c in #t49.{core::Object::==}(null) ?{self::Class} null : #t49.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::field} = new self::Class::•();
let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class?} null : #t50.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
c = let final self::Class? #t51 = c in #t51.{core::Object::==}(null) ?{self::Class?} null : #t51.{self::Class::method}().{self::Class::field} = new self::Class::•().{self::Class::method}();
let final self::Class? #t52 = c in #t52.{core::Object::==}(null) ?{self::Class?} null : #t52.{self::Class::field}.{self::Class::method}().{self::Class::field};
- let final self::Class? #t53 = c in #t53.{core::Object::==}(null) ?{self::Class*} null : #t53.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class*} null : #t54.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t53 = c in #t53.{core::Object::==}(null) ?{self::Class} null : #t53.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t54 = c in #t54.{core::Object::==}(null) ?{self::Class} null : #t54.{self::Class::field}.{self::Class::method}().{self::Class::field} = new self::Class::•();
let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : #t55.{self::Class::field}.{self::Class::method}().{self::Class::method}();
let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : #t56.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
c = let final self::Class? #t57 = c in #t57.{core::Object::==}(null) ?{self::Class?} null : #t57.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field};
- let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class*} null : #t58.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
- c = let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class*} null : #t59.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t58 = c in #t58.{core::Object::==}(null) ?{self::Class} null : #t58.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
+ c = let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class} null : #t59.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::field} = new self::Class::•();
let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class?} null : #t60.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
c = let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : #t61.{self::Class::field} = new self::Class::•().{self::Class::method}().{self::Class::method}();
let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : #t62.{self::Class::method}().{self::Class::method}().{self::Class::field};
- let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class*} null : #t63.{self::Class::method}().{self::Class::method}().{self::Class::field} = new self::Class::•();
+ let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class} null : #t63.{self::Class::method}().{self::Class::method}().{self::Class::field} = new self::Class::•();
let final self::Class? #t64 = c in #t64.{core::Object::==}(null) ?{self::Class?} null : #t64.{self::Class::method}().{self::Class::method}().{self::Class::method}();
}
static method indexAccess(self::Class? c) → void {
- let final self::Class? #t65 = c in #t65.{core::Object::==}(null) ?{self::Class?} null : #t65.{self::Class::field}.{self::Class::[]}(c);
- let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : #t66.{self::Class::field}.{self::Class::[]=}(c, new self::Class::•());
- c = let final self::Class? #t67 = c in #t67.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t68 = #t67.{self::Class::field} in let final self::Class? #t69 = c in let final self::Class* #t70 = new self::Class::•() in let final void #t71 = #t68.{self::Class::[]=}(#t69, #t70) in #t70;
- let final self::Class? #t72 = c in #t72.{core::Object::==}(null) ?{self::Class?} null : #t72.{self::Class::field}.{self::Class::[]}(c).{self::Class::method}();
- let final self::Class? #t73 = c in #t73.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t74 = #t73.{self::Class::field} in let final self::Class? #t75 = c in #t74.{self::Class::[]=}(#t75, #t74.{self::Class::[]}(#t75).{self::Class::+}(0));
- c = let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = #t76.{self::Class::field} in let final self::Class? #t78 = c in let final self::Class? #t79 = #t77.{self::Class::[]}(#t78).{self::Class::+}(0) in let final void #t80 = #t77.{self::Class::[]=}(#t78, #t79) in #t79;
- let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = #t81.{self::Class::field} in let final self::Class? #t83 = c in #t82.{self::Class::[]=}(#t83, #t82.{self::Class::[]}(#t83).{self::Class::+}(1));
- c = let final self::Class? #t84 = c in #t84.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t85 = #t84.{self::Class::field} in let final self::Class? #t86 = c in let final self::Class? #t87 = #t85.{self::Class::[]}(#t86) in let final void #t88 = #t85.{self::Class::[]=}(#t86, #t87.{self::Class::+}(1)) in #t87;
- let final self::Class? #t89 = c in #t89.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t90 = #t89.{self::Class::field} in let final self::Class? #t91 = c in let final self::Class? #t92 = #t90.{self::Class::[]}(#t91).{self::Class::+}(1) in let final void #t93 = #t90.{self::Class::[]=}(#t91, #t92) in #t92;
- c = let final self::Class? #t94 = c in #t94.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t95 = #t94.{self::Class::field} in let final self::Class? #t96 = c in let final self::Class? #t97 = #t95.{self::Class::[]}(#t96).{self::Class::+}(1) in let final void #t98 = #t95.{self::Class::[]=}(#t96, #t97) in #t97;
+ let final self::Class? #t65 = c in #t65.{core::Object::==}(null) ?{self::Class?} null : #t65.{self::Class::[]}(c);
+ let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class} null : #t66.{self::Class::[]=}(c, new self::Class::•());
+ let final self::Class? #t67 = c in #t67.{core::Object::==}(null) ?{self::Class?} null : #t67.{self::Class::[]}(c).{self::Class::method}();
+ let final self::Class? #t68 = c in #t68.{core::Object::==}(null) ?{self::Class?} null : #t68.{self::Class::field}.{self::Class::[]}(c);
+ let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class} null : #t69.{self::Class::field}.{self::Class::[]=}(c, new self::Class::•());
+ c = let final self::Class? #t70 = c in #t70.{core::Object::==}(null) ?{self::Class} null : let final self::Class? #t71 = #t70.{self::Class::field} in let final self::Class? #t72 = c in let final self::Class #t73 = new self::Class::•() in let final void #t74 = #t71.{self::Class::[]=}(#t72, #t73) in #t73;
+ let final self::Class? #t75 = c in #t75.{core::Object::==}(null) ?{self::Class?} null : #t75.{self::Class::field}.{self::Class::[]}(c).{self::Class::method}();
+ let final self::Class? #t76 = c in #t76.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t77 = #t76.{self::Class::field} in let final self::Class? #t78 = c in #t77.{self::Class::[]=}(#t78, #t77.{self::Class::[]}(#t78).{self::Class::+}(0));
+ c = let final self::Class? #t79 = c in #t79.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t80 = #t79.{self::Class::field} in let final self::Class? #t81 = c in let final self::Class? #t82 = #t80.{self::Class::[]}(#t81).{self::Class::+}(0) in let final void #t83 = #t80.{self::Class::[]=}(#t81, #t82) in #t82;
+ let final self::Class? #t84 = c in #t84.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t85 = #t84.{self::Class::field} in let final self::Class? #t86 = c in #t85.{self::Class::[]=}(#t86, #t85.{self::Class::[]}(#t86).{self::Class::+}(1));
+ c = let final self::Class? #t87 = c in #t87.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t88 = #t87.{self::Class::field} in let final self::Class? #t89 = c in let final self::Class? #t90 = #t88.{self::Class::[]}(#t89) in let final void #t91 = #t88.{self::Class::[]=}(#t89, #t90.{self::Class::+}(1)) in #t90;
+ let final self::Class? #t92 = c in #t92.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t93 = #t92.{self::Class::field} in let final self::Class? #t94 = c in let final self::Class? #t95 = #t93.{self::Class::[]}(#t94).{self::Class::+}(1) in let final void #t96 = #t93.{self::Class::[]=}(#t94, #t95) in #t95;
+ c = let final self::Class? #t97 = c in #t97.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t98 = #t97.{self::Class::field} in let final self::Class? #t99 = c in let final self::Class? #t100 = #t98.{self::Class::[]}(#t99).{self::Class::+}(1) in let final void #t101 = #t98.{self::Class::[]=}(#t99, #t100) in #t100;
}
static method operatorAccess(self::Class? c) → void {
- self::throws(() → self::Class? => (let final self::Class? #t99 = c in #t99.{core::Object::==}(null) ?{self::Class?} null : #t99.{self::Class::field}).{self::Class::+}(0));
- self::throws(() → self::Class? => (let final self::Class? #t100 = c in #t100.{core::Object::==}(null) ?{self::Class?} null : #t100.{self::Class::field}).{self::Class::unary-}());
- let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : #t101.{self::Class::field} = #t101.{self::Class::field}.{self::Class::+}(0);
- c = let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t103 = #t102.{self::Class::field}.{self::Class::+}(0) in let final void #t104 = #t102.{self::Class::field} = #t103 in #t103;
- let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t106 = #t105.{self::Class::field} in #t106.{self::Class::field} = #t106.{self::Class::field}.{self::Class::+}(0);
- c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = #t107.{self::Class::field} in #t108.{self::Class::field} = #t108.{self::Class::field}.{self::Class::+}(0);
- let final self::Class? #t109 = c in #t109.{core::Object::==}(null) ?{self::Class?} null : #t109.{self::Class::field} = #t109.{self::Class::field}.{self::Class::+}(1);
- c = let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t111 = #t110.{self::Class::field} in let final void #t112 = #t110.{self::Class::field} = #t111.{self::Class::+}(1) in #t111;
- let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t114 = #t113.{self::Class::field}.{self::Class::+}(1) in let final void #t115 = #t113.{self::Class::field} = #t114 in #t114;
- c = let final self::Class? #t116 = c in #t116.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t117 = #t116.{self::Class::field}.{self::Class::+}(1) in let final void #t118 = #t116.{self::Class::field} = #t117 in #t117;
+ self::throws(() → self::Class? => (let final self::Class? #t102 = c in #t102.{core::Object::==}(null) ?{self::Class?} null : #t102.{self::Class::field}).{self::Class::+}(0));
+ self::throws(() → self::Class? => (let final self::Class? #t103 = c in #t103.{core::Object::==}(null) ?{self::Class?} null : #t103.{self::Class::field}).{self::Class::unary-}());
+ let final self::Class? #t104 = c in #t104.{core::Object::==}(null) ?{self::Class?} null : #t104.{self::Class::field} = #t104.{self::Class::field}.{self::Class::+}(0);
+ c = let final self::Class? #t105 = c in #t105.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t106 = #t105.{self::Class::field}.{self::Class::+}(0) in let final void #t107 = #t105.{self::Class::field} = #t106 in #t106;
+ let final self::Class? #t108 = c in #t108.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t109 = #t108.{self::Class::field} in #t109.{self::Class::field} = #t109.{self::Class::field}.{self::Class::+}(0);
+ c = let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t111 = #t110.{self::Class::field} in #t111.{self::Class::field} = #t111.{self::Class::field}.{self::Class::+}(0);
+ let final self::Class? #t112 = c in #t112.{core::Object::==}(null) ?{self::Class?} null : #t112.{self::Class::field} = #t112.{self::Class::field}.{self::Class::+}(1);
+ c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t114 = #t113.{self::Class::field} in let final void #t115 = #t113.{self::Class::field} = #t114.{self::Class::+}(1) in #t114;
+ let final self::Class? #t116 = c in #t116.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t117 = #t116.{self::Class::field}.{self::Class::+}(1) in let final void #t118 = #t116.{self::Class::field} = #t117 in #t117;
+ c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t120 = #t119.{self::Class::field}.{self::Class::+}(1) in let final void #t121 = #t119.{self::Class::field} = #t120 in #t120;
}
static method ifNull(self::Class? c) → void {
- let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : #t119.{self::Class::field}.{core::Object::==}(null) ?{self::Class?} #t119.{self::Class::field} = c : null;
- c = let final self::Class? #t120 = c in #t120.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t121 = #t120.{self::Class::field} in #t121.{core::Object::==}(null) ?{self::Class?} #t120.{self::Class::field} = c : #t121;
- let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t123 = #t122.{self::Class::field} in let final self::Class? #t124 = c in #t123.{self::Class::[]}(#t124).{core::Object::==}(null) ?{self::Class?} #t123.{self::Class::[]=}(#t124, c) : null;
+ let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : #t122.{self::Class::field}.{core::Object::==}(null) ?{self::Class?} #t122.{self::Class::field} = c : null;
+ c = let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t124 = #t123.{self::Class::field} in #t124.{core::Object::==}(null) ?{self::Class?} #t123.{self::Class::field} = c : #t124;
+ let final self::Class? #t125 = c in #t125.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t126 = #t125.{self::Class::field} in let final self::Class? #t127 = c in #t126.{self::Class::[]}(#t127).{core::Object::==}(null) ?{self::Class?} #t126.{self::Class::[]=}(#t127, c) : null;
}
static method throws(() → void f) → void {
try {
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart
new file mode 100644
index 0000000..5fc73745
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+class Class {
+ Class method() => this;
+}
+
+extension Extension on Class {
+ Class extensionMethod() => this;
+}
+
+main() {
+ Class? c;
+ c?..method();
+ c?..method()..method();
+ c?..extensionMethod();
+ c?..extensionMethod()..extensionMethod();
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.outline.expect
new file mode 100644
index 0000000..3538ffe
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.outline.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class*
+ ;
+ method method() → self::Class
+ ;
+}
+extension Extension on self::Class {
+ method extensionMethod = self::Extension|extensionMethod;
+ tearoff extensionMethod = self::Extension|get#extensionMethod;
+}
+static method Extension|extensionMethod(final self::Class #this) → self::Class
+ ;
+static method Extension|get#extensionMethod(final self::Class #this) → () →* self::Class
+ return () → self::Class => self::Extension|extensionMethod(#this);
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.expect
new file mode 100644
index 0000000..d51a286
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ method method() → self::Class
+ return this;
+}
+extension Extension on self::Class {
+ method extensionMethod = self::Extension|extensionMethod;
+ tearoff extensionMethod = self::Extension|get#extensionMethod;
+}
+static method Extension|extensionMethod(final self::Class #this) → self::Class
+ return #this;
+static method Extension|get#extensionMethod(final self::Class #this) → () →* self::Class
+ return () → self::Class => self::Extension|extensionMethod(#this);
+static method main() → dynamic {
+ self::Class? c;
+ let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : let final void #t2 = #t1.{self::Class::method}() in #t1;
+ let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class?} null : let final void #t4 = #t3.{self::Class::method}() in let final void #t5 = #t3.{self::Class::method}() in #t3;
+ let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : let final void #t7 = self::Extension|extensionMethod(#t6) in #t6;
+ let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class?} null : let final void #t9 = self::Extension|extensionMethod(#t8) in let final void #t10 = self::Extension|extensionMethod(#t8) in #t8;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.transformed.expect
new file mode 100644
index 0000000..d51a286
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.strong.transformed.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+ synthetic constructor •() → self::Class*
+ : super core::Object::•()
+ ;
+ method method() → self::Class
+ return this;
+}
+extension Extension on self::Class {
+ method extensionMethod = self::Extension|extensionMethod;
+ tearoff extensionMethod = self::Extension|get#extensionMethod;
+}
+static method Extension|extensionMethod(final self::Class #this) → self::Class
+ return #this;
+static method Extension|get#extensionMethod(final self::Class #this) → () →* self::Class
+ return () → self::Class => self::Extension|extensionMethod(#this);
+static method main() → dynamic {
+ self::Class? c;
+ let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : let final void #t2 = #t1.{self::Class::method}() in #t1;
+ let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class?} null : let final void #t4 = #t3.{self::Class::method}() in let final void #t5 = #t3.{self::Class::method}() in #t3;
+ let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : let final void #t7 = self::Extension|extensionMethod(#t6) in #t6;
+ let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class?} null : let final void #t9 = self::Extension|extensionMethod(#t8) in let final void #t10 = self::Extension|extensionMethod(#t8) in #t8;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart
index 68821f8..0ea13c5 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart
@@ -103,10 +103,9 @@
}
void indexAccess(Class? c) {
- // TODO(johnniwinther): Handle null aware index access.
- //Extension(c)?.[c];
- //Extension(c)?.[c] = new Class();
- //Extension(c)?.[c].method();
+ Extension(c)?.[c];
+ Extension(c)?.[c] = new Class();
+ Extension(c)?.[c].method();
Extension(c)?.field[c];
Extension(c)?.field[c] = new Class();
c = Extension(c)?.field[c] = new Class();
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
index a988b01..fc4fcc8 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
@@ -44,98 +44,101 @@
}
static method propertyAccess(self::Class? c) → void {
let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t1);
- let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t2, new self::Class::•());
- c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
+ let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t2, new self::Class::•());
+ c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
- let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
+ let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t9)));
- self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
+ self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t13)));
- c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
+ c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t17));
let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t18, self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t20 = self::Extension|get#field(new self::Class::•()) in let final void #t21 = self::Extension|set#field(#t19, #t20) in #t20;
- let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t22, let final self::Class* #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
- c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t26 = let final self::Class* #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
+ let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t22, let final self::Class #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
+ c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t26 = let final self::Class #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t30, self::Extension|method(new self::Class::•()));
c = let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t32 = self::Extension|method(new self::Class::•()) in let final void #t33 = self::Extension|set#field(#t31, #t32) in #t32;
let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t34));
- let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
+ let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t36));
let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t37)));
- let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
- c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
+ let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
+ c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t42)));
let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t43, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t45 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t46 = self::Extension|set#field(#t44, #t45) in #t45;
- let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t47, let final self::Class* #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
- c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t51 = let final self::Class* #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
+ let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t47, let final self::Class #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
+ c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t51 = let final self::Class #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t55, self::Extension|method(self::Extension|get#field(new self::Class::•())));
c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t57 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t58 = self::Extension|set#field(#t56, #t57) in #t57;
let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t59)));
- let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
+ let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t61)));
let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t62), self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t64 = self::Extension|get#field(new self::Class::•()) in let final void #t65 = self::Extension|set#field(self::Extension|get#field(#t63), #t64) in #t64;
- let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class* #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
- c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t70 = let final self::Class* #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
+ let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
+ c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t70 = let final self::Class #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
let final self::Class? #t74 = c in #t74.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t74), self::Extension|method(new self::Class::•()));
c = let final self::Class? #t75 = c in #t75.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t76 = self::Extension|method(new self::Class::•()) in let final void #t77 = self::Extension|set#field(self::Extension|get#field(#t75), #t76) in #t76;
let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t78, let final self::Class? #t79 = self::Extension|get#field(new self::Class::•()) in let final void #t80 = self::Extension|set#field(new self::Class::•(), #t79) in #t79);
c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = let final self::Class? #t83 = self::Extension|get#field(new self::Class::•()) in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(#t81, #t82) in #t82;
- let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t86, let final self::Class* #t87 = let final self::Class* #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
- c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t92 = let final self::Class* #t93 = let final self::Class* #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
+ let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t86, let final self::Class #t87 = let final self::Class #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
+ c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t92 = let final self::Class #t93 = let final self::Class #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t98, let final self::Class? #t99 = self::Extension|method(new self::Class::•()) in let final void #t100 = self::Extension|set#field(new self::Class::•(), #t99) in #t99);
c = let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = let final self::Class? #t103 = self::Extension|method(new self::Class::•()) in let final void #t104 = self::Extension|set#field(new self::Class::•(), #t103) in #t103 in let final void #t105 = self::Extension|set#field(#t101, #t102) in #t102;
let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t106), self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = self::Extension|get#field(new self::Class::•()) in let final void #t109 = self::Extension|set#field(self::Extension|method(#t107), #t108) in #t108;
- let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class* #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
- c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t114 = let final self::Class* #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
+ let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
+ c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t114 = let final self::Class #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t118), self::Extension|method(new self::Class::•()));
c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t120 = self::Extension|method(new self::Class::•()) in let final void #t121 = self::Extension|set#field(self::Extension|method(#t119), #t120) in #t120;
let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t122)));
- let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
- c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
+ let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
+ c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t127)));
let final self::Class? #t128 = c in #t128.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t128, self::Extension|get#field(self::Extension|method(new self::Class::•())));
c = let final self::Class? #t129 = c in #t129.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t130 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t131 = self::Extension|set#field(#t129, #t130) in #t130;
- let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t132, let final self::Class* #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
- c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t136 = let final self::Class* #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
+ let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t132, let final self::Class #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
+ c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t136 = let final self::Class #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t140, self::Extension|method(self::Extension|method(new self::Class::•())));
c = let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t142 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t143 = self::Extension|set#field(#t141, #t142) in #t142;
let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t144)));
- let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
+ let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
let final self::Class? #t146 = c in #t146.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t146)));
}
static method indexAccess(self::Class? c) → void {
- let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t147), c);
- let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{self::Class*} null : self::Extension|[]=(self::Extension|get#field(#t148), c, new self::Class::•());
- c = let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t150 = self::Extension|get#field(#t149) in let final self::Class? #t151 = c in let final self::Class* #t152 = new self::Class::•() in let final void #t153 = self::Extension|[]=(#t150, #t151, #t152) in #t152;
- let final self::Class? #t154 = c in #t154.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t154), c));
- let final self::Class? #t155 = c in #t155.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t156 = self::Extension|get#field(#t155) in let final self::Class? #t157 = c in self::Extension|[]=(#t156, #t157, self::Extension|+(self::Extension|[](#t156, #t157), 0));
- c = let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in let final self::Class? #t161 = self::Extension|+(self::Extension|[](#t159, #t160), 0) in let final void #t162 = self::Extension|[]=(#t159, #t160, #t161) in #t161;
- let final self::Class? #t163 = c in #t163.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t164 = self::Extension|get#field(#t163) in let final self::Class? #t165 = c in self::Extension|[]=(#t164, #t165, self::Extension|+(self::Extension|[](#t164, #t165), 1));
- c = let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|[](#t167, #t168) in let final void #t170 = self::Extension|[]=(#t167, #t168, self::Extension|+(#t169, 1)) in #t169;
- let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
- c = let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t177 = self::Extension|get#field(#t176) in let final self::Class? #t178 = c in let final self::Class? #t179 = self::Extension|+(self::Extension|[](#t177, #t178), 1) in let final void #t180 = self::Extension|[]=(#t177, #t178, #t179) in #t179;
+ let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](#t147, c);
+ let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t148, c, new self::Class::•());
+ let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](#t149, c));
+ let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t150), c);
+ let final self::Class? #t151 = c in #t151.{core::Object::==}(null) ?{self::Class} null : self::Extension|[]=(self::Extension|get#field(#t151), c, new self::Class::•());
+ c = let final self::Class? #t152 = c in #t152.{core::Object::==}(null) ?{self::Class} null : let final self::Class? #t153 = self::Extension|get#field(#t152) in let final self::Class? #t154 = c in let final self::Class #t155 = new self::Class::•() in let final void #t156 = self::Extension|[]=(#t153, #t154, #t155) in #t155;
+ let final self::Class? #t157 = c in #t157.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t157), c));
+ let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 0));
+ c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|+(self::Extension|[](#t162, #t163), 0) in let final void #t165 = self::Extension|[]=(#t162, #t163, #t164) in #t164;
+ let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in self::Extension|[]=(#t167, #t168, self::Extension|+(self::Extension|[](#t167, #t168), 1));
+ c = let final self::Class? #t169 = c in #t169.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t170 = self::Extension|get#field(#t169) in let final self::Class? #t171 = c in let final self::Class? #t172 = self::Extension|[](#t170, #t171) in let final void #t173 = self::Extension|[]=(#t170, #t171, self::Extension|+(#t172, 1)) in #t172;
+ let final self::Class? #t174 = c in #t174.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t175 = self::Extension|get#field(#t174) in let final self::Class? #t176 = c in let final self::Class? #t177 = self::Extension|+(self::Extension|[](#t175, #t176), 1) in let final void #t178 = self::Extension|[]=(#t175, #t176, #t177) in #t177;
+ c = let final self::Class? #t179 = c in #t179.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t180 = self::Extension|get#field(#t179) in let final self::Class? #t181 = c in let final self::Class? #t182 = self::Extension|+(self::Extension|[](#t180, #t181), 1) in let final void #t183 = self::Extension|[]=(#t180, #t181, #t182) in #t182;
}
static method operatorAccess(self::Class? c) → void {
- self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t181), 0));
- self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t182 = c in #t182.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t182)));
- let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t183, self::Extension|+(self::Extension|get#field(#t183), 0));
- c = let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
- let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|get#field(#t187) in self::Extension|set#field(#t188, self::Extension|+(self::Extension|get#field(#t188), 0));
- c = let final self::Class? #t189 = c in #t189.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t190 = self::Extension|get#field(#t189) in let final self::Class? #t191 = self::Extension|+(self::Extension|get#field(#t190), 0) in let final void #t192 = self::Extension|set#field(#t190, #t191) in #t191;
- let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t193, self::Extension|+(self::Extension|get#field(#t193), 1));
- c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|get#field(#t194) in let final self::Class? #t196 = let final self::Class? #t197 = self::Extension|+(#t195, 1) in let final void #t198 = self::Extension|set#field(#t194, #t197) in #t197 in #t195;
- let final self::Class? #t199 = c in #t199.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t200 = self::Extension|+(self::Extension|get#field(#t199), 1) in let final void #t201 = self::Extension|set#field(#t199, #t200) in #t200;
- c = let final self::Class? #t202 = c in #t202.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t203 = self::Extension|+(self::Extension|get#field(#t202), 1) in let final void #t204 = self::Extension|set#field(#t202, #t203) in #t203;
+ self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t184), 0));
+ self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t185 = c in #t185.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t185)));
+ let final self::Class? #t186 = c in #t186.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t186, self::Extension|+(self::Extension|get#field(#t186), 0));
+ c = let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|+(self::Extension|get#field(#t187), 0) in let final void #t189 = self::Extension|set#field(#t187, #t188) in #t188;
+ let final self::Class? #t190 = c in #t190.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t191 = self::Extension|get#field(#t190) in self::Extension|set#field(#t191, self::Extension|+(self::Extension|get#field(#t191), 0));
+ c = let final self::Class? #t192 = c in #t192.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t193 = self::Extension|get#field(#t192) in let final self::Class? #t194 = self::Extension|+(self::Extension|get#field(#t193), 0) in let final void #t195 = self::Extension|set#field(#t193, #t194) in #t194;
+ let final self::Class? #t196 = c in #t196.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t196, self::Extension|+(self::Extension|get#field(#t196), 1));
+ c = let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t198 = self::Extension|get#field(#t197) in let final self::Class? #t199 = let final self::Class? #t200 = self::Extension|+(#t198, 1) in let final void #t201 = self::Extension|set#field(#t197, #t200) in #t200 in #t198;
+ let final self::Class? #t202 = c in #t202.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t203 = self::Extension|+(self::Extension|get#field(#t202), 1) in let final void #t204 = self::Extension|set#field(#t202, #t203) in #t203;
+ c = let final self::Class? #t205 = c in #t205.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t206 = self::Extension|+(self::Extension|get#field(#t205), 1) in let final void #t207 = self::Extension|set#field(#t205, #t206) in #t206;
}
static method ifNull(self::Class? c) → void {
- let final self::Class? #t205 = c in #t205.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t205).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t205, c) : null;
- c = let final self::Class? #t206 = c in #t206.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t207 = self::Extension|get#field(#t206) in #t207.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t208 = c in let final void #t209 = self::Extension|set#field(#t206, #t208) in #t208 : #t207;
- let final self::Class? #t210 = c in #t210.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t211 = self::Extension|get#field(#t210) in let final self::Class? #t212 = c in self::Extension|[](#t211, #t212).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t211, #t212, c) : null;
+ let final self::Class? #t208 = c in #t208.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t208).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t208, c) : null;
+ c = let final self::Class? #t209 = c in #t209.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t210 = self::Extension|get#field(#t209) in #t210.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t211 = c in let final void #t212 = self::Extension|set#field(#t209, #t211) in #t211 : #t210;
+ let final self::Class? #t213 = c in #t213.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t214 = self::Extension|get#field(#t213) in let final self::Class? #t215 = c in self::Extension|[](#t214, #t215).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t214, #t215, c) : null;
}
static method throws(() → void f) → void {
try {
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
index a988b01..fc4fcc8 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
@@ -44,98 +44,101 @@
}
static method propertyAccess(self::Class? c) → void {
let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t1);
- let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t2, new self::Class::•());
- c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
+ let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t2, new self::Class::•());
+ c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
- let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
+ let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t9)));
- self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
+ self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t13)));
- c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
+ c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t17));
let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t18, self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t20 = self::Extension|get#field(new self::Class::•()) in let final void #t21 = self::Extension|set#field(#t19, #t20) in #t20;
- let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t22, let final self::Class* #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
- c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t26 = let final self::Class* #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
+ let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t22, let final self::Class #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
+ c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t26 = let final self::Class #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t30, self::Extension|method(new self::Class::•()));
c = let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t32 = self::Extension|method(new self::Class::•()) in let final void #t33 = self::Extension|set#field(#t31, #t32) in #t32;
let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t34));
- let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
+ let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t36));
let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t37)));
- let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
- c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
+ let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
+ c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t42)));
let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t43, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t45 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t46 = self::Extension|set#field(#t44, #t45) in #t45;
- let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t47, let final self::Class* #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
- c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t51 = let final self::Class* #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
+ let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t47, let final self::Class #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
+ c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t51 = let final self::Class #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t55, self::Extension|method(self::Extension|get#field(new self::Class::•())));
c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t57 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t58 = self::Extension|set#field(#t56, #t57) in #t57;
let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t59)));
- let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
+ let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t61)));
let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t62), self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t64 = self::Extension|get#field(new self::Class::•()) in let final void #t65 = self::Extension|set#field(self::Extension|get#field(#t63), #t64) in #t64;
- let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class* #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
- c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t70 = let final self::Class* #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
+ let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
+ c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t70 = let final self::Class #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
let final self::Class? #t74 = c in #t74.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t74), self::Extension|method(new self::Class::•()));
c = let final self::Class? #t75 = c in #t75.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t76 = self::Extension|method(new self::Class::•()) in let final void #t77 = self::Extension|set#field(self::Extension|get#field(#t75), #t76) in #t76;
let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t78, let final self::Class? #t79 = self::Extension|get#field(new self::Class::•()) in let final void #t80 = self::Extension|set#field(new self::Class::•(), #t79) in #t79);
c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = let final self::Class? #t83 = self::Extension|get#field(new self::Class::•()) in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(#t81, #t82) in #t82;
- let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t86, let final self::Class* #t87 = let final self::Class* #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
- c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t92 = let final self::Class* #t93 = let final self::Class* #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
+ let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t86, let final self::Class #t87 = let final self::Class #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
+ c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t92 = let final self::Class #t93 = let final self::Class #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t98, let final self::Class? #t99 = self::Extension|method(new self::Class::•()) in let final void #t100 = self::Extension|set#field(new self::Class::•(), #t99) in #t99);
c = let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = let final self::Class? #t103 = self::Extension|method(new self::Class::•()) in let final void #t104 = self::Extension|set#field(new self::Class::•(), #t103) in #t103 in let final void #t105 = self::Extension|set#field(#t101, #t102) in #t102;
let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t106), self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = self::Extension|get#field(new self::Class::•()) in let final void #t109 = self::Extension|set#field(self::Extension|method(#t107), #t108) in #t108;
- let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class* #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
- c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t114 = let final self::Class* #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
+ let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
+ c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t114 = let final self::Class #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t118), self::Extension|method(new self::Class::•()));
c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t120 = self::Extension|method(new self::Class::•()) in let final void #t121 = self::Extension|set#field(self::Extension|method(#t119), #t120) in #t120;
let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t122)));
- let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
- c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
+ let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
+ c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t127)));
let final self::Class? #t128 = c in #t128.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t128, self::Extension|get#field(self::Extension|method(new self::Class::•())));
c = let final self::Class? #t129 = c in #t129.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t130 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t131 = self::Extension|set#field(#t129, #t130) in #t130;
- let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t132, let final self::Class* #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
- c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t136 = let final self::Class* #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
+ let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t132, let final self::Class #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
+ c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t136 = let final self::Class #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t140, self::Extension|method(self::Extension|method(new self::Class::•())));
c = let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t142 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t143 = self::Extension|set#field(#t141, #t142) in #t142;
let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t144)));
- let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
+ let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
let final self::Class? #t146 = c in #t146.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t146)));
}
static method indexAccess(self::Class? c) → void {
- let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t147), c);
- let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{self::Class*} null : self::Extension|[]=(self::Extension|get#field(#t148), c, new self::Class::•());
- c = let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t150 = self::Extension|get#field(#t149) in let final self::Class? #t151 = c in let final self::Class* #t152 = new self::Class::•() in let final void #t153 = self::Extension|[]=(#t150, #t151, #t152) in #t152;
- let final self::Class? #t154 = c in #t154.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t154), c));
- let final self::Class? #t155 = c in #t155.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t156 = self::Extension|get#field(#t155) in let final self::Class? #t157 = c in self::Extension|[]=(#t156, #t157, self::Extension|+(self::Extension|[](#t156, #t157), 0));
- c = let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in let final self::Class? #t161 = self::Extension|+(self::Extension|[](#t159, #t160), 0) in let final void #t162 = self::Extension|[]=(#t159, #t160, #t161) in #t161;
- let final self::Class? #t163 = c in #t163.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t164 = self::Extension|get#field(#t163) in let final self::Class? #t165 = c in self::Extension|[]=(#t164, #t165, self::Extension|+(self::Extension|[](#t164, #t165), 1));
- c = let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|[](#t167, #t168) in let final void #t170 = self::Extension|[]=(#t167, #t168, self::Extension|+(#t169, 1)) in #t169;
- let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
- c = let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t177 = self::Extension|get#field(#t176) in let final self::Class? #t178 = c in let final self::Class? #t179 = self::Extension|+(self::Extension|[](#t177, #t178), 1) in let final void #t180 = self::Extension|[]=(#t177, #t178, #t179) in #t179;
+ let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](#t147, c);
+ let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t148, c, new self::Class::•());
+ let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](#t149, c));
+ let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t150), c);
+ let final self::Class? #t151 = c in #t151.{core::Object::==}(null) ?{self::Class} null : self::Extension|[]=(self::Extension|get#field(#t151), c, new self::Class::•());
+ c = let final self::Class? #t152 = c in #t152.{core::Object::==}(null) ?{self::Class} null : let final self::Class? #t153 = self::Extension|get#field(#t152) in let final self::Class? #t154 = c in let final self::Class #t155 = new self::Class::•() in let final void #t156 = self::Extension|[]=(#t153, #t154, #t155) in #t155;
+ let final self::Class? #t157 = c in #t157.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t157), c));
+ let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 0));
+ c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|+(self::Extension|[](#t162, #t163), 0) in let final void #t165 = self::Extension|[]=(#t162, #t163, #t164) in #t164;
+ let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in self::Extension|[]=(#t167, #t168, self::Extension|+(self::Extension|[](#t167, #t168), 1));
+ c = let final self::Class? #t169 = c in #t169.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t170 = self::Extension|get#field(#t169) in let final self::Class? #t171 = c in let final self::Class? #t172 = self::Extension|[](#t170, #t171) in let final void #t173 = self::Extension|[]=(#t170, #t171, self::Extension|+(#t172, 1)) in #t172;
+ let final self::Class? #t174 = c in #t174.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t175 = self::Extension|get#field(#t174) in let final self::Class? #t176 = c in let final self::Class? #t177 = self::Extension|+(self::Extension|[](#t175, #t176), 1) in let final void #t178 = self::Extension|[]=(#t175, #t176, #t177) in #t177;
+ c = let final self::Class? #t179 = c in #t179.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t180 = self::Extension|get#field(#t179) in let final self::Class? #t181 = c in let final self::Class? #t182 = self::Extension|+(self::Extension|[](#t180, #t181), 1) in let final void #t183 = self::Extension|[]=(#t180, #t181, #t182) in #t182;
}
static method operatorAccess(self::Class? c) → void {
- self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t181), 0));
- self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t182 = c in #t182.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t182)));
- let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t183, self::Extension|+(self::Extension|get#field(#t183), 0));
- c = let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
- let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|get#field(#t187) in self::Extension|set#field(#t188, self::Extension|+(self::Extension|get#field(#t188), 0));
- c = let final self::Class? #t189 = c in #t189.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t190 = self::Extension|get#field(#t189) in let final self::Class? #t191 = self::Extension|+(self::Extension|get#field(#t190), 0) in let final void #t192 = self::Extension|set#field(#t190, #t191) in #t191;
- let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t193, self::Extension|+(self::Extension|get#field(#t193), 1));
- c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|get#field(#t194) in let final self::Class? #t196 = let final self::Class? #t197 = self::Extension|+(#t195, 1) in let final void #t198 = self::Extension|set#field(#t194, #t197) in #t197 in #t195;
- let final self::Class? #t199 = c in #t199.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t200 = self::Extension|+(self::Extension|get#field(#t199), 1) in let final void #t201 = self::Extension|set#field(#t199, #t200) in #t200;
- c = let final self::Class? #t202 = c in #t202.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t203 = self::Extension|+(self::Extension|get#field(#t202), 1) in let final void #t204 = self::Extension|set#field(#t202, #t203) in #t203;
+ self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t184), 0));
+ self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t185 = c in #t185.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t185)));
+ let final self::Class? #t186 = c in #t186.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t186, self::Extension|+(self::Extension|get#field(#t186), 0));
+ c = let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|+(self::Extension|get#field(#t187), 0) in let final void #t189 = self::Extension|set#field(#t187, #t188) in #t188;
+ let final self::Class? #t190 = c in #t190.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t191 = self::Extension|get#field(#t190) in self::Extension|set#field(#t191, self::Extension|+(self::Extension|get#field(#t191), 0));
+ c = let final self::Class? #t192 = c in #t192.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t193 = self::Extension|get#field(#t192) in let final self::Class? #t194 = self::Extension|+(self::Extension|get#field(#t193), 0) in let final void #t195 = self::Extension|set#field(#t193, #t194) in #t194;
+ let final self::Class? #t196 = c in #t196.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t196, self::Extension|+(self::Extension|get#field(#t196), 1));
+ c = let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t198 = self::Extension|get#field(#t197) in let final self::Class? #t199 = let final self::Class? #t200 = self::Extension|+(#t198, 1) in let final void #t201 = self::Extension|set#field(#t197, #t200) in #t200 in #t198;
+ let final self::Class? #t202 = c in #t202.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t203 = self::Extension|+(self::Extension|get#field(#t202), 1) in let final void #t204 = self::Extension|set#field(#t202, #t203) in #t203;
+ c = let final self::Class? #t205 = c in #t205.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t206 = self::Extension|+(self::Extension|get#field(#t205), 1) in let final void #t207 = self::Extension|set#field(#t205, #t206) in #t206;
}
static method ifNull(self::Class? c) → void {
- let final self::Class? #t205 = c in #t205.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t205).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t205, c) : null;
- c = let final self::Class? #t206 = c in #t206.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t207 = self::Extension|get#field(#t206) in #t207.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t208 = c in let final void #t209 = self::Extension|set#field(#t206, #t208) in #t208 : #t207;
- let final self::Class? #t210 = c in #t210.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t211 = self::Extension|get#field(#t210) in let final self::Class? #t212 = c in self::Extension|[](#t211, #t212).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t211, #t212, c) : null;
+ let final self::Class? #t208 = c in #t208.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t208).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t208, c) : null;
+ c = let final self::Class? #t209 = c in #t209.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t210 = self::Extension|get#field(#t209) in #t210.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t211 = c in let final void #t212 = self::Extension|set#field(#t209, #t211) in #t211 : #t210;
+ let final self::Class? #t213 = c in #t213.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t214 = self::Extension|get#field(#t213) in let final self::Class? #t215 = c in self::Extension|[](#t214, #t215).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t214, #t215, c) : null;
}
static method throws(() → void f) → void {
try {
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart
index 25f6e4e..f7a2f33 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart
@@ -103,10 +103,9 @@
}
void indexAccess(Class? c) {
- // TODO(johnniwinther): Handle null aware index access.
- //c?.[c];
- //c?.[c] = new Class();
- //c?.[c].method();
+ c?.[c];
+ c?.[c] = new Class();
+ c?.[c].method();
c?.field[c];
c?.field[c] = new Class();
c = c?.field[c] = new Class();
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
index ac7b6fb..e45d0bc 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
@@ -44,98 +44,101 @@
}
static method propertyAccess(self::Class? c) → void {
let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t1);
- let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t2, new self::Class::•());
- c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
+ let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t2, new self::Class::•());
+ c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
- let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
+ let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t9)));
- self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
+ self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t13)));
- c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
+ c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t17));
let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t18, self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t20 = self::Extension|get#field(new self::Class::•()) in let final void #t21 = self::Extension|set#field(#t19, #t20) in #t20;
- let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t22, let final self::Class* #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
- c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t26 = let final self::Class* #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
+ let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t22, let final self::Class #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
+ c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t26 = let final self::Class #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t30, self::Extension|method(new self::Class::•()));
c = let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t32 = self::Extension|method(new self::Class::•()) in let final void #t33 = self::Extension|set#field(#t31, #t32) in #t32;
let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t34));
- let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
+ let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t36));
let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t37)));
- let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
- c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
+ let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
+ c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t42)));
let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t43, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t45 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t46 = self::Extension|set#field(#t44, #t45) in #t45;
- let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t47, let final self::Class* #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
- c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t51 = let final self::Class* #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
+ let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t47, let final self::Class #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
+ c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t51 = let final self::Class #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t55, self::Extension|method(self::Extension|get#field(new self::Class::•())));
c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t57 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t58 = self::Extension|set#field(#t56, #t57) in #t57;
let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t59)));
- let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
+ let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t61)));
let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t62), self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t64 = self::Extension|get#field(new self::Class::•()) in let final void #t65 = self::Extension|set#field(self::Extension|get#field(#t63), #t64) in #t64;
- let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class* #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
- c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t70 = let final self::Class* #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
+ let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
+ c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t70 = let final self::Class #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
let final self::Class? #t74 = c in #t74.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t74), self::Extension|method(new self::Class::•()));
c = let final self::Class? #t75 = c in #t75.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t76 = self::Extension|method(new self::Class::•()) in let final void #t77 = self::Extension|set#field(self::Extension|get#field(#t75), #t76) in #t76;
let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t78, let final self::Class? #t79 = self::Extension|get#field(new self::Class::•()) in let final void #t80 = self::Extension|set#field(new self::Class::•(), #t79) in #t79);
c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = let final self::Class? #t83 = self::Extension|get#field(new self::Class::•()) in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(#t81, #t82) in #t82;
- let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t86, let final self::Class* #t87 = let final self::Class* #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
- c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t92 = let final self::Class* #t93 = let final self::Class* #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
+ let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t86, let final self::Class #t87 = let final self::Class #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
+ c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t92 = let final self::Class #t93 = let final self::Class #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t98, let final self::Class? #t99 = self::Extension|method(new self::Class::•()) in let final void #t100 = self::Extension|set#field(new self::Class::•(), #t99) in #t99);
c = let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = let final self::Class? #t103 = self::Extension|method(new self::Class::•()) in let final void #t104 = self::Extension|set#field(new self::Class::•(), #t103) in #t103 in let final void #t105 = self::Extension|set#field(#t101, #t102) in #t102;
let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t106), self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = self::Extension|get#field(new self::Class::•()) in let final void #t109 = self::Extension|set#field(self::Extension|method(#t107), #t108) in #t108;
- let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class* #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
- c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t114 = let final self::Class* #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
+ let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
+ c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t114 = let final self::Class #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t118), self::Extension|method(new self::Class::•()));
c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t120 = self::Extension|method(new self::Class::•()) in let final void #t121 = self::Extension|set#field(self::Extension|method(#t119), #t120) in #t120;
let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t122)));
- let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
- c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
+ let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
+ c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t127)));
let final self::Class? #t128 = c in #t128.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t128, self::Extension|get#field(self::Extension|method(new self::Class::•())));
c = let final self::Class? #t129 = c in #t129.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t130 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t131 = self::Extension|set#field(#t129, #t130) in #t130;
- let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t132, let final self::Class* #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
- c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t136 = let final self::Class* #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
+ let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t132, let final self::Class #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
+ c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t136 = let final self::Class #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t140, self::Extension|method(self::Extension|method(new self::Class::•())));
c = let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t142 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t143 = self::Extension|set#field(#t141, #t142) in #t142;
let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t144)));
- let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
+ let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
let final self::Class? #t146 = c in #t146.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t146)));
}
static method indexAccess(self::Class? c) → void {
- let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t147), c);
- let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{self::Class*} null : self::Extension|[]=(self::Extension|get#field(#t148), c, new self::Class::•());
- c = let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t150 = self::Extension|get#field(#t149) in let final self::Class? #t151 = c in let final self::Class* #t152 = new self::Class::•() in let final void #t153 = self::Extension|[]=(#t150, #t151, #t152) in #t152;
- let final self::Class? #t154 = c in #t154.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t154), c));
- let final self::Class? #t155 = c in #t155.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t156 = self::Extension|get#field(#t155) in let final self::Class? #t157 = c in self::Extension|[]=(#t156, #t157, self::Extension|+(self::Extension|[](#t156, #t157), 0));
- c = let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in let final self::Class? #t161 = self::Extension|+(self::Extension|[](#t159, #t160), 0) in let final void #t162 = self::Extension|[]=(#t159, #t160, #t161) in #t161;
- let final self::Class? #t163 = c in #t163.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t164 = self::Extension|get#field(#t163) in let final self::Class? #t165 = c in self::Extension|[]=(#t164, #t165, self::Extension|+(self::Extension|[](#t164, #t165), 1));
- c = let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|[](#t167, #t168) in let final void #t170 = self::Extension|[]=(#t167, #t168, self::Extension|+(#t169, 1)) in #t169;
- let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
- c = let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t177 = self::Extension|get#field(#t176) in let final self::Class? #t178 = c in let final self::Class? #t179 = self::Extension|+(self::Extension|[](#t177, #t178), 1) in let final void #t180 = self::Extension|[]=(#t177, #t178, #t179) in #t179;
+ let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](#t147, c);
+ let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{self::Class} null : self::Extension|[]=(#t148, c, new self::Class::•());
+ let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](#t149, c));
+ let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t150), c);
+ let final self::Class? #t151 = c in #t151.{core::Object::==}(null) ?{self::Class} null : self::Extension|[]=(self::Extension|get#field(#t151), c, new self::Class::•());
+ c = let final self::Class? #t152 = c in #t152.{core::Object::==}(null) ?{self::Class} null : let final self::Class? #t153 = self::Extension|get#field(#t152) in let final self::Class? #t154 = c in let final self::Class #t155 = new self::Class::•() in let final void #t156 = self::Extension|[]=(#t153, #t154, #t155) in #t155;
+ let final self::Class? #t157 = c in #t157.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t157), c));
+ let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 0));
+ c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|+(self::Extension|[](#t162, #t163), 0) in let final void #t165 = self::Extension|[]=(#t162, #t163, #t164) in #t164;
+ let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in self::Extension|[]=(#t167, #t168, self::Extension|+(self::Extension|[](#t167, #t168), 1));
+ c = let final self::Class? #t169 = c in #t169.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t170 = self::Extension|get#field(#t169) in let final self::Class? #t171 = c in let final self::Class? #t172 = self::Extension|[](#t170, #t171) in let final void #t173 = self::Extension|[]=(#t170, #t171, self::Extension|+(#t172, 1)) in #t172;
+ let final self::Class? #t174 = c in #t174.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t175 = self::Extension|get#field(#t174) in let final self::Class? #t176 = c in let final self::Class? #t177 = self::Extension|+(self::Extension|[](#t175, #t176), 1) in let final void #t178 = self::Extension|[]=(#t175, #t176, #t177) in #t177;
+ c = let final self::Class? #t179 = c in #t179.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t180 = self::Extension|get#field(#t179) in let final self::Class? #t181 = c in let final self::Class? #t182 = self::Extension|+(self::Extension|[](#t180, #t181), 1) in let final void #t183 = self::Extension|[]=(#t180, #t181, #t182) in #t182;
}
static method operatorAccess(self::Class? c) → void {
- self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t181), 0));
- self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t182 = c in #t182.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t182)));
- let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t183, self::Extension|+(self::Extension|get#field(#t183), 0));
- c = let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
- let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|get#field(#t187) in self::Extension|set#field(#t188, self::Extension|+(self::Extension|get#field(#t188), 0));
- c = let final self::Class? #t189 = c in #t189.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t190 = self::Extension|get#field(#t189) in let final self::Class? #t191 = self::Extension|+(self::Extension|get#field(#t190), 0) in let final void #t192 = self::Extension|set#field(#t190, #t191) in #t191;
- let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t193, self::Extension|+(self::Extension|get#field(#t193), 1));
- c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|get#field(#t194) in let final void #t196 = self::Extension|set#field(#t194, self::Extension|+(#t195, 1)) in #t195;
- let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t198 = self::Extension|+(self::Extension|get#field(#t197), 1) in let final void #t199 = self::Extension|set#field(#t197, #t198) in #t198;
- c = let final self::Class? #t200 = c in #t200.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t201 = self::Extension|+(self::Extension|get#field(#t200), 1) in let final void #t202 = self::Extension|set#field(#t200, #t201) in #t201;
+ self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t184), 0));
+ self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t185 = c in #t185.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t185)));
+ let final self::Class? #t186 = c in #t186.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t186, self::Extension|+(self::Extension|get#field(#t186), 0));
+ c = let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|+(self::Extension|get#field(#t187), 0) in let final void #t189 = self::Extension|set#field(#t187, #t188) in #t188;
+ let final self::Class? #t190 = c in #t190.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t191 = self::Extension|get#field(#t190) in self::Extension|set#field(#t191, self::Extension|+(self::Extension|get#field(#t191), 0));
+ c = let final self::Class? #t192 = c in #t192.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t193 = self::Extension|get#field(#t192) in let final self::Class? #t194 = self::Extension|+(self::Extension|get#field(#t193), 0) in let final void #t195 = self::Extension|set#field(#t193, #t194) in #t194;
+ let final self::Class? #t196 = c in #t196.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t196, self::Extension|+(self::Extension|get#field(#t196), 1));
+ c = let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t198 = self::Extension|get#field(#t197) in let final void #t199 = self::Extension|set#field(#t197, self::Extension|+(#t198, 1)) in #t198;
+ let final self::Class? #t200 = c in #t200.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t201 = self::Extension|+(self::Extension|get#field(#t200), 1) in let final void #t202 = self::Extension|set#field(#t200, #t201) in #t201;
+ c = let final self::Class? #t203 = c in #t203.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t204 = self::Extension|+(self::Extension|get#field(#t203), 1) in let final void #t205 = self::Extension|set#field(#t203, #t204) in #t204;
}
static method ifNull(self::Class? c) → void {
- let final self::Class? #t203 = c in #t203.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t203).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t203, c) : null;
- c = let final self::Class? #t204 = c in #t204.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t205 = self::Extension|get#field(#t204) in #t205.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t206 = c in let final void #t207 = self::Extension|set#field(#t204, #t206) in #t206 : #t205;
- let final self::Class? #t208 = c in #t208.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t209 = self::Extension|get#field(#t208) in let final self::Class? #t210 = c in self::Extension|[](#t209, #t210).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t209, #t210, c) : null;
+ let final self::Class? #t206 = c in #t206.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t206).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t206, c) : null;
+ c = let final self::Class? #t207 = c in #t207.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t208 = self::Extension|get#field(#t207) in #t208.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t209 = c in let final void #t210 = self::Extension|set#field(#t207, #t209) in #t209 : #t208;
+ let final self::Class? #t211 = c in #t211.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t212 = self::Extension|get#field(#t211) in let final self::Class? #t213 = c in self::Extension|[](#t212, #t213).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t212, #t213, c) : null;
}
static method throws(() → void f) → void {
try {
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
index ac7b6fb..e45d0bc 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
@@ -44,98 +44,101 @@
}
static method propertyAccess(self::Class? c) → void {
let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t1);
- let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t2, new self::Class::•());
- c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
+ let final self::Class? #t2 = c in #t2.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t2, new self::Class::•());
+ c = let final self::Class? #t3 = c in #t3.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t4 = new self::Class::•() in let final void #t5 = self::Extension|set#field(#t3, #t4) in #t4;
let final self::Class? #t6 = c in #t6.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t6);
let final self::Class? #t7 = c in #t7.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(#t7));
- let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
+ let final self::Class? #t8 = c in #t8.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(#t8), new self::Class::•());
self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t9 = c in #t9.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t9)));
- self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
+ self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t10 = c in #t10.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t11 = new self::Class::•() in let final void #t12 = self::Extension|set#field(#t10, #t11) in #t11));
self::throws(() → self::Class? => self::Extension|get#field(let final self::Class? #t13 = c in #t13.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(#t13)));
- c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
+ c = let final self::Class? #t14 = c in #t14.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t15 = new self::Class::•() in let final void #t16 = self::Extension|set#field(self::Extension|get#field(#t14), #t15) in #t15;
let final self::Class? #t17 = c in #t17.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(#t17));
let final self::Class? #t18 = c in #t18.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t18, self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t19 = c in #t19.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t20 = self::Extension|get#field(new self::Class::•()) in let final void #t21 = self::Extension|set#field(#t19, #t20) in #t20;
- let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t22, let final self::Class* #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
- c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t26 = let final self::Class* #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
+ let final self::Class? #t22 = c in #t22.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t22, let final self::Class #t23 = new self::Class::•() in let final void #t24 = self::Extension|set#field(new self::Class::•(), #t23) in #t23);
+ c = let final self::Class? #t25 = c in #t25.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t26 = let final self::Class #t27 = new self::Class::•() in let final void #t28 = self::Extension|set#field(new self::Class::•(), #t27) in #t27 in let final void #t29 = self::Extension|set#field(#t25, #t26) in #t26;
let final self::Class? #t30 = c in #t30.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t30, self::Extension|method(new self::Class::•()));
c = let final self::Class? #t31 = c in #t31.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t32 = self::Extension|method(new self::Class::•()) in let final void #t33 = self::Extension|set#field(#t31, #t32) in #t32;
let final self::Class? #t34 = c in #t34.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(#t34));
- let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
+ let final self::Class? #t35 = c in #t35.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(#t35), new self::Class::•());
let final self::Class? #t36 = c in #t36.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(#t36));
let final self::Class? #t37 = c in #t37.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|get#field(#t37)));
- let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
- c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
+ let final self::Class? #t38 = c in #t38.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t38)), new self::Class::•());
+ c = let final self::Class? #t39 = c in #t39.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t40 = new self::Class::•() in let final void #t41 = self::Extension|set#field(self::Extension|get#field(self::Extension|get#field(#t39)), #t40) in #t40;
let final self::Class? #t42 = c in #t42.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|get#field(#t42)));
let final self::Class? #t43 = c in #t43.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t43, self::Extension|get#field(self::Extension|get#field(new self::Class::•())));
c = let final self::Class? #t44 = c in #t44.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t45 = self::Extension|get#field(self::Extension|get#field(new self::Class::•())) in let final void #t46 = self::Extension|set#field(#t44, #t45) in #t45;
- let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t47, let final self::Class* #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
- c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t51 = let final self::Class* #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
+ let final self::Class? #t47 = c in #t47.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t47, let final self::Class #t48 = new self::Class::•() in let final void #t49 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t48) in #t48);
+ c = let final self::Class? #t50 = c in #t50.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t51 = let final self::Class #t52 = new self::Class::•() in let final void #t53 = self::Extension|set#field(self::Extension|get#field(new self::Class::•()), #t52) in #t52 in let final void #t54 = self::Extension|set#field(#t50, #t51) in #t51;
let final self::Class? #t55 = c in #t55.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t55, self::Extension|method(self::Extension|get#field(new self::Class::•())));
c = let final self::Class? #t56 = c in #t56.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t57 = self::Extension|method(self::Extension|get#field(new self::Class::•())) in let final void #t58 = self::Extension|set#field(#t56, #t57) in #t57;
let final self::Class? #t59 = c in #t59.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|get#field(self::Extension|method(#t59)));
- let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
+ let final self::Class? #t60 = c in #t60.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(self::Extension|method(#t60)), new self::Class::•());
let final self::Class? #t61 = c in #t61.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|get#field(self::Extension|method(#t61)));
let final self::Class? #t62 = c in #t62.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t62), self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t63 = c in #t63.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t64 = self::Extension|get#field(new self::Class::•()) in let final void #t65 = self::Extension|set#field(self::Extension|get#field(#t63), #t64) in #t64;
- let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class* #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
- c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t70 = let final self::Class* #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
+ let final self::Class? #t66 = c in #t66.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|get#field(#t66), let final self::Class #t67 = new self::Class::•() in let final void #t68 = self::Extension|set#field(new self::Class::•(), #t67) in #t67);
+ c = let final self::Class? #t69 = c in #t69.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t70 = let final self::Class #t71 = new self::Class::•() in let final void #t72 = self::Extension|set#field(new self::Class::•(), #t71) in #t71 in let final void #t73 = self::Extension|set#field(self::Extension|get#field(#t69), #t70) in #t70;
let final self::Class? #t74 = c in #t74.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|get#field(#t74), self::Extension|method(new self::Class::•()));
c = let final self::Class? #t75 = c in #t75.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t76 = self::Extension|method(new self::Class::•()) in let final void #t77 = self::Extension|set#field(self::Extension|get#field(#t75), #t76) in #t76;
let final self::Class? #t78 = c in #t78.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t78, let final self::Class? #t79 = self::Extension|get#field(new self::Class::•()) in let final void #t80 = self::Extension|set#field(new self::Class::•(), #t79) in #t79);
c = let final self::Class? #t81 = c in #t81.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t82 = let final self::Class? #t83 = self::Extension|get#field(new self::Class::•()) in let final void #t84 = self::Extension|set#field(new self::Class::•(), #t83) in #t83 in let final void #t85 = self::Extension|set#field(#t81, #t82) in #t82;
- let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t86, let final self::Class* #t87 = let final self::Class* #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
- c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t92 = let final self::Class* #t93 = let final self::Class* #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
+ let final self::Class? #t86 = c in #t86.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t86, let final self::Class #t87 = let final self::Class #t88 = new self::Class::•() in let final void #t89 = self::Extension|set#field(new self::Class::•(), #t88) in #t88 in let final void #t90 = self::Extension|set#field(new self::Class::•(), #t87) in #t87);
+ c = let final self::Class? #t91 = c in #t91.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t92 = let final self::Class #t93 = let final self::Class #t94 = new self::Class::•() in let final void #t95 = self::Extension|set#field(new self::Class::•(), #t94) in #t94 in let final void #t96 = self::Extension|set#field(new self::Class::•(), #t93) in #t93 in let final void #t97 = self::Extension|set#field(#t91, #t92) in #t92;
let final self::Class? #t98 = c in #t98.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t98, let final self::Class? #t99 = self::Extension|method(new self::Class::•()) in let final void #t100 = self::Extension|set#field(new self::Class::•(), #t99) in #t99);
c = let final self::Class? #t101 = c in #t101.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t102 = let final self::Class? #t103 = self::Extension|method(new self::Class::•()) in let final void #t104 = self::Extension|set#field(new self::Class::•(), #t103) in #t103 in let final void #t105 = self::Extension|set#field(#t101, #t102) in #t102;
let final self::Class? #t106 = c in #t106.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t106), self::Extension|get#field(new self::Class::•()));
c = let final self::Class? #t107 = c in #t107.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t108 = self::Extension|get#field(new self::Class::•()) in let final void #t109 = self::Extension|set#field(self::Extension|method(#t107), #t108) in #t108;
- let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class* #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
- c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t114 = let final self::Class* #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
+ let final self::Class? #t110 = c in #t110.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(#t110), let final self::Class #t111 = new self::Class::•() in let final void #t112 = self::Extension|set#field(new self::Class::•(), #t111) in #t111);
+ c = let final self::Class? #t113 = c in #t113.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t114 = let final self::Class #t115 = new self::Class::•() in let final void #t116 = self::Extension|set#field(new self::Class::•(), #t115) in #t115 in let final void #t117 = self::Extension|set#field(self::Extension|method(#t113), #t114) in #t114;
let final self::Class? #t118 = c in #t118.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(self::Extension|method(#t118), self::Extension|method(new self::Class::•()));
c = let final self::Class? #t119 = c in #t119.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t120 = self::Extension|method(new self::Class::•()) in let final void #t121 = self::Extension|set#field(self::Extension|method(#t119), #t120) in #t120;
let final self::Class? #t122 = c in #t122.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|get#field(#t122)));
- let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
- c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
+ let final self::Class? #t123 = c in #t123.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t123)), new self::Class::•());
+ c = let final self::Class? #t124 = c in #t124.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t125 = new self::Class::•() in let final void #t126 = self::Extension|set#field(self::Extension|method(self::Extension|get#field(#t124)), #t125) in #t125;
let final self::Class? #t127 = c in #t127.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|get#field(#t127)));
let final self::Class? #t128 = c in #t128.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t128, self::Extension|get#field(self::Extension|method(new self::Class::•())));
c = let final self::Class? #t129 = c in #t129.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t130 = self::Extension|get#field(self::Extension|method(new self::Class::•())) in let final void #t131 = self::Extension|set#field(#t129, #t130) in #t130;
- let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(#t132, let final self::Class* #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
- c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class*} null : let final self::Class* #t136 = let final self::Class* #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
+ let final self::Class? #t132 = c in #t132.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(#t132, let final self::Class #t133 = new self::Class::•() in let final void #t134 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t133) in #t133);
+ c = let final self::Class? #t135 = c in #t135.{core::Object::==}(null) ?{self::Class} null : let final self::Class #t136 = let final self::Class #t137 = new self::Class::•() in let final void #t138 = self::Extension|set#field(self::Extension|method(new self::Class::•()), #t137) in #t137 in let final void #t139 = self::Extension|set#field(#t135, #t136) in #t136;
let final self::Class? #t140 = c in #t140.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t140, self::Extension|method(self::Extension|method(new self::Class::•())));
c = let final self::Class? #t141 = c in #t141.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t142 = self::Extension|method(self::Extension|method(new self::Class::•())) in let final void #t143 = self::Extension|set#field(#t141, #t142) in #t142;
let final self::Class? #t144 = c in #t144.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(self::Extension|method(self::Extension|method(#t144)));
- let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class*} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
+ let final self::Class? #t145 = c in #t145.{core::Object::==}(null) ?{self::Class} null : self::Extension|set#field(self::Extension|method(self::Extension|method(#t145)), new self::Class::•());
let final self::Class? #t146 = c in #t146.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|method(self::Extension|method(#t146)));
}
static method indexAccess(self::Class? c) → void {
- let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t147), c);
- let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{self::Class*} null : self::Extension|[]=(self::Extension|get#field(#t148), c, new self::Class::•());
- c = let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class*} null : let final self::Class? #t150 = self::Extension|get#field(#t149) in let final self::Class? #t151 = c in let final self::Class* #t152 = new self::Class::•() in let final void #t153 = self::Extension|[]=(#t150, #t151, #t152) in #t152;
- let final self::Class? #t154 = c in #t154.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t154), c));
- let final self::Class? #t155 = c in #t155.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t156 = self::Extension|get#field(#t155) in let final self::Class? #t157 = c in self::Extension|[]=(#t156, #t157, self::Extension|+(self::Extension|[](#t156, #t157), 0));
- c = let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in let final self::Class? #t161 = self::Extension|+(self::Extension|[](#t159, #t160), 0) in let final void #t162 = self::Extension|[]=(#t159, #t160, #t161) in #t161;
- let final self::Class? #t163 = c in #t163.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t164 = self::Extension|get#field(#t163) in let final self::Class? #t165 = c in self::Extension|[]=(#t164, #t165, self::Extension|+(self::Extension|[](#t164, #t165), 1));
- c = let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in let final self::Class? #t169 = self::Extension|[](#t167, #t168) in let final void #t170 = self::Extension|[]=(#t167, #t168, self::Extension|+(#t169, 1)) in #t169;
- let final self::Class? #t171 = c in #t171.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t172 = self::Extension|get#field(#t171) in let final self::Class? #t173 = c in let final self::Class? #t174 = self::Extension|+(self::Extension|[](#t172, #t173), 1) in let final void #t175 = self::Extension|[]=(#t172, #t173, #t174) in #t174;
- c = let final self::Class? #t176 = c in #t176.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t177 = self::Extension|get#field(#t176) in let final self::Class? #t178 = c in let final self::Class? #t179 = self::Extension|+(self::Extension|[](#t177, #t178), 1) in let final void #t180 = self::Extension|[]=(#t177, #t178, #t179) in #t179;
+ let final self::Class? #t147 = c in #t147.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](#t147, c);
+ let final self::Class? #t148 = c in #t148.{core::Object::==}(null) ?{self::Class} null : self::Extension|[]=(#t148, c, new self::Class::•());
+ let final self::Class? #t149 = c in #t149.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](#t149, c));
+ let final self::Class? #t150 = c in #t150.{core::Object::==}(null) ?{self::Class?} null : self::Extension|[](self::Extension|get#field(#t150), c);
+ let final self::Class? #t151 = c in #t151.{core::Object::==}(null) ?{self::Class} null : self::Extension|[]=(self::Extension|get#field(#t151), c, new self::Class::•());
+ c = let final self::Class? #t152 = c in #t152.{core::Object::==}(null) ?{self::Class} null : let final self::Class? #t153 = self::Extension|get#field(#t152) in let final self::Class? #t154 = c in let final self::Class #t155 = new self::Class::•() in let final void #t156 = self::Extension|[]=(#t153, #t154, #t155) in #t155;
+ let final self::Class? #t157 = c in #t157.{core::Object::==}(null) ?{self::Class?} null : self::Extension|method(self::Extension|[](self::Extension|get#field(#t157), c));
+ let final self::Class? #t158 = c in #t158.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t159 = self::Extension|get#field(#t158) in let final self::Class? #t160 = c in self::Extension|[]=(#t159, #t160, self::Extension|+(self::Extension|[](#t159, #t160), 0));
+ c = let final self::Class? #t161 = c in #t161.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t162 = self::Extension|get#field(#t161) in let final self::Class? #t163 = c in let final self::Class? #t164 = self::Extension|+(self::Extension|[](#t162, #t163), 0) in let final void #t165 = self::Extension|[]=(#t162, #t163, #t164) in #t164;
+ let final self::Class? #t166 = c in #t166.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t167 = self::Extension|get#field(#t166) in let final self::Class? #t168 = c in self::Extension|[]=(#t167, #t168, self::Extension|+(self::Extension|[](#t167, #t168), 1));
+ c = let final self::Class? #t169 = c in #t169.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t170 = self::Extension|get#field(#t169) in let final self::Class? #t171 = c in let final self::Class? #t172 = self::Extension|[](#t170, #t171) in let final void #t173 = self::Extension|[]=(#t170, #t171, self::Extension|+(#t172, 1)) in #t172;
+ let final self::Class? #t174 = c in #t174.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t175 = self::Extension|get#field(#t174) in let final self::Class? #t176 = c in let final self::Class? #t177 = self::Extension|+(self::Extension|[](#t175, #t176), 1) in let final void #t178 = self::Extension|[]=(#t175, #t176, #t177) in #t177;
+ c = let final self::Class? #t179 = c in #t179.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t180 = self::Extension|get#field(#t179) in let final self::Class? #t181 = c in let final self::Class? #t182 = self::Extension|+(self::Extension|[](#t180, #t181), 1) in let final void #t183 = self::Extension|[]=(#t180, #t181, #t182) in #t182;
}
static method operatorAccess(self::Class? c) → void {
- self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t181 = c in #t181.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t181), 0));
- self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t182 = c in #t182.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t182)));
- let final self::Class? #t183 = c in #t183.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t183, self::Extension|+(self::Extension|get#field(#t183), 0));
- c = let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t185 = self::Extension|+(self::Extension|get#field(#t184), 0) in let final void #t186 = self::Extension|set#field(#t184, #t185) in #t185;
- let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|get#field(#t187) in self::Extension|set#field(#t188, self::Extension|+(self::Extension|get#field(#t188), 0));
- c = let final self::Class? #t189 = c in #t189.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t190 = self::Extension|get#field(#t189) in let final self::Class? #t191 = self::Extension|+(self::Extension|get#field(#t190), 0) in let final void #t192 = self::Extension|set#field(#t190, #t191) in #t191;
- let final self::Class? #t193 = c in #t193.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t193, self::Extension|+(self::Extension|get#field(#t193), 1));
- c = let final self::Class? #t194 = c in #t194.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t195 = self::Extension|get#field(#t194) in let final void #t196 = self::Extension|set#field(#t194, self::Extension|+(#t195, 1)) in #t195;
- let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t198 = self::Extension|+(self::Extension|get#field(#t197), 1) in let final void #t199 = self::Extension|set#field(#t197, #t198) in #t198;
- c = let final self::Class? #t200 = c in #t200.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t201 = self::Extension|+(self::Extension|get#field(#t200), 1) in let final void #t202 = self::Extension|set#field(#t200, #t201) in #t201;
+ self::throws(() → self::Class? => self::Extension|+(let final self::Class? #t184 = c in #t184.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t184), 0));
+ self::throws(() → self::Class? => self::Extension|unary-(let final self::Class? #t185 = c in #t185.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t185)));
+ let final self::Class? #t186 = c in #t186.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t186, self::Extension|+(self::Extension|get#field(#t186), 0));
+ c = let final self::Class? #t187 = c in #t187.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t188 = self::Extension|+(self::Extension|get#field(#t187), 0) in let final void #t189 = self::Extension|set#field(#t187, #t188) in #t188;
+ let final self::Class? #t190 = c in #t190.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t191 = self::Extension|get#field(#t190) in self::Extension|set#field(#t191, self::Extension|+(self::Extension|get#field(#t191), 0));
+ c = let final self::Class? #t192 = c in #t192.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t193 = self::Extension|get#field(#t192) in let final self::Class? #t194 = self::Extension|+(self::Extension|get#field(#t193), 0) in let final void #t195 = self::Extension|set#field(#t193, #t194) in #t194;
+ let final self::Class? #t196 = c in #t196.{core::Object::==}(null) ?{self::Class?} null : self::Extension|set#field(#t196, self::Extension|+(self::Extension|get#field(#t196), 1));
+ c = let final self::Class? #t197 = c in #t197.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t198 = self::Extension|get#field(#t197) in let final void #t199 = self::Extension|set#field(#t197, self::Extension|+(#t198, 1)) in #t198;
+ let final self::Class? #t200 = c in #t200.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t201 = self::Extension|+(self::Extension|get#field(#t200), 1) in let final void #t202 = self::Extension|set#field(#t200, #t201) in #t201;
+ c = let final self::Class? #t203 = c in #t203.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t204 = self::Extension|+(self::Extension|get#field(#t203), 1) in let final void #t205 = self::Extension|set#field(#t203, #t204) in #t204;
}
static method ifNull(self::Class? c) → void {
- let final self::Class? #t203 = c in #t203.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t203).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t203, c) : null;
- c = let final self::Class? #t204 = c in #t204.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t205 = self::Extension|get#field(#t204) in #t205.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t206 = c in let final void #t207 = self::Extension|set#field(#t204, #t206) in #t206 : #t205;
- let final self::Class? #t208 = c in #t208.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t209 = self::Extension|get#field(#t208) in let final self::Class? #t210 = c in self::Extension|[](#t209, #t210).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t209, #t210, c) : null;
+ let final self::Class? #t206 = c in #t206.{core::Object::==}(null) ?{self::Class?} null : self::Extension|get#field(#t206).{core::Object::==}(null) ?{self::Class?} self::Extension|set#field(#t206, c) : null;
+ c = let final self::Class? #t207 = c in #t207.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t208 = self::Extension|get#field(#t207) in #t208.{core::Object::==}(null) ?{self::Class?} let final self::Class? #t209 = c in let final void #t210 = self::Extension|set#field(#t207, #t209) in #t209 : #t208;
+ let final self::Class? #t211 = c in #t211.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t212 = self::Extension|get#field(#t211) in let final self::Class? #t213 = c in self::Extension|[](#t212, #t213).{core::Object::==}(null) ?{self::Class?} self::Extension|[]=(#t212, #t213, c) : null;
}
static method throws(() → void f) → void {
try {
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart b/pkg/front_end/testcases/nnbd/null_shorting_index.dart
new file mode 100644
index 0000000..ce4173d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2019, 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.
+
+class Class1 {
+ int operator [](int index) => index;
+ void operator []=(int index, int value) {}
+}
+
+class Class2 {
+ int field;
+}
+
+extension Extension on Class2 {
+ int operator [](int index) => field;
+ void operator []=(int index, int value) {
+ field = value;
+ }
+}
+
+main() {
+ Class1? c1;
+ c1?.[0];
+ c1?.[0] = 1;
+ c1?.[0] = 1 + c1[0];
+ c1?.[0] += 1;
+ c1?.[0] += 1 + c1[0];
+ // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
+ // update.
+ ++c1?.[0];
+ c1?.[0]++;
+ c1?.[0] ??= 1;
+ c1?.[0] ??= 1 + c1[1];
+
+ Class2? c2;
+ c2?.[0];
+ c2?.[0] = 1;
+ c2?.[0] = 1 + c2[0];
+ c2?.[0] += 1;
+ c2?.[0] += 1 + c2[0];
+ // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
+ // update.
+ ++c2?.[0];
+ c2?.[0]++;
+ c2?.[0] ??= 1;
+ c2?.[0] ??= 1 + c2[1];
+
+ Extension(c2)?.[0];
+ Extension(c2)?.[0] = 1;
+ Extension(c2)?.[0] = 1 + Extension(c2)[0];
+ Extension(c2)?.[0] += 1;
+ Extension(c2)?.[0] += 1 + Extension(c2)[0];
+ // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
+ // update.
+ ++Extension(c2)?.[0];
+ Extension(c2)?.[0]++;
+ Extension(c2)?.[0] ??= 1;
+ Extension(c2)?.[0] ??= 1 + Extension(c2)[1];
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.outline.expect
new file mode 100644
index 0000000..f96ff24
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.outline.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ synthetic constructor •() → self::Class1*
+ ;
+ operator [](core::int index) → core::int
+ ;
+ operator []=(core::int index, core::int value) → void
+ ;
+}
+class Class2 extends core::Object {
+ field core::int field;
+ synthetic constructor •() → self::Class2*
+ ;
+}
+extension Extension on self::Class2 {
+ operator [] = self::Extension|[];
+ operator []= = self::Extension|[]=;
+}
+static method Extension|[](final self::Class2 #this, core::int index) → core::int
+ ;
+static method Extension|[]=(final self::Class2 #this, core::int index, core::int value) → void
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
new file mode 100644
index 0000000..ebb3975
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
@@ -0,0 +1,58 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ synthetic constructor •() → self::Class1*
+ : super core::Object::•()
+ ;
+ operator [](core::int index) → core::int
+ return index;
+ operator []=(core::int index, core::int value) → void {}
+}
+class Class2 extends core::Object {
+ field core::int field = null;
+ synthetic constructor •() → self::Class2*
+ : super core::Object::•()
+ ;
+}
+extension Extension on self::Class2 {
+ operator [] = self::Extension|[];
+ operator []= = self::Extension|[]=;
+}
+static method Extension|[](final self::Class2 #this, core::int index) → core::int
+ return #this.{self::Class2::field};
+static method Extension|[]=(final self::Class2 #this, core::int index, core::int value) → void {
+ #this.{self::Class2::field} = value;
+}
+static method main() → dynamic {
+ self::Class1? c1;
+ let final self::Class1? #t1 = c1 in #t1.{core::Object::==}(null) ?{core::int} null : #t1.{self::Class1::[]}(0);
+ let final self::Class1? #t2 = c1 in #t2.{core::Object::==}(null) ?{core::int} null : #t2.{self::Class1::[]=}(0, 1);
+ let final self::Class1? #t3 = c1 in #t3.{core::Object::==}(null) ?{core::int} null : #t3.{self::Class1::[]=}(0, 1.{core::num::+}(c1.{self::Class1::[]}(0)));
+ let final self::Class1? #t4 = c1 in #t4.{core::Object::==}(null) ?{core::int} null : let final core::int #t5 = 0 in #t4.{self::Class1::[]=}(#t5, #t4.{self::Class1::[]}(#t5).{core::num::+}(1));
+ let final self::Class1? #t6 = c1 in #t6.{core::Object::==}(null) ?{core::int} null : let final core::int #t7 = 0 in #t6.{self::Class1::[]=}(#t7, #t6.{self::Class1::[]}(#t7).{core::num::+}(1.{core::num::+}(c1.{self::Class1::[]}(0))));
+ let final self::Class1? #t8 = c1 in #t8.{core::Object::==}(null) ?{core::int} null : let final core::int #t9 = 0 in let final core::int #t10 = #t8.{self::Class1::[]}(#t9).{core::num::+}(1) in let final void #t11 = #t8.{self::Class1::[]=}(#t9, #t10) in #t10;
+ let final self::Class1? #t12 = c1 in #t12.{core::Object::==}(null) ?{core::int} null : let final core::int #t13 = 0 in #t12.{self::Class1::[]=}(#t13, #t12.{self::Class1::[]}(#t13).{core::num::+}(1));
+ let final self::Class1? #t14 = c1 in #t14.{core::Object::==}(null) ?{core::int} null : let final core::int #t15 = 0 in #t14.{self::Class1::[]}(#t15).{core::num::==}(null) ?{core::int} #t14.{self::Class1::[]=}(#t15, 1) : null;
+ let final self::Class1? #t16 = c1 in #t16.{core::Object::==}(null) ?{core::int} null : let final core::int #t17 = 0 in #t16.{self::Class1::[]}(#t17).{core::num::==}(null) ?{core::int} #t16.{self::Class1::[]=}(#t17, 1.{core::num::+}(c1.{self::Class1::[]}(1))) : null;
+ self::Class2? c2;
+ let final self::Class2? #t18 = c2 in #t18.{core::Object::==}(null) ?{core::int} null : self::Extension|[](#t18, 0);
+ let final self::Class2? #t19 = c2 in #t19.{core::Object::==}(null) ?{core::int} null : self::Extension|[]=(#t19, 0, 1);
+ let final self::Class2? #t20 = c2 in #t20.{core::Object::==}(null) ?{core::int} null : self::Extension|[]=(#t20, 0, 1.{core::num::+}(self::Extension|[](c2, 0)));
+ let final self::Class2? #t21 = c2 in #t21.{core::Object::==}(null) ?{core::int} null : let final core::int #t22 = 0 in self::Extension|[]=(#t21, #t22, self::Extension|[](#t21, #t22).{core::num::+}(1));
+ let final self::Class2? #t23 = c2 in #t23.{core::Object::==}(null) ?{core::int} null : let final core::int #t24 = 0 in self::Extension|[]=(#t23, #t24, self::Extension|[](#t23, #t24).{core::num::+}(1.{core::num::+}(self::Extension|[](c2, 0))));
+ let final self::Class2? #t25 = c2 in #t25.{core::Object::==}(null) ?{core::int} null : let final core::int #t26 = 0 in let final core::int #t27 = self::Extension|[](#t25, #t26).{core::num::+}(1) in let final void #t28 = self::Extension|[]=(#t25, #t26, #t27) in #t27;
+ let final self::Class2? #t29 = c2 in #t29.{core::Object::==}(null) ?{core::int} null : let final core::int #t30 = 0 in self::Extension|[]=(#t29, #t30, self::Extension|[](#t29, #t30).{core::num::+}(1));
+ let final self::Class2? #t31 = c2 in #t31.{core::Object::==}(null) ?{core::int} null : let final core::int #t32 = 0 in self::Extension|[](#t31, #t32).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t31, #t32, 1) : null;
+ let final self::Class2? #t33 = c2 in #t33.{core::Object::==}(null) ?{core::int} null : let final core::int #t34 = 0 in self::Extension|[](#t33, #t34).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t33, #t34, 1.{core::num::+}(self::Extension|[](c2, 1))) : null;
+ let final self::Class2? #t35 = c2 in #t35.{core::Object::==}(null) ?{core::int} null : self::Extension|[](#t35, 0);
+ let final self::Class2? #t36 = c2 in #t36.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t36, 0, 1);
+ let final self::Class2? #t37 = c2 in #t37.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t37, 0, 1.{core::num::+}(self::Extension|[](c2, 0)));
+ let final self::Class2? #t38 = c2 in #t38.{core::Object::==}(null) ?{core::int} null : let final core::int #t39 = 0 in self::Extension|[]=(#t38, #t39, self::Extension|[](#t38, #t39).{core::num::+}(1));
+ let final self::Class2? #t40 = c2 in #t40.{core::Object::==}(null) ?{core::int} null : let final core::int #t41 = 0 in self::Extension|[]=(#t40, #t41, self::Extension|[](#t40, #t41).{core::num::+}(1.{core::num::+}(self::Extension|[](c2, 0))));
+ let final self::Class2? #t42 = c2 in #t42.{core::Object::==}(null) ?{core::int} null : let final core::int #t43 = 0 in let final core::int #t44 = self::Extension|[](#t42, #t43).{core::num::+}(1) in let final void #t45 = self::Extension|[]=(#t42, #t43, #t44) in #t44;
+ let final self::Class2? #t46 = c2 in #t46.{core::Object::==}(null) ?{core::int} null : let final core::int #t47 = 0 in self::Extension|[]=(#t46, #t47, self::Extension|[](#t46, #t47).{core::num::+}(1));
+ let final self::Class2? #t48 = c2 in #t48.{core::Object::==}(null) ?{core::int} null : let final core::int #t49 = 0 in self::Extension|[](#t48, #t49).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t48, #t49, 1) : null;
+ let final self::Class2? #t50 = c2 in #t50.{core::Object::==}(null) ?{core::int} null : let final core::int #t51 = 0 in self::Extension|[](#t50, #t51).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t50, #t51, 1.{core::num::+}(self::Extension|[](c2, 1))) : null;
+}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
new file mode 100644
index 0000000..ebb3975
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
@@ -0,0 +1,58 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object {
+ synthetic constructor •() → self::Class1*
+ : super core::Object::•()
+ ;
+ operator [](core::int index) → core::int
+ return index;
+ operator []=(core::int index, core::int value) → void {}
+}
+class Class2 extends core::Object {
+ field core::int field = null;
+ synthetic constructor •() → self::Class2*
+ : super core::Object::•()
+ ;
+}
+extension Extension on self::Class2 {
+ operator [] = self::Extension|[];
+ operator []= = self::Extension|[]=;
+}
+static method Extension|[](final self::Class2 #this, core::int index) → core::int
+ return #this.{self::Class2::field};
+static method Extension|[]=(final self::Class2 #this, core::int index, core::int value) → void {
+ #this.{self::Class2::field} = value;
+}
+static method main() → dynamic {
+ self::Class1? c1;
+ let final self::Class1? #t1 = c1 in #t1.{core::Object::==}(null) ?{core::int} null : #t1.{self::Class1::[]}(0);
+ let final self::Class1? #t2 = c1 in #t2.{core::Object::==}(null) ?{core::int} null : #t2.{self::Class1::[]=}(0, 1);
+ let final self::Class1? #t3 = c1 in #t3.{core::Object::==}(null) ?{core::int} null : #t3.{self::Class1::[]=}(0, 1.{core::num::+}(c1.{self::Class1::[]}(0)));
+ let final self::Class1? #t4 = c1 in #t4.{core::Object::==}(null) ?{core::int} null : let final core::int #t5 = 0 in #t4.{self::Class1::[]=}(#t5, #t4.{self::Class1::[]}(#t5).{core::num::+}(1));
+ let final self::Class1? #t6 = c1 in #t6.{core::Object::==}(null) ?{core::int} null : let final core::int #t7 = 0 in #t6.{self::Class1::[]=}(#t7, #t6.{self::Class1::[]}(#t7).{core::num::+}(1.{core::num::+}(c1.{self::Class1::[]}(0))));
+ let final self::Class1? #t8 = c1 in #t8.{core::Object::==}(null) ?{core::int} null : let final core::int #t9 = 0 in let final core::int #t10 = #t8.{self::Class1::[]}(#t9).{core::num::+}(1) in let final void #t11 = #t8.{self::Class1::[]=}(#t9, #t10) in #t10;
+ let final self::Class1? #t12 = c1 in #t12.{core::Object::==}(null) ?{core::int} null : let final core::int #t13 = 0 in #t12.{self::Class1::[]=}(#t13, #t12.{self::Class1::[]}(#t13).{core::num::+}(1));
+ let final self::Class1? #t14 = c1 in #t14.{core::Object::==}(null) ?{core::int} null : let final core::int #t15 = 0 in #t14.{self::Class1::[]}(#t15).{core::num::==}(null) ?{core::int} #t14.{self::Class1::[]=}(#t15, 1) : null;
+ let final self::Class1? #t16 = c1 in #t16.{core::Object::==}(null) ?{core::int} null : let final core::int #t17 = 0 in #t16.{self::Class1::[]}(#t17).{core::num::==}(null) ?{core::int} #t16.{self::Class1::[]=}(#t17, 1.{core::num::+}(c1.{self::Class1::[]}(1))) : null;
+ self::Class2? c2;
+ let final self::Class2? #t18 = c2 in #t18.{core::Object::==}(null) ?{core::int} null : self::Extension|[](#t18, 0);
+ let final self::Class2? #t19 = c2 in #t19.{core::Object::==}(null) ?{core::int} null : self::Extension|[]=(#t19, 0, 1);
+ let final self::Class2? #t20 = c2 in #t20.{core::Object::==}(null) ?{core::int} null : self::Extension|[]=(#t20, 0, 1.{core::num::+}(self::Extension|[](c2, 0)));
+ let final self::Class2? #t21 = c2 in #t21.{core::Object::==}(null) ?{core::int} null : let final core::int #t22 = 0 in self::Extension|[]=(#t21, #t22, self::Extension|[](#t21, #t22).{core::num::+}(1));
+ let final self::Class2? #t23 = c2 in #t23.{core::Object::==}(null) ?{core::int} null : let final core::int #t24 = 0 in self::Extension|[]=(#t23, #t24, self::Extension|[](#t23, #t24).{core::num::+}(1.{core::num::+}(self::Extension|[](c2, 0))));
+ let final self::Class2? #t25 = c2 in #t25.{core::Object::==}(null) ?{core::int} null : let final core::int #t26 = 0 in let final core::int #t27 = self::Extension|[](#t25, #t26).{core::num::+}(1) in let final void #t28 = self::Extension|[]=(#t25, #t26, #t27) in #t27;
+ let final self::Class2? #t29 = c2 in #t29.{core::Object::==}(null) ?{core::int} null : let final core::int #t30 = 0 in self::Extension|[]=(#t29, #t30, self::Extension|[](#t29, #t30).{core::num::+}(1));
+ let final self::Class2? #t31 = c2 in #t31.{core::Object::==}(null) ?{core::int} null : let final core::int #t32 = 0 in self::Extension|[](#t31, #t32).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t31, #t32, 1) : null;
+ let final self::Class2? #t33 = c2 in #t33.{core::Object::==}(null) ?{core::int} null : let final core::int #t34 = 0 in self::Extension|[](#t33, #t34).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t33, #t34, 1.{core::num::+}(self::Extension|[](c2, 1))) : null;
+ let final self::Class2? #t35 = c2 in #t35.{core::Object::==}(null) ?{core::int} null : self::Extension|[](#t35, 0);
+ let final self::Class2? #t36 = c2 in #t36.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t36, 0, 1);
+ let final self::Class2? #t37 = c2 in #t37.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t37, 0, 1.{core::num::+}(self::Extension|[](c2, 0)));
+ let final self::Class2? #t38 = c2 in #t38.{core::Object::==}(null) ?{core::int} null : let final core::int #t39 = 0 in self::Extension|[]=(#t38, #t39, self::Extension|[](#t38, #t39).{core::num::+}(1));
+ let final self::Class2? #t40 = c2 in #t40.{core::Object::==}(null) ?{core::int} null : let final core::int #t41 = 0 in self::Extension|[]=(#t40, #t41, self::Extension|[](#t40, #t41).{core::num::+}(1.{core::num::+}(self::Extension|[](c2, 0))));
+ let final self::Class2? #t42 = c2 in #t42.{core::Object::==}(null) ?{core::int} null : let final core::int #t43 = 0 in let final core::int #t44 = self::Extension|[](#t42, #t43).{core::num::+}(1) in let final void #t45 = self::Extension|[]=(#t42, #t43, #t44) in #t44;
+ let final self::Class2? #t46 = c2 in #t46.{core::Object::==}(null) ?{core::int} null : let final core::int #t47 = 0 in self::Extension|[]=(#t46, #t47, self::Extension|[](#t46, #t47).{core::num::+}(1));
+ let final self::Class2? #t48 = c2 in #t48.{core::Object::==}(null) ?{core::int} null : let final core::int #t49 = 0 in self::Extension|[](#t48, #t49).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t48, #t49, 1) : null;
+ let final self::Class2? #t50 = c2 in #t50.{core::Object::==}(null) ?{core::int} null : let final core::int #t51 = 0 in self::Extension|[](#t50, #t51).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t50, #t51, 1.{core::num::+}(self::Extension|[](c2, 1))) : null;
+}
diff --git a/pkg/front_end/testcases/nnbd/nullable_null.dart.outline.expect b/pkg/front_end/testcases/nnbd/nullable_null.dart.outline.expect
index f782516..9c9d87a 100644
--- a/pkg/front_end/testcases/nnbd/nullable_null.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_null.dart.outline.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
class A<X extends core::Object? = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::X*>*
+ synthetic constructor •() → self::A<self::A::X%>*
;
}
class B extends self::A<core::Null?> {
diff --git a/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.expect
index 8d9c779..263e44a 100644
--- a/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
class A<X extends core::Object? = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::X*>*
+ synthetic constructor •() → self::A<self::A::X%>*
: super core::Object::•()
;
}
@@ -20,10 +20,10 @@
return n;
}
static method foo() → dynamic {
- return <core::List<self::A<core::Null?>>*>[<core::Null?>[], <self::A<core::Null?>>[]];
+ return <core::List<self::A<core::Null?>>>[<core::Null?>[], <self::A<core::Null?>>[]];
}
static method bar() → dynamic {
- return <core::List<self::A<core::Null?>>*>[#C1, #C2];
+ return <core::List<self::A<core::Null?>>>[#C1, #C2];
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect
index 8d9c779..263e44a 100644
--- a/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_null.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
class A<X extends core::Object? = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::X*>*
+ synthetic constructor •() → self::A<self::A::X%>*
: super core::Object::•()
;
}
@@ -20,10 +20,10 @@
return n;
}
static method foo() → dynamic {
- return <core::List<self::A<core::Null?>>*>[<core::Null?>[], <self::A<core::Null?>>[]];
+ return <core::List<self::A<core::Null?>>>[<core::Null?>[], <self::A<core::Null?>>[]];
}
static method bar() → dynamic {
- return <core::List<self::A<core::Null?>>*>[#C1, #C2];
+ return <core::List<self::A<core::Null?>>>[#C1, #C2];
}
static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.outline.expect b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.outline.expect
index 5c95be5..537af02 100644
--- a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.outline.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
class A<T extends core::Object? = core::Object?, S extends core::Object = core::Object> extends core::Object {
- synthetic constructor •() → self::A<self::A::T*, self::A::S*>*
+ synthetic constructor •() → self::A<self::A::T%, self::A::S>*
;
method hest<generic-covariant-impl X extends self::A::T% = self::A::T%, Y extends core::List<self::A::hest::X%> = core::List<self::A::T%>, Z extends core::List<self::A::hest::X?> = core::List<self::A::T?>>() → dynamic
;
diff --git a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.expect b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.expect
index ed9375c..cbc95c4 100644
--- a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
class A<T extends core::Object? = core::Object?, S extends core::Object = core::Object> extends core::Object {
- synthetic constructor •() → self::A<self::A::T*, self::A::S*>*
+ synthetic constructor •() → self::A<self::A::T%, self::A::S>*
: super core::Object::•()
;
method hest<generic-covariant-impl X extends self::A::T% = self::A::T%, Y extends core::List<self::A::hest::X%> = core::List<self::A::T%>, Z extends core::List<self::A::hest::X?> = core::List<self::A::T?>>() → dynamic
diff --git a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.transformed.expect
index ed9375c..cbc95c4 100644
--- a/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/substitution_in_inference.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
class A<T extends core::Object? = core::Object?, S extends core::Object = core::Object> extends core::Object {
- synthetic constructor •() → self::A<self::A::T*, self::A::S*>*
+ synthetic constructor •() → self::A<self::A::T%, self::A::S>*
: super core::Object::•()
;
method hest<generic-covariant-impl X extends self::A::T% = self::A::T%, Y extends core::List<self::A::hest::X%> = core::List<self::A::T%>, Z extends core::List<self::A::hest::X?> = core::List<self::A::T?>>() → dynamic
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect
index ce46e5f..54c224f 100644
--- a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.outline.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
class A<X extends core::Object = core::Object, Y extends core::Object? = core::Object?> extends core::Object {
- synthetic constructor •() → self::A<self::A::X*, self::A::Y*>*
+ synthetic constructor •() → self::A<self::A::X, self::A::Y%>*
;
method foo() → self::A::X
;
@@ -13,19 +13,19 @@
;
}
class B<X extends core::List<self::B::Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?> extends core::Object {
- synthetic constructor •() → self::B<self::B::X*, self::B::Y*>*
+ synthetic constructor •() → self::B<self::B::X, self::B::Y%>*
;
method foo(generic-covariant-impl self::B::X x, generic-covariant-impl self::B::Y% y) → dynamic
;
}
class C<X extends core::List<self::C::Y%>? = core::List<dynamic>?, Y extends core::List<self::C::X%>? = core::List<dynamic>?> extends core::Object {
- synthetic constructor •() → self::C<self::C::X*, self::C::Y*>*
+ synthetic constructor •() → self::C<self::C::X%, self::C::Y%>*
;
method foo(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → dynamic
;
}
class D<X extends self::D::Y% = dynamic, Y extends self::D::Z% = dynamic, Z extends core::Object? = dynamic> extends core::Object {
- synthetic constructor •() → self::D<self::D::X*, self::D::Y*, self::D::Z*>*
+ synthetic constructor •() → self::D<self::D::X%, self::D::Y%, self::D::Z%>*
;
method foo(generic-covariant-impl self::D::X% x, generic-covariant-impl self::D::Y% y, generic-covariant-impl self::D::Z% z) → dynamic
;
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect
index 83c7544..da778be 100644
--- a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
class A<X extends core::Object = core::Object, Y extends core::Object? = core::Object?> extends core::Object {
- synthetic constructor •() → self::A<self::A::X*, self::A::Y*>*
+ synthetic constructor •() → self::A<self::A::X, self::A::Y%>*
: super core::Object::•()
;
method foo() → self::A::X
@@ -14,19 +14,19 @@
return null;
}
class B<X extends core::List<self::B::Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?> extends core::Object {
- synthetic constructor •() → self::B<self::B::X*, self::B::Y*>*
+ synthetic constructor •() → self::B<self::B::X, self::B::Y%>*
: super core::Object::•()
;
method foo(generic-covariant-impl self::B::X x, generic-covariant-impl self::B::Y% y) → dynamic {}
}
class C<X extends core::List<self::C::Y%>? = core::List<dynamic>?, Y extends core::List<self::C::X%>? = core::List<dynamic>?> extends core::Object {
- synthetic constructor •() → self::C<self::C::X*, self::C::Y*>*
+ synthetic constructor •() → self::C<self::C::X%, self::C::Y%>*
: super core::Object::•()
;
method foo(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → dynamic {}
}
class D<X extends self::D::Y% = dynamic, Y extends self::D::Z% = dynamic, Z extends core::Object? = dynamic> extends core::Object {
- synthetic constructor •() → self::D<self::D::X*, self::D::Y*, self::D::Z*>*
+ synthetic constructor •() → self::D<self::D::X%, self::D::Y%, self::D::Z%>*
: super core::Object::•()
;
method foo(generic-covariant-impl self::D::X% x, generic-covariant-impl self::D::Y% y, generic-covariant-impl self::D::Z% z) → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect
index 83c7544..da778be 100644
--- a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.strong.transformed.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
class A<X extends core::Object = core::Object, Y extends core::Object? = core::Object?> extends core::Object {
- synthetic constructor •() → self::A<self::A::X*, self::A::Y*>*
+ synthetic constructor •() → self::A<self::A::X, self::A::Y%>*
: super core::Object::•()
;
method foo() → self::A::X
@@ -14,19 +14,19 @@
return null;
}
class B<X extends core::List<self::B::Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?> extends core::Object {
- synthetic constructor •() → self::B<self::B::X*, self::B::Y*>*
+ synthetic constructor •() → self::B<self::B::X, self::B::Y%>*
: super core::Object::•()
;
method foo(generic-covariant-impl self::B::X x, generic-covariant-impl self::B::Y% y) → dynamic {}
}
class C<X extends core::List<self::C::Y%>? = core::List<dynamic>?, Y extends core::List<self::C::X%>? = core::List<dynamic>?> extends core::Object {
- synthetic constructor •() → self::C<self::C::X*, self::C::Y*>*
+ synthetic constructor •() → self::C<self::C::X%, self::C::Y%>*
: super core::Object::•()
;
method foo(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → dynamic {}
}
class D<X extends self::D::Y% = dynamic, Y extends self::D::Z% = dynamic, Z extends core::Object? = dynamic> extends core::Object {
- synthetic constructor •() → self::D<self::D::X*, self::D::Y*, self::D::Z*>*
+ synthetic constructor •() → self::D<self::D::X%, self::D::Y%, self::D::Z%>*
: super core::Object::•()
;
method foo(generic-covariant-impl self::D::X% x, generic-covariant-impl self::D::Y% y, generic-covariant-impl self::D::Z% z) → dynamic {}
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index 33482fb..c400d6f 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -2,12 +2,6 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE.md file.
-inference/downwards_inference_on_list_literals_infer_if_value_types_match_context: ExpectationFileMismatchSerialized
-inference/generic_methods_infer_generic_function_parameter_type2: ExpectationFileMismatchSerialized
-regress/issue_31181: ExpectationFileMismatchSerialized
-regress/issue_31213: ExpectationFileMismatchSerialized
-runtime_checks/contravariant_generic_return_tear_off: ExpectationFileMismatchSerialized
-
general/abstract_members: TypeCheckError
general/bug30695: TypeCheckError
general/bug30695: TypeCheckError
diff --git a/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect
index 896ebc5..8b4190c 100644
--- a/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.expect
@@ -7,11 +7,12 @@
// ^^^^
//
import self as self;
+import "dart:core" as core;
import "dart:math" as math;
static method main() → dynamic {
let final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000031.dart:8:3: Error: A prefix can't be used as an expression.
math..toString();
- ^^^^" in let final void #t2 = #t1.{dart.core::Object::toString}() in #t1;
+ ^^^^" in let final void #t2 = #t1.{core::Object::toString}() in #t1;
}
diff --git a/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect
index 896ebc5..8b4190c 100644
--- a/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000031.dart.strong.transformed.expect
@@ -7,11 +7,12 @@
// ^^^^
//
import self as self;
+import "dart:core" as core;
import "dart:math" as math;
static method main() → dynamic {
let final dynamic #t1 = invalid-expression "pkg/front_end/testcases/rasta/issue_000031.dart:8:3: Error: A prefix can't be used as an expression.
math..toString();
- ^^^^" in let final void #t2 = #t1.{dart.core::Object::toString}() in #t1;
+ ^^^^" in let final void #t2 = #t1.{core::Object::toString}() in #t1;
}
diff --git a/pkg/front_end/testcases/rasta/issue_000032.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000032.dart.outline.expect
index 4045a94..497582b 100644
--- a/pkg/front_end/testcases/rasta/issue_000032.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000032.dart.outline.expect
@@ -7,6 +7,7 @@
// ^
//
// pkg/front_end/testcases/rasta/issue_000032.dart:6:4: Error: Constructors can't have type parameters.
+// Try removing the type parameters.
// C<
// ^^...
//
diff --git a/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect
index 0bcb6e2..f449dd1 100644
--- a/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect
@@ -7,6 +7,7 @@
// ^
//
// pkg/front_end/testcases/rasta/issue_000032.dart:6:4: Error: Constructors can't have type parameters.
+// Try removing the type parameters.
// C<
// ^^...
//
diff --git a/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect
index 0bcb6e2..f449dd1 100644
--- a/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect
@@ -7,6 +7,7 @@
// ^
//
// pkg/front_end/testcases/rasta/issue_000032.dart:6:4: Error: Constructors can't have type parameters.
+// Try removing the type parameters.
// C<
// ^^...
//
diff --git a/pkg/front_end/testcases/regress/issue_29983.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29983.dart.strong.transformed.expect
index 2908e6c..9eae023 100644
--- a/pkg/front_end/testcases/regress/issue_29983.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29983.dart.strong.transformed.expect
@@ -22,7 +22,7 @@
import "dart:core" as core;
static method f() → dynamic /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<dynamic>* :iterator) → core::bool* yielding {
{
@@ -35,7 +35,7 @@
return new core::_SyncIterable::•<dynamic>(:sync_op);
}
static method g() → dynamic /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<dynamic>* :iterator) → core::bool* yielding {
invalid-expression "pkg/front_end/testcases/regress/issue_29983.dart:11:14: Error: 'sync*' and 'async*' can't return a value.
@@ -46,7 +46,7 @@
return new core::_SyncIterable::•<dynamic>(:sync_op);
}
static method h() → dynamic /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<dynamic>* :iterator) → core::bool* yielding {
{
diff --git a/pkg/front_end/testcases/regress/issue_31181.dart.outline.expect b/pkg/front_end/testcases/regress/issue_31181.dart.outline.expect
index 91c2fcb..2181f89 100644
--- a/pkg/front_end/testcases/regress/issue_31181.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_31181.dart.outline.expect
@@ -2,7 +2,7 @@
import self as self;
import "dart:core" as core;
-typedef Foo<invariant T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
+typedef Foo<unrelated T extends core::Object* = dynamic> = <T extends core::Object* = dynamic>(T*) →* T*;
static field <T extends core::Object* = dynamic>(T*) →* T* x;
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect b/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
index a734b9c..b80b64a 100644
--- a/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_31213.dart.outline.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
typedef C<contravariant A extends core::Object* = dynamic, contravariant K extends core::Object* = dynamic> = <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
-typedef D<unrelated K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
+typedef D<contravariant K extends core::Object* = dynamic> = <A extends core::Object* = dynamic>(core::int*) →* <B extends core::Object* = dynamic>(A*, K*, B*) →* core::int*;
static method producer<K extends core::Object* = dynamic>() → dynamic
;
static method main() → dynamic
diff --git a/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
index 26c459c..1175daa 100644
--- a/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34850.dart.strong.transformed.expect
@@ -57,6 +57,7 @@
import self as self;
import "dart:core" as core;
import "dart:async" as asy;
+import "dart:_internal" as _in;
static method f1() → invalid-type {
return null;
@@ -68,7 +69,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -95,7 +96,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -122,7 +123,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -133,7 +134,7 @@
[yield] let dynamic #t1 = asy::_awaitHelper(self::f2(), :async_op_then, :async_op_error, :async_op) in null;
core::print(:result);
[yield] let dynamic #t2 = asy::_awaitHelper(self::f3(), :async_op_then, :async_op_error, :async_op) in null;
- core::print(:result);
+ core::print(_in::unsafeCast<invalid-type>(:result));
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
diff --git a/pkg/front_end/testcases/regress/issue_37681.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_37681.dart.strong.transformed.expect
index 5cffed8..519cf0e 100644
--- a/pkg/front_end/testcases/regress/issue_37681.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_37681.dart.strong.transformed.expect
@@ -17,6 +17,7 @@
import self as self;
import "dart:async" as asy;
import "dart:core" as core;
+import "dart:_internal" as _in;
static method main() → dynamic /* originally async */ {
final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
@@ -24,7 +25,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -40,7 +41,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -62,14 +63,14 @@
return :async_completer.{asy::Completer::future};
}
[yield] let dynamic #t1 = asy::_awaitHelper(f_async.call(), :async_op_then, :async_op_error, :async_op) in null;
- core::print(:result);
+ core::print(_in::unsafeCast<core::int*>(:result));
function f_async_star() → core::int* /* originally async* */ {
asy::_AsyncStarStreamController<dynamic>* :controller;
dynamic :controller_stream;
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -107,7 +108,7 @@
while (true) {
dynamic #t2 = asy::_asyncStarMoveNextHelper(:stream);
[yield] let dynamic #t3 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
- if(:result) {
+ if(_in::unsafeCast<core::bool*>(:result)) {
dynamic x = :for-iterator.{asy::_StreamIterator::current};
{
core::print(x);
@@ -123,7 +124,7 @@
}
}
function f_sync_star() → core::int* /* originally sync* */ {
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :sync_op(core::_SyncIterator<dynamic>* :iterator) → core::bool* yielding {
{
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.outline.expect b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.outline.expect
index 3ab6c88..dd755c5 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_generic_return_tear_off.dart.outline.expect
@@ -3,7 +3,7 @@
import "dart:core" as core;
typedef F<contravariant T extends core::Object* = dynamic> = (T*) →* void;
-typedef G<unrelated T extends core::Object* = dynamic> = () →* (T*) →* void;
+typedef G<contravariant T extends core::Object* = dynamic> = () →* (T*) →* void;
class C<T extends core::Object* = dynamic> extends core::Object {
field (self::C::T*) →* void _x;
constructor •((self::C::T*) →* void _x) → self::C<self::C::T*>*
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
index 5af0f46..3f7f9e6 100644
--- a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
@@ -48,6 +48,7 @@
import "dart:async" as asy;
import "dart:core" as core;
import "dart:collection" as col;
+import "dart:_internal" as _in;
import "dart:async";
import "dart:collection";
@@ -58,7 +59,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -81,25 +82,25 @@
LinkedHashMap<int, bool> lhm = {};
^" in <dynamic, dynamic>{};
[yield] let dynamic #t6 = asy::_awaitHelper(self::mapfun(), :async_op_then, :async_op_error, :async_op) in null;
- core::Map<core::int*, core::bool*>* fm = :result;
+ core::Map<core::int*, core::bool*>* fm = _in::unsafeCast<core::Map<core::int*, core::bool*>*>(:result);
[yield] let dynamic #t7 = asy::_awaitHelper(self::setfun(), :async_op_then, :async_op_error, :async_op) in null;
- core::Set<core::int*>* fs = :result;
+ core::Set<core::int*>* fs = _in::unsafeCast<core::Set<core::int*>*>(:result);
[yield] let dynamic #t8 = asy::_awaitHelper(self::iterablefun(), :async_op_then, :async_op_error, :async_op) in null;
- core::Iterable<core::int*>* fi = :result;
+ core::Iterable<core::int*>* fi = _in::unsafeCast<core::Iterable<core::int*>*>(:result);
[yield] let dynamic #t9 = asy::_awaitHelper(self::lhsfun(), :async_op_then, :async_op_error, :async_op) in null;
- col::LinkedHashSet<core::int*>* flhs = :result;
+ col::LinkedHashSet<core::int*>* flhs = _in::unsafeCast<col::LinkedHashSet<core::int*>*>(:result);
[yield] let dynamic #t10 = asy::_awaitHelper(self::lhmfun(), :async_op_then, :async_op_error, :async_op) in null;
- col::LinkedHashMap<core::int*, core::bool*>* flhm = :result;
+ col::LinkedHashMap<core::int*, core::bool*>* flhm = _in::unsafeCast<col::LinkedHashMap<core::int*, core::bool*>*>(:result);
[yield] let dynamic #t11 = asy::_awaitHelper(self::mapfun2(), :async_op_then, :async_op_error, :async_op) in null;
- core::Map<core::int*, core::bool*>* fm2 = :result;
+ core::Map<core::int*, core::bool*>* fm2 = _in::unsafeCast<core::Map<core::int*, core::bool*>*>(:result);
[yield] let dynamic #t12 = asy::_awaitHelper(self::setfun2(), :async_op_then, :async_op_error, :async_op) in null;
- core::Set<core::int*>* fs2 = :result;
+ core::Set<core::int*>* fs2 = _in::unsafeCast<core::Set<core::int*>*>(:result);
[yield] let dynamic #t13 = asy::_awaitHelper(self::iterablefun2(), :async_op_then, :async_op_error, :async_op) in null;
- core::Iterable<core::int*>* fi2 = :result;
+ core::Iterable<core::int*>* fi2 = _in::unsafeCast<core::Iterable<core::int*>*>(:result);
[yield] let dynamic #t14 = asy::_awaitHelper(self::lhsfun2(), :async_op_then, :async_op_error, :async_op) in null;
- col::LinkedHashSet<core::int*>* flhs2 = :result;
+ col::LinkedHashSet<core::int*>* flhs2 = _in::unsafeCast<col::LinkedHashSet<core::int*>*>(:result);
[yield] let dynamic #t15 = asy::_awaitHelper(self::lhmfun2(), :async_op_then, :async_op_error, :async_op) in null;
- col::LinkedHashMap<core::int*, core::bool*>* flhm2 = :result;
+ col::LinkedHashMap<core::int*, core::bool*>* flhm2 = _in::unsafeCast<col::LinkedHashMap<core::int*, core::bool*>*>(:result);
}
asy::_completeOnAsyncReturn(:async_completer, :return_value);
return;
@@ -119,7 +120,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -146,7 +147,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -173,7 +174,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -200,7 +201,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -232,7 +233,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 626187039..a50207f 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -62,7 +62,7 @@
general/type_parameter_type_named_int: RuntimeError # Expected
general/type_variable_as_super: RuntimeError
general/type_variable_bound_access: TypeCheckError
-general/unsound_promotion: RuntimeError
+general/unsound_promotion: TypeCheckError
general/void_methods: RuntimeError
general/warn_unresolved_sends: InstrumentationMismatch # Test assumes Dart 1.0 semantics
inference/abstract_class_instantiation: InstrumentationMismatch # Issue #30040
@@ -111,8 +111,8 @@
inference_new/invalid_assignment_during_toplevel_inference: TypeCheckError
instantiate_to_bound/non_simple_class_parametrized_typedef_cycle: RuntimeError # Expected
instantiate_to_bound/non_simple_generic_function_in_bound_regress: RuntimeError # Expected
-nnbd/nullable_param: RuntimeError
nnbd/inheritance_from_opt_out: TypeCheckError
+nnbd/nullable_param: RuntimeError
rasta/abstract_constructor: RuntimeError
rasta/bad_constructor_redirection: RuntimeError
rasta/bad_continue: RuntimeError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index c70f507..02dd58d 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -10,6 +10,7 @@
expression/main: TextSerializationFailure # Was: Pass
extensions/annotations: TextSerializationFailure
extensions/builtin_identifiers: TextSerializationFailure
+extensions/call_methods: TextSerializationFailure
extensions/check_bounds: TextSerializationFailure
extensions/compounds: TextSerializationFailure
extensions/conflict_with_object: TextSerializationFailure
@@ -87,6 +88,8 @@
general/async_function: TextSerializationFailure # Was: Pass
general/async_nested: TextSerializationFailure # Was: Pass
general/await: TextSerializationFailure # Was: Pass
+general/await_complex: TextSerializationFailure
+general/await_in_cascade: TextSerializationFailure
general/await_in_non_async: TextSerializationFailure
general/bad_setter_abstract: TextSerializationFailure # Was: Pass
general/bad_store: TextSerializationFailure # Was: Pass
@@ -167,6 +170,7 @@
general/external: TextSerializationFailure # Was: Pass
general/external_import: TextSerializationFailure # Was: RuntimeError # The native extension to import doesn't exist. This is ok.
general/fallthrough: TextSerializationFailure
+general/ffi_sample: TextSerializationFailure
general/fibonacci: TextSerializationFailure # Was: Pass
general/for_in_scope: TextSerializationFailure # Was: Pass
general/for_in_without_declaration: TextSerializationFailure
@@ -212,6 +216,8 @@
general/issue38943: TextSerializationFailure
general/issue38944: TextSerializationFailure
general/issue38961: TextSerializationFailure
+general/issue39344: TextSerializationFailure
+general/issue39421: TextSerializationFailure
general/literals: TextSerializationFailure # Was: Pass
general/local_generic_function: TextSerializationFailure # Was: Pass
general/long_chain_of_typedefs: TextSerializationFailure
@@ -317,7 +323,7 @@
general/undefined: TextSerializationFailure # Was: Pass
general/undefined_getter_in_compound_assignment: TextSerializationFailure # Was: Pass
general/uninitialized_fields: TextSerializationFailure # Was: Pass
-general/unsound_promotion: TextSerializationFailure
+general/unsound_promotion: TypeCheckError
general/unused_methods: TextSerializationFailure # Was: Pass
general/var_as_type_name: TextSerializationFailure # Was: Pass
general/void_methods: TextSerializationFailure
@@ -889,6 +895,28 @@
instantiate_to_bound/typedef_omitted_bound: TextSerializationFailure # Was: Pass
instantiate_to_bound/typedef_raw_in_bound: TextSerializationFailure # Was: Pass
instantiate_to_bound/typedef_super_bounded_type: TextSerializationFailure # Was: Pass
+late_lowering/instance_field_with_initializer: TextSerializationFailure
+late_lowering/instance_field_without_initializer: TextSerializationFailure
+late_lowering/instance_final_field_without_initializer: TextSerializationFailure
+late_lowering/instance_nullable_field_with_initializer: TextSerializationFailure
+late_lowering/instance_nullable_field_without_initializer: TextSerializationFailure
+late_lowering/instance_nullable_final_field_without_initializer: TextSerializationFailure
+late_lowering/late_field_with_initializer: TextSerializationFailure
+late_lowering/late_field_without_initializer: TextSerializationFailure
+late_lowering/late_final_field_with_initializer: TextSerializationFailure
+late_lowering/late_final_field_without_initializer: TextSerializationFailure
+late_lowering/late_final_nullable_field_with_initializer: TextSerializationFailure
+late_lowering/late_final_nullable_field_without_initializer: TextSerializationFailure
+late_lowering/late_nullable_field_with_initializer: TextSerializationFailure
+late_lowering/late_nullable_field_without_initializer: TextSerializationFailure
+late_lowering/late_final_local_with_initializer: TextSerializationFailure
+late_lowering/late_final_local_without_initializer: TextSerializationFailure
+late_lowering/late_final_nullable_local_with_initializer: TextSerializationFailure
+late_lowering/late_final_nullable_local_without_initializer: TextSerializationFailure
+late_lowering/late_local_with_initializer: TextSerializationFailure
+late_lowering/late_local_without_initializer: TextSerializationFailure
+late_lowering/late_nullable_local_with_initializer: TextSerializationFailure
+late_lowering/late_nullable_local_without_initializer: TextSerializationFailure
new_const_insertion/simple: TextSerializationFailure # Was: Pass
nnbd/function_types: TextSerializationFailure
nnbd/inheritance_from_opt_out: TypeCheckError
@@ -898,8 +926,10 @@
nnbd/late: TextSerializationFailure
nnbd/null_check: TextSerializationFailure
nnbd/null_shorting: TextSerializationFailure
+nnbd/null_shorting_cascade: TextSerializationFailure
nnbd/null_shorting_explicit_extension: TextSerializationFailure
nnbd/null_shorting_extension: TextSerializationFailure
+nnbd/null_shorting_index: TextSerializationFailure
nnbd/nullable_null: TextSerializationFailure
nnbd/nullable_param: TextSerializationFailure
nnbd/opt_out: TextSerializationFailure
@@ -1172,5 +1202,5 @@
top_level_variance_test: TextSerializationFailure
unified_collections/mixed_entries: TextSerializationFailure
variance/class_type_parameter_modifier: TextSerializationFailure
-variance/mixin_type_parameter_modifier: TextSerializationFailure
variance/generic_covariance_sound_variance: TextSerializationFailure
+variance/mixin_type_parameter_modifier: TextSerializationFailure
diff --git a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart
index 9400df5..058c7be 100644
--- a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart
+++ b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart
@@ -20,7 +20,7 @@
class B<inout T> {
T x;
- T method(T x) => null;
+ T method(T x) => x;
void set y(T x) {}
}
@@ -46,6 +46,10 @@
F(void Function(T) f) : super(f);
}
+class NoSuchMethod<inout T> implements B<T> {
+ noSuchMethod(_) => 3;
+}
+
main() {
A<int, num, String> a = new A();
expect(null, a.field);
@@ -60,7 +64,7 @@
B<int> b = new B();
b.x = 3;
expect(3, b.x);
- expect(null, b.method(3));
+ expect(3, b.method(3));
b.y = 3;
C<int> c = new C();
@@ -70,6 +74,9 @@
D<Object> d = new F<String>((String s) {});
d.method("test");
+
+ NoSuchMethod<num> nsm = new NoSuchMethod<num>();
+ expect(3, nsm.method(3));
}
expect(expected, actual) {
diff --git a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect
index 6260243..7d0b0e0 100644
--- a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect
+++ b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect
@@ -67,6 +67,20 @@
forwarding-stub method method(generic-covariant-impl self::F::T* x) → core::int*
return super.{self::E::method}(x);
}
+class NoSuchMethod<invariant T extends core::Object* = dynamic> extends core::Object implements self::B<self::NoSuchMethod::T*> {
+ synthetic constructor •() → self::NoSuchMethod<self::NoSuchMethod::T*>*
+ ;
+ method noSuchMethod(core::Invocation* _) → dynamic
+ ;
+ no-such-method-forwarder get x() → self::NoSuchMethod::T*
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#x, 1, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError} self::NoSuchMethod::T*;
+ no-such-method-forwarder method method(self::NoSuchMethod::T* x) → self::NoSuchMethod::T*
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#method, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError} self::NoSuchMethod::T*;
+ no-such-method-forwarder set y(self::NoSuchMethod::T* x) → void
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#y=, 2, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
+ no-such-method-forwarder set x(self::NoSuchMethod::T* value) → void
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#x=, 2, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
+}
static method main() → dynamic
;
static method expect(dynamic expected, dynamic actual) → dynamic
diff --git a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.expect b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.expect
index 0c751d4..fa18fb9 100644
--- a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.expect
+++ b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.expect
@@ -37,7 +37,7 @@
: super core::Object::•()
;
method method(self::B::T* x) → self::B::T*
- return null;
+ return x;
set y(self::B::T* x) → void {}
}
class C<contravariant T extends core::Object* = dynamic> extends core::Object {
@@ -70,6 +70,21 @@
forwarding-stub method method(generic-covariant-impl self::F::T* x) → core::int*
return super.{self::E::method}(x);
}
+class NoSuchMethod<invariant T extends core::Object* = dynamic> extends core::Object implements self::B<self::NoSuchMethod::T*> {
+ synthetic constructor •() → self::NoSuchMethod<self::NoSuchMethod::T*>*
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation* _) → dynamic
+ return 3;
+ no-such-method-forwarder get x() → self::NoSuchMethod::T*
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError} self::NoSuchMethod::T*;
+ no-such-method-forwarder method method(self::NoSuchMethod::T* x) → self::NoSuchMethod::T*
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError} self::NoSuchMethod::T*;
+ no-such-method-forwarder set y(self::NoSuchMethod::T* x) → void
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+ no-such-method-forwarder set x(self::NoSuchMethod::T* value) → void
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
static method main() → dynamic {
self::A<core::int*, core::num*, core::String*>* a = new self::A::•<core::int*, core::num*, core::String*>();
self::expect(null, a.{self::A::field});
@@ -83,7 +98,7 @@
self::B<core::int*>* b = new self::B::•<core::int*>();
b.{self::B::x} = 3;
self::expect(3, b.{self::B::x});
- self::expect(null, b.{self::B::method}(3));
+ self::expect(3, b.{self::B::method}(3));
b.{self::B::y} = 3;
self::C<core::int*>* c = new self::C::•<core::int*>();
self::expect(null, c.{self::C::field});
@@ -91,6 +106,8 @@
c.{self::C::x} = 3;
self::D<core::Object*>* d = new self::F::•<core::String*>((core::String* s) → core::Null? {});
d.{self::D::method}("test");
+ self::NoSuchMethod<core::num*>* nsm = new self::NoSuchMethod::•<core::num*>();
+ self::expect(3, nsm.{self::B::method}(3));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
@@ -100,4 +117,11 @@
constants {
#C1 = null
+ #C2 = #x
+ #C3 = <core::Type*>[]
+ #C4 = <dynamic>[]
+ #C5 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C4}
+ #C6 = #method
+ #C7 = #y=
+ #C8 = #x=
}
diff --git a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect
index 0c751d4..fa18fb9 100644
--- a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.strong.transformed.expect
@@ -37,7 +37,7 @@
: super core::Object::•()
;
method method(self::B::T* x) → self::B::T*
- return null;
+ return x;
set y(self::B::T* x) → void {}
}
class C<contravariant T extends core::Object* = dynamic> extends core::Object {
@@ -70,6 +70,21 @@
forwarding-stub method method(generic-covariant-impl self::F::T* x) → core::int*
return super.{self::E::method}(x);
}
+class NoSuchMethod<invariant T extends core::Object* = dynamic> extends core::Object implements self::B<self::NoSuchMethod::T*> {
+ synthetic constructor •() → self::NoSuchMethod<self::NoSuchMethod::T*>*
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation* _) → dynamic
+ return 3;
+ no-such-method-forwarder get x() → self::NoSuchMethod::T*
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C2, 1, #C3, #C4, core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError} self::NoSuchMethod::T*;
+ no-such-method-forwarder method method(self::NoSuchMethod::T* x) → self::NoSuchMethod::T*
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5))) as{TypeError} self::NoSuchMethod::T*;
+ no-such-method-forwarder set y(self::NoSuchMethod::T* x) → void
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[x]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+ no-such-method-forwarder set x(self::NoSuchMethod::T* value) → void
+ return this.{self::NoSuchMethod::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 2, #C3, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C5)));
+}
static method main() → dynamic {
self::A<core::int*, core::num*, core::String*>* a = new self::A::•<core::int*, core::num*, core::String*>();
self::expect(null, a.{self::A::field});
@@ -83,7 +98,7 @@
self::B<core::int*>* b = new self::B::•<core::int*>();
b.{self::B::x} = 3;
self::expect(3, b.{self::B::x});
- self::expect(null, b.{self::B::method}(3));
+ self::expect(3, b.{self::B::method}(3));
b.{self::B::y} = 3;
self::C<core::int*>* c = new self::C::•<core::int*>();
self::expect(null, c.{self::C::field});
@@ -91,6 +106,8 @@
c.{self::C::x} = 3;
self::D<core::Object*>* d = new self::F::•<core::String*>((core::String* s) → core::Null? {});
d.{self::D::method}("test");
+ self::NoSuchMethod<core::num*>* nsm = new self::NoSuchMethod::•<core::num*>();
+ self::expect(3, nsm.{self::B::method}(3));
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!expected.{core::Object::==}(actual)) {
@@ -100,4 +117,11 @@
constants {
#C1 = null
+ #C2 = #x
+ #C3 = <core::Type*>[]
+ #C4 = <dynamic>[]
+ #C5 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C4}
+ #C6 = #method
+ #C7 = #y=
+ #C8 = #x=
}
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index e2cbcce..47b4925 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -187,7 +187,7 @@
"exclude": []
},
{
- "name": "old_dill_test",
+ "name": "old_dill",
"kind": "Chain",
"source": "test/old_dill_suite.dart",
"path": "testcases/old_dills/dills/",
@@ -198,7 +198,7 @@
"exclude": []
},
{
- "name": "parser_test",
+ "name": "parser",
"kind": "Chain",
"source": "test/parser_suite.dart",
"path": "parser_testcases/",
@@ -210,7 +210,7 @@
"exclude": []
},
{
- "name": "lint_test",
+ "name": "lint",
"kind": "Chain",
"source": "test/lint_suite.dart",
"path": "lib/",
@@ -223,7 +223,7 @@
]
},
{
- "name": "spelling_test_src_test",
+ "name": "spelling_test_src",
"kind": "Chain",
"source": "test/spelling_test_src_suite.dart",
"path": "../",
@@ -238,7 +238,7 @@
]
},
{
- "name": "spelling_test_not_src_test",
+ "name": "spelling_test_not_src",
"kind": "Chain",
"source": "test/spelling_test_not_src_suite.dart",
"path": ".",
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 05a5b83..5644059 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -249,6 +249,7 @@
"--omit-platform": false,
"--fatal": ",",
"--fatal-skip": String,
+ "--force-late-lowering": false,
"--help": false,
// TODO(johnniwinther): Remove legacy option flags. Legacy mode is no longer
// supported.
@@ -304,7 +305,8 @@
final String targetName = options["--target"] ?? "vm";
- final TargetFlags flags = new TargetFlags();
+ final TargetFlags flags = new TargetFlags(
+ forceLateLoweringForTesting: options["--force-late-lowering"]);
final Target target = getTarget(targetName, flags);
if (target == null) {
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index 176909e..6f73514 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -428,6 +428,7 @@
await _runWithPrintRedirection(() => _generator.compile());
results = KernelCompilationResults(
component,
+ const {},
_generator.getClassHierarchy(),
_generator.getCoreTypes(),
component.uriToSource.keys);
@@ -444,6 +445,7 @@
// No bytecode at this step. Bytecode is generated later in _writePackage.
results = await _runWithPrintRedirection(() => compileToKernel(
_mainSource, compilerOptions,
+ includePlatform: options['link-platform'],
aot: options['aot'],
useGlobalTypeFlowAnalysis: options['tfa'],
environmentDefines: environmentDefines,
@@ -528,8 +530,12 @@
KernelCompilationResults results, String filename) async {
final Component component = results.component;
// Compute strongly connected components.
- final strongComponents = StrongComponents(component, _mainSource,
- _compilerOptions.packagesFileUri, _compilerOptions.fileSystem);
+ final strongComponents = StrongComponents(
+ component,
+ results.loadedLibraries,
+ _mainSource,
+ _compilerOptions.packagesFileUri,
+ _compilerOptions.fileSystem);
await strongComponents.computeModules();
// Create JavaScript bundler.
@@ -543,8 +549,13 @@
final sourceFileSink = sourceFile.openWrite();
final manifestFileSink = manifestFile.openWrite();
final sourceMapsFileSink = sourceMapsFile.openWrite();
- bundler.compile(results.classHierarchy, results.coreTypes, sourceFileSink,
- manifestFileSink, sourceMapsFileSink);
+ bundler.compile(
+ results.classHierarchy,
+ results.coreTypes,
+ results.loadedLibraries,
+ sourceFileSink,
+ manifestFileSink,
+ sourceMapsFileSink);
await Future.wait([
sourceFileSink.close(),
manifestFileSink.close(),
@@ -569,7 +580,7 @@
if (_options['incremental']) {
// When loading a single kernel buffer with multiple sub-components,
// the VM expects 'main' to be the first sub-component.
- await forEachPackage(component,
+ await forEachPackage(results,
(String package, List<Library> libraries) async {
_writePackage(results, package, libraries, sink);
}, mainFirst: true);
@@ -597,11 +608,11 @@
final file = new File(_initializeFromDill);
await file.create(recursive: true);
final IOSink sink = file.openWrite();
+ final Set<Library> loadedLibraries = results.loadedLibraries;
final BinaryPrinter printer = filterExternal
? LimitedBinaryPrinter(
sink,
- // ignore: DEPRECATED_MEMBER_USE
- (lib) => !lib.isExternal,
+ (lib) => !loadedLibraries.contains(lib),
true /* excludeUriToSource */)
: printerFactory.newBinaryPrinter(sink);
@@ -613,11 +624,9 @@
} else {
// Generate AST as the output proper.
final IOSink sink = File(filename).openWrite();
+ final Set<Library> loadedLibraries = results.loadedLibraries;
final BinaryPrinter printer = filterExternal
- ? LimitedBinaryPrinter(
- sink,
- // ignore: DEPRECATED_MEMBER_USE
- (lib) => !lib.isExternal,
+ ? LimitedBinaryPrinter(sink, (lib) => !loadedLibraries.contains(lib),
true /* excludeUriToSource */)
: printerFactory.newBinaryPrinter(sink);
@@ -636,12 +645,7 @@
if (_options['split-output-by-packages']) {
await writeOutputSplitByPackages(
- _mainSource,
- _compilerOptions,
- results.component,
- results.coreTypes,
- results.classHierarchy,
- filename,
+ _mainSource, _compilerOptions, results, filename,
genBytecode: _compilerOptions.bytecode,
bytecodeOptions: _bytecodeOptions,
dropAST: _options['drop-ast']);
@@ -731,9 +735,16 @@
Component partComponent = result.component;
if (_compilerOptions.bytecode && errors.isEmpty) {
+ final List<Library> librariesFiltered = new List<Library>();
+ final Set<Library> loadedLibraries = result.loadedLibraries;
+ for (Library library in libraries) {
+ if (loadedLibraries.contains(library)) continue;
+ librariesFiltered.add(library);
+ }
+
generateBytecode(partComponent,
options: _bytecodeOptions,
- libraries: libraries,
+ libraries: librariesFiltered,
coreTypes: _generator?.getCoreTypes(),
hierarchy: _generator?.getClassHierarchy());
@@ -743,8 +754,10 @@
}
final byteSink = ByteSink();
- final BinaryPrinter printer = LimitedBinaryPrinter(byteSink,
- (lib) => packageFor(lib) == package, false /* excludeUriToSource */);
+ final BinaryPrinter printer = LimitedBinaryPrinter(
+ byteSink,
+ (lib) => packageFor(lib, result.loadedLibraries) == package,
+ false /* excludeUriToSource */);
printer.writeComponentFile(partComponent);
final bytes = byteSink.builder.takeBytes();
@@ -771,6 +784,7 @@
KernelCompilationResults results = KernelCompilationResults(
deltaProgram,
+ const {},
_generator.getClassHierarchy(),
_generator.getCoreTypes(),
deltaProgram.uriToSource.keys);
@@ -923,9 +937,9 @@
@override
Future<void> rejectLastDelta() async {
- await _generator.reject();
final String boundaryKey = Uuid().generateV4();
_outputStream.writeln('result $boundaryKey');
+ await _generator.reject();
_outputStream.writeln(boundaryKey);
}
diff --git a/pkg/frontend_server/lib/src/javascript_bundle.dart b/pkg/frontend_server/lib/src/javascript_bundle.dart
index 2ed86d3..1178433 100644
--- a/pkg/frontend_server/lib/src/javascript_bundle.dart
+++ b/pkg/frontend_server/lib/src/javascript_bundle.dart
@@ -50,15 +50,20 @@
Map<Uri, Component> _uriToComponent;
/// Compile each component into a single JavaScript module.
- void compile(ClassHierarchy classHierarchy, CoreTypes coreTypes,
- IOSink codeSink, IOSink manifestSink, IOSink sourceMapsSink) {
+ void compile(
+ ClassHierarchy classHierarchy,
+ CoreTypes coreTypes,
+ Set<Library> loadedLibraries,
+ IOSink codeSink,
+ IOSink manifestSink,
+ IOSink sourceMapsSink) {
var codeOffset = 0;
var sourceMapOffset = 0;
final manifest = <String, Map<String, List<int>>>{};
final Set<Uri> visited = <Uri>{};
for (Library library in _originalComponent.libraries) {
- // ignore: DEPRECATED_MEMBER_USE
- if (library.isExternal || library.importUri.scheme == 'dart') {
+ if (loadedLibraries.contains(library) ||
+ library.importUri.scheme == 'dart') {
continue;
}
final Uri moduleUri = _strongComponents.moduleAssignment[library.fileUri];
diff --git a/pkg/frontend_server/lib/src/strong_components.dart b/pkg/frontend_server/lib/src/strong_components.dart
index bf2cf8d6..534cb30 100644
--- a/pkg/frontend_server/lib/src/strong_components.dart
+++ b/pkg/frontend_server/lib/src/strong_components.dart
@@ -29,6 +29,7 @@
class StrongComponents {
StrongComponents(
this.component,
+ this.loadedLibraries,
this.mainUri, [
this.packagesUri,
this.fileSystem,
@@ -40,6 +41,9 @@
/// lbraries.
final Component component;
+ /// The libraries loaded from a dill file that should not be processed.
+ final Set<Library> loadedLibraries;
+
/// The main URI for thiis application.
final Uri mainUri;
@@ -90,7 +94,7 @@
}
final List<List<Library>> results =
- computeStrongComponents(_LibraryGraph(entrypoint));
+ computeStrongComponents(_LibraryGraph(entrypoint, loadedLibraries));
for (List<Library> component in results) {
assert(component.length > 0);
final Uri moduleUri = component.first.fileUri;
@@ -149,16 +153,16 @@
}
class _LibraryGraph implements Graph<Library> {
- _LibraryGraph(this.library);
+ _LibraryGraph(this.library, this.loadedLibraries);
final Library library;
+ final Set<Library> loadedLibraries;
@override
Iterable<Library> neighborsOf(Library vertex) {
return <Library>[
for (LibraryDependency dependency in vertex.dependencies)
- // ignore: DEPRECATED_MEMBER_USE
- if (!dependency.targetLibrary.isExternal &&
+ if (!loadedLibraries.contains(dependency.targetLibrary) &&
dependency.targetLibrary.importUri.scheme != 'dart')
dependency.targetLibrary
];
diff --git a/pkg/frontend_server/test/frontend_server_test.dart b/pkg/frontend_server/test/frontend_server_test.dart
index 26d94bd..810c85e 100644
--- a/pkg/frontend_server/test/frontend_server_test.dart
+++ b/pkg/frontend_server/test/frontend_server_test.dart
@@ -1095,14 +1095,18 @@
file.writeAsStringSync("pkgA() {} pkgA_2() {}");
count += 1;
+ outputParser.expectSources = false;
inputStreamController.add('reject\n'.codeUnits);
- inputStreamController.add('reset\n'.codeUnits);
- inputStreamController.add('recompile ${file.path} abc\n'
- '${file.path}\n'
- 'abc\n'
- .codeUnits);
break;
case 1:
+ count += 1;
+ inputStreamController.add('reset\n'.codeUnits);
+ inputStreamController.add('recompile ${file.path} abc\n'
+ '${file.uri}\n'
+ 'abc\n'
+ .codeUnits);
+ break;
+ case 2:
expect(dillFile.existsSync(), equals(true));
expect(result.filename, dillFile.path);
expect(result.errorsCount, 0);
@@ -1124,11 +1128,11 @@
inputStreamController.add('accept\n'.codeUnits);
inputStreamController.add('reset\n'.codeUnits);
inputStreamController.add('recompile ${file.path} abc\n'
- '${file.path}\n'
- 'abc\n'
+ '${file.uri}\n'
+ 'abc\n'
.codeUnits);
break;
- case 2:
+ case 3:
expect(result.filename, dillFile.path);
expect(result.errorsCount, 0);
inputStreamController.add('quit\n'.codeUnits);
diff --git a/pkg/frontend_server/test/src/javascript_bundle_test.dart b/pkg/frontend_server/test/src/javascript_bundle_test.dart
index b6d860d..7c491da 100644
--- a/pkg/frontend_server/test/src/javascript_bundle_test.dart
+++ b/pkg/frontend_server/test/src/javascript_bundle_test.dart
@@ -69,7 +69,7 @@
);
final testComponent = Component(libraries: [library, ...testCoreLibraries]);
final strongComponents =
- StrongComponents(testComponent, Uri.file('/c.dart'));
+ StrongComponents(testComponent, {}, Uri.file('/c.dart'));
strongComponents.computeModules();
final javaScriptBundler =
JavaScriptBundler(testComponent, strongComponents);
@@ -78,7 +78,7 @@
final sourcemapSink = _MemorySink();
javaScriptBundler.compile(ClassHierarchy(testComponent),
- CoreTypes(testComponent), codeSink, manifestSink, sourcemapSink);
+ CoreTypes(testComponent), {}, codeSink, manifestSink, sourcemapSink);
final Map manifest = json.decode(utf8.decode(manifestSink.buffer));
final String code = utf8.decode(codeSink.buffer);
@@ -117,7 +117,7 @@
libraries: [libraryA, libraryB, libraryC, ...testCoreLibraries]);
final strongComponents =
- StrongComponents(testComponent, Uri.file('/a.dart'));
+ StrongComponents(testComponent, {}, Uri.file('/a.dart'));
strongComponents.computeModules();
final javaScriptBundler =
JavaScriptBundler(testComponent, strongComponents);
@@ -126,7 +126,7 @@
final sourcemapSink = _MemorySink();
javaScriptBundler.compile(ClassHierarchy(testComponent),
- CoreTypes(testComponent), codeSink, manifestSink, sourcemapSink);
+ CoreTypes(testComponent), {}, codeSink, manifestSink, sourcemapSink);
final code = utf8.decode(codeSink.buffer);
final manifest = json.decode(utf8.decode(manifestSink.buffer));
diff --git a/pkg/frontend_server/test/src/strong_components_test.dart b/pkg/frontend_server/test/src/strong_components_test.dart
index 42dab3b..6d36691 100644
--- a/pkg/frontend_server/test/src/strong_components_test.dart
+++ b/pkg/frontend_server/test/src/strong_components_test.dart
@@ -10,7 +10,7 @@
test('empty component', () {
final testComponent = Component(libraries: []);
final StrongComponents strongComponents =
- StrongComponents(testComponent, Uri.file('/c.dart'));
+ StrongComponents(testComponent, {}, Uri.file('/c.dart'));
strongComponents.computeModules();
expect(strongComponents.modules, {});
@@ -41,7 +41,7 @@
libraryC,
]);
final StrongComponents strongComponents =
- StrongComponents(testComponent, Uri.file('/c.dart'));
+ StrongComponents(testComponent, {}, Uri.file('/c.dart'));
strongComponents.computeModules();
expect(strongComponents.modules, {
@@ -81,7 +81,7 @@
libraryC,
]);
final StrongComponents strongComponents =
- StrongComponents(testComponent, Uri.file('/c.dart'));
+ StrongComponents(testComponent, {}, Uri.file('/c.dart'));
strongComponents.computeModules();
expect(strongComponents.modules, {
@@ -97,8 +97,8 @@
});
});
- test('does not index external, dart:, or unimported libraries', () {
- final libraryExternal = Library(
+ test('does not index loaded , dart:, or unimported libraries', () {
+ final libraryLoaded = Library(
Uri.file('a.dart'),
fileUri: Uri.file('/a.dart'),
isExternal: true,
@@ -115,18 +115,18 @@
Uri.file('/c.dart'),
fileUri: Uri.file('/c.dart'),
dependencies: [
- LibraryDependency.import(libraryExternal),
+ LibraryDependency.import(libraryLoaded),
LibraryDependency.import(libraryDart),
],
);
final testComponent = Component(libraries: [
- libraryExternal,
+ libraryLoaded,
libraryDart,
libraryUnrelated,
libraryC,
]);
final StrongComponents strongComponents =
- StrongComponents(testComponent, Uri.file('/c.dart'));
+ StrongComponents(testComponent, {libraryLoaded}, Uri.file('/c.dart'));
strongComponents.computeModules();
expect(strongComponents.modules, {
diff --git a/pkg/js/proposal.md b/pkg/js/proposal.md
index abc888d..381e85c 100644
--- a/pkg/js/proposal.md
+++ b/pkg/js/proposal.md
@@ -60,7 +60,7 @@
This proposal outlines a series of usability improvements that, taken together,
make it much easier to use JS from Dart and vice versa.
-Here's an example of JS interop is like today, from the [Firebase package](https://pub.dartlang.org/packages/firebase):
+Here's an example of JS interop is like today, from the [Firebase package](https://pub.dev/packages/firebase):
```dart
import 'interop/app_interop.dart';
diff --git a/pkg/kernel/bin/transform.dart b/pkg/kernel/bin/transform.dart
index 8285315..40196b4 100755
--- a/pkg/kernel/bin/transform.dart
+++ b/pkg/kernel/bin/transform.dart
@@ -20,6 +20,7 @@
import 'package:kernel/transformations/empty.dart' as empty;
import 'package:kernel/transformations/method_call.dart' as method_call;
import 'package:kernel/transformations/mixin_full_resolution.dart' as mix;
+import 'package:kernel/type_environment.dart';
import 'package:kernel/vm/constants_native_effects.dart';
ArgParser parser = new ArgParser()
@@ -87,10 +88,11 @@
final coreTypes = new CoreTypes(component);
final hierarchy = new ClassHierarchy(component);
+ final typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
switch (options['transformation']) {
case 'continuation':
bool productMode = defines["dart.vm.product"] == "true";
- component = cont.transformComponent(coreTypes, component,
+ component = cont.transformComponent(typeEnvironment, component,
productMode: productMode);
break;
case 'resolve-mixins':
diff --git a/pkg/kernel/doc/nnbd_api.md b/pkg/kernel/doc/nnbd_api.md
index a0b3781..cfabaeb 100644
--- a/pkg/kernel/doc/nnbd_api.md
+++ b/pkg/kernel/doc/nnbd_api.md
@@ -274,9 +274,212 @@
Fields and variables can be declared using the `late` keyword. To reflect the use of the keyword the CFE sets the `isLate` flag on `Field` and `VariableDeclaration` nodes.
-The plan is to provide an optional desugaring of `late` fields and variables to aid the initial implementation of the feature. The desugaring could be turned on by back ends via a compilation-target flag.
+#### Late field encoding
+An optional desugaring of `late` fields and variables is provided to aid the initial implementation of the feature. The desugaring is enabled if `Target.supportsLateFields` returns `false`.
-*TODO: Expand the section on desugaring.*
+There are 8 variants of the encoding based on whether type of the field is potentially nullable, whether the field is final and whether the field has an initializer.
+
+If a late field is non-nullable, its value is stored in a private nullable field and a field value of `null` signals that the field is uninitialized. Otherwise if a late field is potentially nullable, an additional boolean `_#isSet#` field is generated to tracking whether the field has been initialized.
+
+##### 1) Potentially nullable late field without initializer
+A potentially nullable late non-final field:
+```
+late T? x;
+```
+is encoded as
+```
+bool _#x#isSet = false;
+T? _#x;
+T? get x => _#x#isSet ? _#x : throw new StateError("Field 'x' has not been initialized.");
+void set x(T? value) {
+ _#x#isSet = true;
+ _#x = value;
+}
+```
+
+##### 2) Potentially nullable late final field without initializer
+A potentially nullable late final field _without_ an initializer
+```
+late final T? x;
+```
+is encoded as
+```
+bool _#x#isSet = false;
+T? _#x;
+T? get x => _#x#isSet ? _#x : throw new StateError("Field 'x' has not been initialized.");
+void set x(T? value) {
+ if (_#x#isSet) {
+ throw new StateError('Field x has already been initialized.');
+ } else {
+ _#x#isSet = true;
+ _#x = value;
+ }
+}
+```
+
+##### 3) Potentially nullable late field with initializer
+A potentially nullable late field _with_ initializer `<exp>`
+```
+late T? x = <exp>;
+```
+is encoded as
+```
+bool _#x#isSet = false;
+T? _#x;
+T? get x {
+ if (!_#x#isSet) {
+ _#x#isSet = true;
+ _#x = <exp>;
+ }
+return _#x
+}
+void set x(T? value) {
+ _#x#isSet = true
+ _#x = value;
+}
+```
+
+##### 4) Potentially nullable late final field with initializer
+A potentially nullable late final field _with_ initializer `<exp>`
+```
+late final T? x = <exp>;
+```
+is encoded as
+```
+bool _#x#isSet = false;
+T? _#x;
+T? get x {
+ if (!_#x#isSet) {
+ _#x#isSet = true;
+ _#x = <exp>;
+ }
+ return _#x;
+}
+```
+
+##### 5) Non-nullable late field without initializer
+A non-nullable late non-final field:
+```
+late T x;
+```
+is encoded as
+```
+T? _#x;
+T get x => let T? # = _#x in # == null ? throw new StateError("Field 'x' has not been initialized.") : #;
+void set x(T value) {
+ _#x = value;
+}
+```
+The reason for using a `let` expression here, is that while the private field is nullable, the temporary variable in the `let` expression will be promoted to a non-nullable type when checking against `null`, thus ensuring that the returned value is soundly non-nullable, also when analyzing the kernel ast itself.
+
+##### 6) Non-nullable late final field without initializer
+A non-nullable late final field _without_ an initializer
+```
+late final T x;
+```
+is encoded as
+```
+T? _#x;
+T get x => let T? # = _#x in # == null ? throw new StateError("Field 'x' has not been initialized.") : #;
+void set x(T value) {
+ if (_#x == null) {
+ _#x = value;
+ } else {
+ throw new StateError("Field 'x' has already been initialized.");
+ }
+}
+```
+
+##### 7) Non-nullable late field with initializer
+A non-nullable late field _with_ initializer `<exp>`
+```
+late T x = <exp>;
+```
+is encoded as
+```
+T? _#x;
+T get x => let T? # = _#x in # == null ? _#x = <exp> : #;
+void set x(T value) {
+ _#x = value;
+}
+```
+
+##### 8) Non-nullable late final field with initializer
+A non-nullable late final field _with_ initializer `<exp>`
+```
+late final T x = <exp>;
+```
+is encoded as
+```
+T? _#x;
+T get x => let T? # = _#x in # == null ? _#x = <exp> : _#x;
+```
+
+##### Local variables
+A late local variable is encoded similarly to a late field. Local functions are created which correspond to the getters and setters for late fields.
+
+For instance, a nullable late local _without_ initializer
+```
+method() {
+ late T? x;
+ <lhs> = x;
+ variable = <rhs>;
+}
+```
+is encoded as
+```
+method() {
+ bool #x#isSet = false;
+ T? #x;
+ T? #x#get() => #x#isSet ? #x : throw new StateError("Local 'x' has not been initialized.")
+ T? #x#set(T? value) {
+ _#x#isSet = true;
+ return _#x = value;
+ }
+ <lhs> = #x#get.call();
+ #x#set.call(<rhs>);
+}
+```
+
+##### Instance field initialization
+A field initialization of late _nullable_ instance field
+```
+class Class {
+ late T? x;
+ Class.a();
+ Class.b(this.x);
+ Class.c() : x = <exp>;
+}
+```
+is encoded as
+```
+class Class {
+ bool _#x#isSet = false;
+ T? _#x;
+ Class.a();
+ Class.b(T x) : _#x#isSet true, _#x = x;
+ Class.c() : _#x#isSet = true, _#x = <exp>;
+}
+```
+
+A field initialization of late _non-nullable_ instance field
+```
+class Class {
+ late T x;
+ Class.a();
+ Class.b(this.x);
+ Class.c() : x = <exp>;
+}
+```
+is encoded as
+```
+class Class {
+ T? _#x;
+ Class.a();
+ Class.b(T x) : _#x = x;
+ Class.b() : _#x = <exp>;
+}
+```
### The Null Check Operator
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 8f97938..1c993e3 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -75,6 +75,7 @@
import 'transformations/flags.dart';
import 'text/ast_to_text.dart';
+import 'core_types.dart';
import 'type_algebra.dart';
import 'type_environment.dart';
@@ -705,8 +706,10 @@
final List<TypeParameter> typeParameters;
DartType type;
- // The following two fields describe parameters of the underlying function
- // type. They are needed to keep such attributes as names and annotations.
+ // The following two fields describe parameters of the underlying type when
+ // that is a function type. They are needed to keep such attributes as names
+ // and annotations. When the underlying type is not a function type, they are
+ // empty.
final List<TypeParameter> typeParametersOfFunctionType;
final List<VariableDeclaration> positionalParameters;
final List<VariableDeclaration> namedParameters;
@@ -730,11 +733,6 @@
Library get enclosingLibrary => parent;
- TypedefType get thisType {
- return new TypedefType(
- this, Nullability.legacy, _getAsTypeArguments(typeParameters));
- }
-
R accept<R>(TreeVisitor<R> v) {
return v.visitTypedef(this);
}
@@ -1226,13 +1224,13 @@
}
Supertype get asThisSupertype {
- return new Supertype(this, _getAsTypeArguments(typeParameters));
+ return new Supertype(
+ this, getAsTypeArguments(typeParameters, this.enclosingLibrary));
}
- InterfaceType _thisType;
- InterfaceType get thisType {
- return _thisType ??= new InterfaceType(
- this, Nullability.legacy, _getAsTypeArguments(typeParameters));
+ /// Returns the type of `this` for the class using [coreTypes] for caching.
+ InterfaceType getThisType(CoreTypes coreTypes, Nullability nullability) {
+ return coreTypes.thisInterfaceType(this, nullability);
}
InterfaceType _bottomType;
@@ -2571,10 +2569,7 @@
abstract class Expression extends TreeNode {
/// Returns the static type of the expression.
- ///
- /// Shouldn't be used on code compiled in legacy mode, as this method assumes
- /// the IR is strongly typed.
- DartType getStaticType(TypeEnvironment types);
+ DartType getStaticType(StaticTypeContext context);
/// Returns the static type of the expression as an instantiation of
/// [superclass].
@@ -2587,32 +2582,36 @@
/// If this is not the case, either an exception is thrown or the raw type of
/// [superclass] is returned.
InterfaceType getStaticTypeAsInstanceOf(
- Class superclass, TypeEnvironment types) {
+ Class superclass, StaticTypeContext context) {
// This method assumes the program is correctly typed, so if the superclass
// is not generic, we can just return its raw type without computing the
// type of this expression. It also ensures that all types are considered
// subtypes of Object (not just interface types), and function types are
// considered subtypes of Function.
if (superclass.typeParameters.isEmpty) {
- return types.coreTypes.legacyRawType(superclass);
+ return context.typeEnvironment.coreTypes
+ .rawType(superclass, context.nonNullable);
}
- var type = getStaticType(types);
+ var type = getStaticType(context);
while (type is TypeParameterType) {
TypeParameterType typeParameterType = type;
type =
typeParameterType.promotedBound ?? typeParameterType.parameter.bound;
}
- if (type == types.nullType) {
+ if (type == context.typeEnvironment.nullType) {
return superclass.bottomType;
}
if (type is InterfaceType) {
- var upcastType = types.getTypeAsInstanceOf(type, superclass);
+ var upcastType =
+ context.typeEnvironment.getTypeAsInstanceOf(type, superclass);
if (upcastType != null) return upcastType;
} else if (type is BottomType) {
return superclass.bottomType;
}
- types.typeError(this, '$type is not a subtype of $superclass');
- return types.coreTypes.legacyRawType(superclass);
+ context.typeEnvironment
+ .typeError(this, '$type is not a subtype of $superclass');
+ return context.typeEnvironment.coreTypes
+ .rawType(superclass, context.nonNullable);
}
R accept<R>(ExpressionVisitor<R> v);
@@ -2630,7 +2629,7 @@
InvalidExpression(this.message);
- DartType getStaticType(TypeEnvironment types) => const BottomType();
+ DartType getStaticType(StaticTypeContext context) => const BottomType();
R accept<R>(ExpressionVisitor<R> v) => v.visitInvalidExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -2645,9 +2644,9 @@
VariableDeclaration variable;
DartType promotedType; // Null if not promoted.
- VariableGet(this.variable, [this.promotedType]);
+ VariableGet(this.variable, [this.promotedType]) : assert(variable != null);
- DartType getStaticType(TypeEnvironment types) {
+ DartType getStaticType(StaticTypeContext context) {
return promotedType ?? variable.type;
}
@@ -2673,11 +2672,12 @@
VariableDeclaration variable;
Expression value;
- VariableSet(this.variable, this.value) {
+ VariableSet(this.variable, this.value) : assert(variable != null) {
value?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
+ DartType getStaticType(StaticTypeContext context) =>
+ value.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitVariableSet(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -2718,20 +2718,21 @@
interfaceTargetReference = getMemberReference(member);
}
- DartType getStaticType(TypeEnvironment types) {
+ DartType getStaticType(StaticTypeContext context) {
var interfaceTarget = this.interfaceTarget;
if (interfaceTarget != null) {
Class superclass = interfaceTarget.enclosingClass;
- var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types);
+ var receiverType =
+ receiver.getStaticTypeAsInstanceOf(superclass, context);
return Substitution.fromInterfaceType(receiverType)
.substituteType(interfaceTarget.getterType);
}
// Treat the properties of Object specially.
String nameString = name.name;
if (nameString == 'hashCode') {
- return types.coreTypes.intLegacyRawType;
+ return context.typeEnvironment.coreTypes.intRawType(context.nonNullable);
} else if (nameString == 'runtimeType') {
- return types.coreTypes.typeLegacyRawType;
+ return context.typeEnvironment.coreTypes.typeRawType(context.nonNullable);
}
return const DynamicType();
}
@@ -2742,6 +2743,7 @@
visitChildren(Visitor v) {
receiver?.accept(v);
+ interfaceTarget?.acceptReference(v);
name?.accept(v);
}
@@ -2782,7 +2784,8 @@
interfaceTargetReference = getMemberReference(member);
}
- DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
+ DartType getStaticType(StaticTypeContext context) =>
+ value.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitPropertySet(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -2790,6 +2793,7 @@
visitChildren(Visitor v) {
receiver?.accept(v);
+ interfaceTarget?.acceptReference(v);
name?.accept(v);
value?.accept(v);
}
@@ -2840,9 +2844,9 @@
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
v.visitDirectPropertyGet(this, arg);
- DartType getStaticType(TypeEnvironment types) {
+ DartType getStaticType(StaticTypeContext context) {
Class superclass = target.enclosingClass;
- var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types);
+ var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, context);
return Substitution.fromInterfaceType(receiverType)
.substituteType(target.getterType);
}
@@ -2892,7 +2896,8 @@
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
v.visitDirectPropertySet(this, arg);
- DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
+ DartType getStaticType(StaticTypeContext context) =>
+ value.getStaticType(context);
}
/// Directly call an instance method, bypassing ordinary dispatch.
@@ -2940,13 +2945,14 @@
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
v.visitDirectMethodInvocation(this, arg);
- DartType getStaticType(TypeEnvironment types) {
- if (types.isOverloadedArithmeticOperator(target)) {
- return types.getTypeOfOverloadedArithmetic(receiver.getStaticType(types),
- arguments.positional[0].getStaticType(types));
+ DartType getStaticType(StaticTypeContext context) {
+ if (context.typeEnvironment.isOverloadedArithmeticOperator(target)) {
+ return context.typeEnvironment.getTypeOfOverloadedArithmetic(
+ receiver.getStaticType(context),
+ arguments.positional[0].getStaticType(context));
}
Class superclass = target.enclosingClass;
- var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types);
+ var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, context);
var returnType = Substitution.fromInterfaceType(receiverType)
.substituteType(target.function.returnType);
return Substitution.fromPairs(
@@ -2974,12 +2980,18 @@
interfaceTargetReference = getMemberReference(member);
}
- DartType getStaticType(TypeEnvironment types) {
+ DartType getStaticType(StaticTypeContext context) {
+ if (interfaceTarget == null) {
+ // TODO(johnniwinther): SuperPropertyGet without a target should be
+ // replaced by invalid expressions.
+ return const DynamicType();
+ }
Class declaringClass = interfaceTarget.enclosingClass;
if (declaringClass.typeParameters.isEmpty) {
return interfaceTarget.getterType;
}
- var receiver = types.getTypeAsInstanceOf(types.thisType, declaringClass);
+ var receiver = context.typeEnvironment
+ .getTypeAsInstanceOf(context.thisType, declaringClass);
return Substitution.fromInterfaceType(receiver)
.substituteType(interfaceTarget.getterType);
}
@@ -2989,6 +3001,7 @@
v.visitSuperPropertyGet(this, arg);
visitChildren(Visitor v) {
+ interfaceTarget?.acceptReference(v);
name?.accept(v);
}
@@ -3020,13 +3033,15 @@
interfaceTargetReference = getMemberReference(member);
}
- DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
+ DartType getStaticType(StaticTypeContext context) =>
+ value.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitSuperPropertySet(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
v.visitSuperPropertySet(this, arg);
visitChildren(Visitor v) {
+ interfaceTarget?.acceptReference(v);
name?.accept(v);
value?.accept(v);
}
@@ -3054,7 +3069,7 @@
targetReference = getMemberReference(target);
}
- DartType getStaticType(TypeEnvironment types) => target.getterType;
+ DartType getStaticType(StaticTypeContext context) => target.getterType;
R accept<R>(ExpressionVisitor<R> v) => v.visitStaticGet(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3088,7 +3103,8 @@
targetReference = getMemberReference(target);
}
- DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
+ DartType getStaticType(StaticTypeContext context) =>
+ value.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitStaticSet(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3127,14 +3143,15 @@
positional = <Expression>[],
named = <NamedExpression>[];
- factory Arguments.forwarded(FunctionNode function) {
+ factory Arguments.forwarded(FunctionNode function, Library library) {
return new Arguments(
function.positionalParameters.map((p) => new VariableGet(p)).toList(),
named: function.namedParameters
.map((p) => new NamedExpression(p.name, new VariableGet(p)))
.toList(),
types: function.typeParameters
- .map((p) => new TypeParameterType(p, Nullability.legacy))
+ .map((p) => new TypeParameterType.withDefaultNullabilityForLibrary(
+ p, library))
.toList());
}
@@ -3213,29 +3230,59 @@
interfaceTargetReference = getMemberReference(target);
}
- DartType getStaticType(TypeEnvironment types) {
+ DartType getStaticType(StaticTypeContext context) {
var interfaceTarget = this.interfaceTarget;
if (interfaceTarget != null) {
if (interfaceTarget is Procedure &&
- types.isOverloadedArithmeticOperator(interfaceTarget)) {
- return types.getTypeOfOverloadedArithmetic(
- receiver.getStaticType(types),
- arguments.positional[0].getStaticType(types));
+ context.typeEnvironment
+ .isOverloadedArithmeticOperator(interfaceTarget)) {
+ return context.typeEnvironment.getTypeOfOverloadedArithmetic(
+ receiver.getStaticType(context),
+ arguments.positional[0].getStaticType(context));
}
Class superclass = interfaceTarget.enclosingClass;
- var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, types);
+ var receiverType =
+ receiver.getStaticTypeAsInstanceOf(superclass, context);
var getterType = Substitution.fromInterfaceType(receiverType)
.substituteType(interfaceTarget.getterType);
if (getterType is FunctionType) {
- return Substitution.fromPairs(
- getterType.typeParameters, arguments.types)
- .substituteType(getterType.returnType);
- } else {
- return const DynamicType();
+ Substitution substitution;
+ if (getterType.typeParameters.length == arguments.types.length) {
+ substitution = Substitution.fromPairs(
+ getterType.typeParameters, arguments.types);
+ } else {
+ // TODO(johnniwinther): The front end should normalize the type
+ // argument count or create an invalid expression in case of method
+ // invocations with invalid type argument count.
+ substitution = Substitution.fromPairs(
+ getterType.typeParameters,
+ getterType.typeParameters
+ .map((TypeParameter typeParameter) =>
+ typeParameter.defaultType)
+ .toList());
+ }
+ return substitution.substituteType(getterType.returnType);
}
+ // The front end currently do not replace a property call `o.foo()`, where
+ // `foo` is a field or getter, with a function call on the property,
+ // `o.foo.call()`, so we look up the call method explicitly here.
+ // TODO(johnniwinther): Remove this when the front end performs the
+ // correct replacement.
+ if (getterType is InterfaceType) {
+ Member member = context.typeEnvironment
+ .getInterfaceMember(getterType.classNode, new Name('call'));
+ if (member != null) {
+ DartType callType = member.getterType;
+ if (callType is FunctionType) {
+ return Substitution.fromInterfaceType(getterType)
+ .substituteType(callType.returnType);
+ }
+ }
+ }
+ return const DynamicType();
}
if (name.name == 'call') {
- var receiverType = receiver.getStaticType(types);
+ var receiverType = receiver.getStaticType(context);
if (receiverType is FunctionType) {
if (receiverType.typeParameters.length != arguments.types.length) {
return const BottomType();
@@ -3247,7 +3294,7 @@
}
if (name.name == '==') {
// We use this special case to simplify generation of '==' checks.
- return types.coreTypes.boolLegacyRawType;
+ return context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
}
return const DynamicType();
}
@@ -3258,6 +3305,7 @@
visitChildren(Visitor v) {
receiver?.accept(v);
+ interfaceTarget?.acceptReference(v);
name?.accept(v);
arguments?.accept(v);
}
@@ -3298,10 +3346,11 @@
interfaceTargetReference = getMemberReference(target);
}
- DartType getStaticType(TypeEnvironment types) {
+ DartType getStaticType(StaticTypeContext context) {
if (interfaceTarget == null) return const DynamicType();
Class superclass = interfaceTarget.enclosingClass;
- var receiverType = types.getTypeAsInstanceOf(types.thisType, superclass);
+ var receiverType = context.typeEnvironment
+ .getTypeAsInstanceOf(context.thisType, superclass);
var returnType = Substitution.fromInterfaceType(receiverType)
.substituteType(interfaceTarget.function.returnType);
return Substitution.fromPairs(
@@ -3314,6 +3363,7 @@
v.visitSuperMethodInvocation(this, arg);
visitChildren(Visitor v) {
+ interfaceTarget?.acceptReference(v);
name?.accept(v);
arguments?.accept(v);
}
@@ -3354,7 +3404,7 @@
targetReference = getMemberReference(target);
}
- DartType getStaticType(TypeEnvironment types) {
+ DartType getStaticType(StaticTypeContext context) {
return Substitution.fromPairs(
target.function.typeParameters, arguments.types)
.substituteType(target.function.returnType);
@@ -3407,11 +3457,12 @@
targetReference = getMemberReference(target);
}
- DartType getStaticType(TypeEnvironment types) {
+ DartType getStaticType(StaticTypeContext context) {
return arguments.types.isEmpty
- ? types.coreTypes.legacyRawType(target.enclosingClass)
+ ? context.typeEnvironment.coreTypes
+ .rawType(target.enclosingClass, context.nonNullable)
: new InterfaceType(
- target.enclosingClass, Nullability.legacy, arguments.types);
+ target.enclosingClass, context.nonNullable, arguments.types);
}
R accept<R>(ExpressionVisitor<R> v) => v.visitConstructorInvocation(this);
@@ -3452,8 +3503,8 @@
expression?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) {
- FunctionType type = expression.getStaticType(types);
+ DartType getStaticType(StaticTypeContext context) {
+ FunctionType type = expression.getStaticType(context);
return Substitution.fromPairs(type.typeParameters, typeArguments)
.substituteType(type.withoutTypeParameters);
}
@@ -3487,8 +3538,8 @@
operand?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) =>
- types.coreTypes.boolLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitNot(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) => v.visitNot(this, arg);
@@ -3516,8 +3567,8 @@
right?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) =>
- types.coreTypes.boolLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitLogicalExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3556,7 +3607,7 @@
otherwise?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) => staticType;
+ DartType getStaticType(StaticTypeContext context) => staticType;
R accept<R>(ExpressionVisitor<R> v) => v.visitConditionalExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3602,8 +3653,8 @@
setParents(expressions, this);
}
- DartType getStaticType(TypeEnvironment types) =>
- types.coreTypes.stringLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.stringRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitStringConcatenation(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3633,8 +3684,9 @@
setParents(lists, this);
}
- DartType getStaticType(TypeEnvironment types) {
- return types.literalListType(typeArgument);
+ DartType getStaticType(StaticTypeContext context) {
+ return context.typeEnvironment
+ .literalListType(typeArgument, context.nonNullable);
}
R accept<R>(ExpressionVisitor<R> v) => v.visitListConcatenation(this);
@@ -3670,8 +3722,9 @@
setParents(sets, this);
}
- DartType getStaticType(TypeEnvironment types) {
- return types.literalSetType(typeArgument);
+ DartType getStaticType(StaticTypeContext context) {
+ return context.typeEnvironment
+ .literalSetType(typeArgument, context.nonNullable);
}
R accept<R>(ExpressionVisitor<R> v) => v.visitSetConcatenation(this);
@@ -3710,8 +3763,9 @@
setParents(maps, this);
}
- DartType getStaticType(TypeEnvironment types) {
- return types.literalMapType(keyType, valueType);
+ DartType getStaticType(StaticTypeContext context) {
+ return context.typeEnvironment
+ .literalMapType(keyType, valueType, context.nonNullable);
}
R accept<R>(ExpressionVisitor<R> v) => v.visitMapConcatenation(this);
@@ -3753,10 +3807,11 @@
Class get classNode => classReference.asClass;
- DartType getStaticType(TypeEnvironment types) {
+ DartType getStaticType(StaticTypeContext context) {
return typeArguments.isEmpty
- ? types.coreTypes.legacyRawType(classNode)
- : new InterfaceType(classNode, Nullability.legacy, typeArguments);
+ ? context.typeEnvironment.coreTypes
+ .rawType(classNode, context.nonNullable)
+ : new InterfaceType(classNode, context.nonNullable, typeArguments);
}
R accept<R>(ExpressionVisitor<R> v) => v.visitInstanceCreation(this);
@@ -3806,8 +3861,8 @@
expression.parent = this;
}
- DartType getStaticType(TypeEnvironment types) =>
- expression.getStaticType(types);
+ DartType getStaticType(StaticTypeContext context) =>
+ expression.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitFileUriExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3835,8 +3890,8 @@
operand?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) =>
- types.coreTypes.boolLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitIsExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3879,7 +3934,7 @@
flags = value ? (flags | FlagTypeError) : (flags & ~FlagTypeError);
}
- DartType getStaticType(TypeEnvironment types) => type;
+ DartType getStaticType(StaticTypeContext context) => type;
R accept<R>(ExpressionVisitor<R> v) => v.visitAsExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3910,9 +3965,9 @@
operand?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) =>
- // TODO(johnniwinther): Return `NonNull(operand.getStaticType(types))`.
- operand.getStaticType(types);
+ DartType getStaticType(StaticTypeContext context) =>
+ // TODO(johnniwinther): Return `NonNull(operand.getStaticType(context))`.
+ operand.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitNullCheck(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3943,8 +3998,8 @@
StringLiteral(this.value);
- DartType getStaticType(TypeEnvironment types) =>
- types.coreTypes.stringLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.stringRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitStringLiteral(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3960,8 +4015,8 @@
IntLiteral(this.value);
- DartType getStaticType(TypeEnvironment types) =>
- types.coreTypes.intLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.intRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitIntLiteral(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3973,8 +4028,8 @@
DoubleLiteral(this.value);
- DartType getStaticType(TypeEnvironment types) =>
- types.coreTypes.doubleLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.doubleRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitDoubleLiteral(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3986,8 +4041,8 @@
BoolLiteral(this.value);
- DartType getStaticType(TypeEnvironment types) =>
- types.coreTypes.boolLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitBoolLiteral(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -3997,7 +4052,8 @@
class NullLiteral extends BasicLiteral {
Object get value => null;
- DartType getStaticType(TypeEnvironment types) => types.nullType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.nullType;
R accept<R>(ExpressionVisitor<R> v) => v.visitNullLiteral(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4009,8 +4065,8 @@
SymbolLiteral(this.value);
- DartType getStaticType(TypeEnvironment types) =>
- types.coreTypes.symbolLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.symbolRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitSymbolLiteral(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4025,8 +4081,8 @@
TypeLiteral(this.type);
- DartType getStaticType(TypeEnvironment types) =>
- types.coreTypes.typeLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.typeRawType(context.nonNullable);
R accept<R>(ExpressionVisitor<R> v) => v.visitTypeLiteral(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4042,7 +4098,7 @@
}
class ThisExpression extends Expression {
- DartType getStaticType(TypeEnvironment types) => types.thisType;
+ DartType getStaticType(StaticTypeContext context) => context.thisType;
R accept<R>(ExpressionVisitor<R> v) => v.visitThisExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4053,7 +4109,7 @@
}
class Rethrow extends Expression {
- DartType getStaticType(TypeEnvironment types) => const BottomType();
+ DartType getStaticType(StaticTypeContext context) => const BottomType();
R accept<R>(ExpressionVisitor<R> v) => v.visitRethrow(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4070,7 +4126,7 @@
expression?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) => const BottomType();
+ DartType getStaticType(StaticTypeContext context) => const BottomType();
R accept<R>(ExpressionVisitor<R> v) => v.visitThrow(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) => v.visitThrow(this, arg);
@@ -4098,8 +4154,9 @@
setParents(expressions, this);
}
- DartType getStaticType(TypeEnvironment types) {
- return types.literalListType(typeArgument);
+ DartType getStaticType(StaticTypeContext context) {
+ return context.typeEnvironment
+ .literalListType(typeArgument, context.nonNullable);
}
R accept<R>(ExpressionVisitor<R> v) => v.visitListLiteral(this);
@@ -4128,8 +4185,9 @@
setParents(expressions, this);
}
- DartType getStaticType(TypeEnvironment types) {
- return types.literalSetType(typeArgument);
+ DartType getStaticType(StaticTypeContext context) {
+ return context.typeEnvironment
+ .literalSetType(typeArgument, context.nonNullable);
}
R accept<R>(ExpressionVisitor<R> v) => v.visitSetLiteral(this);
@@ -4162,8 +4220,9 @@
setParents(entries, this);
}
- DartType getStaticType(TypeEnvironment types) {
- return types.literalMapType(keyType, valueType);
+ DartType getStaticType(StaticTypeContext context) {
+ return context.typeEnvironment
+ .literalMapType(keyType, valueType, context.nonNullable);
}
R accept<R>(ExpressionVisitor<R> v) => v.visitMapLiteral(this);
@@ -4219,8 +4278,8 @@
operand?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) {
- return types.unfutureType(operand.getStaticType(types));
+ DartType getStaticType(StaticTypeContext context) {
+ return context.typeEnvironment.unfutureType(operand.getStaticType(context));
}
R accept<R>(ExpressionVisitor<R> v) => v.visitAwaitExpression(this);
@@ -4254,7 +4313,7 @@
function?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) => function.functionType;
+ DartType getStaticType(StaticTypeContext context) => function.functionType;
R accept<R>(ExpressionVisitor<R> v) => v.visitFunctionExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4280,7 +4339,7 @@
assert(constant != null);
}
- DartType getStaticType(TypeEnvironment types) => type;
+ DartType getStaticType(StaticTypeContext context) => type;
R accept<R>(ExpressionVisitor<R> v) => v.visitConstantExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4307,7 +4366,8 @@
body?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) => body.getStaticType(types);
+ DartType getStaticType(StaticTypeContext context) =>
+ body.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitLet(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) => v.visitLet(this, arg);
@@ -4338,7 +4398,8 @@
value?.parent = this;
}
- DartType getStaticType(TypeEnvironment types) => value.getStaticType(types);
+ DartType getStaticType(StaticTypeContext context) =>
+ value.getStaticType(context);
R accept<R>(ExpressionVisitor<R> v) => v.visitBlockExpression(this);
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
@@ -4379,8 +4440,9 @@
LoadLibrary(this.import);
- DartType getStaticType(TypeEnvironment types) {
- return types.futureType(const DynamicType(), Nullability.legacy);
+ DartType getStaticType(StaticTypeContext context) {
+ return context.typeEnvironment
+ .futureType(const DynamicType(), context.nonNullable);
}
R accept<R>(ExpressionVisitor<R> v) => v.visitLoadLibrary(this);
@@ -4398,8 +4460,8 @@
CheckLibraryIsLoaded(this.import);
- DartType getStaticType(TypeEnvironment types) {
- return types.coreTypes.objectLegacyRawType;
+ DartType getStaticType(StaticTypeContext context) {
+ return context.typeEnvironment.coreTypes.objectRawType(context.nonNullable);
}
R accept<R>(ExpressionVisitor<R> v) => v.visitCheckLibraryIsLoaded(this);
@@ -5216,6 +5278,10 @@
flags = value ? (flags | FlagRequired) : (flags & ~FlagRequired);
}
+ void clearAnnotations() {
+ annotations = const <Expression>[];
+ }
+
void addAnnotation(Expression annotation) {
if (annotations.isEmpty) {
annotations = <Expression>[];
@@ -5703,8 +5769,7 @@
/// type.
FunctionType get withoutTypeParameters {
if (typeParameters.isEmpty) return this;
- return new FunctionType(
- positionalParameters, returnType, Nullability.legacy,
+ return new FunctionType(positionalParameters, returnType, nullability,
requiredParameterCount: requiredParameterCount,
namedParameters: namedParameters,
typedefType: null);
@@ -5738,7 +5803,6 @@
hash = 0x3fffffff & (hash * 31 + requiredParameterCount);
for (int i = 0; i < typeParameters.length; ++i) {
TypeParameter parameter = typeParameters[i];
- _temporaryHashCodeTable[parameter] = _temporaryHashCodeTable.length;
hash = 0x3fffffff & (hash * 31 + parameter.bound.hashCode);
}
for (int i = 0; i < positionalParameters.length; ++i) {
@@ -5748,10 +5812,6 @@
hash = 0x3fffffff & (hash * 31 + namedParameters[i].hashCode);
}
hash = 0x3fffffff & (hash * 31 + returnType.hashCode);
- for (int i = 0; i < typeParameters.length; ++i) {
- // Remove the type parameters from the scope again.
- _temporaryHashCodeTable.remove(typeParameters[i]);
- }
hash = 0x3fffffff & (hash * 31 + nullability.index);
return hash;
}
@@ -5872,14 +5932,6 @@
}
}
-/// Stores the hash code of function type parameters while computing the hash
-/// code of a [FunctionType] object.
-///
-/// This ensures that distinct [FunctionType] objects get the same hash code
-/// if they represent the same type, even though their type parameters are
-/// represented by different objects.
-final Map<TypeParameter, int> _temporaryHashCodeTable = <TypeParameter, int>{};
-
/// Reference to a type variable.
///
/// A type variable has an optional bound because type promotion can change the
@@ -5912,6 +5964,35 @@
TypeParameterType(this.parameter, this.typeParameterTypeNullability,
[this.promotedBound]);
+ /// Creates an intersection type between a type parameter and [promotedBound].
+ TypeParameterType.intersection(
+ this.parameter, this.typeParameterTypeNullability, this.promotedBound);
+
+ /// Creates a type-parameter type to be used in alpha-renaming.
+ ///
+ /// The constructed type object is supposed to be used as a value in a
+ /// substitution map created to perform an alpha-renaming from parameter
+ /// [from] to parameter [to] on a generic type. The resulting type-parameter
+ /// type is an occurrence of [to] as a type, but the nullability property is
+ /// derived from the bound of [from]. It allows to assign the bound to [to]
+ /// after the desired alpha-renaming is performed, which is often the case.
+ TypeParameterType.forAlphaRenaming(TypeParameter from, TypeParameter to)
+ : this(to, computeNullabilityFromBound(from));
+
+ /// Creates a type-parameter type with default nullability for the library.
+ ///
+ /// The nullability is computed as if the programmer omitted the modifier. It
+ /// means that in the opt-out libraries `Nullability.legacy` will be used, and
+ /// in opt-in libraries either `Nullability.nonNullable` or
+ /// `Nullability.undetermined` will be used, depending on the nullability of
+ /// the bound of [parameter].
+ TypeParameterType.withDefaultNullabilityForLibrary(
+ this.parameter, Library library) {
+ typeParameterTypeNullability = library.isNonNullableByDefault
+ ? computeNullabilityFromBound(parameter)
+ : Nullability.legacy;
+ }
+
R accept<R>(DartTypeVisitor<R> v) => v.visitTypeParameterType(this);
R accept1<R, A>(DartTypeVisitor1<R, A> v, A arg) =>
v.visitTypeParameterType(this, arg);
@@ -5926,7 +6007,10 @@
}
int get hashCode {
- int hash = _temporaryHashCodeTable[parameter] ?? parameter.hashCode;
+ // TODO(johnniwinther): Since we use a unification strategy for function
+ // type type parameter equality, we have to assume they can end up being
+ // equal. Maybe we should change the equality strategy.
+ int hash = parameter.isFunctionTypeTypeParameter ? 0 : parameter.hashCode;
int nullabilityHash = (0x33333333 >> nullability.index) ^ 0x33333333;
hash = 0x3fffffff & (hash * 31 + (hash ^ nullabilityHash));
hash = 0x3fffffff & (hash * 31 + (hash ^ promotedBound.hashCode));
@@ -6354,7 +6438,7 @@
bool operator ==(Object other);
/// Gets the type of this constant.
- DartType getType(TypeEnvironment types);
+ DartType getType(StaticTypeContext context);
Expression asExpression() {
return new ConstantExpression(this);
@@ -6381,7 +6465,8 @@
R accept<R>(ConstantVisitor<R> v) => v.visitNullConstant(this);
R acceptReference<R>(Visitor<R> v) => v.visitNullConstantReference(this);
- DartType getType(TypeEnvironment types) => types.nullType;
+ DartType getType(StaticTypeContext context) =>
+ context.typeEnvironment.nullType;
}
class BoolConstant extends PrimitiveConstant<bool> {
@@ -6391,7 +6476,8 @@
R accept<R>(ConstantVisitor<R> v) => v.visitBoolConstant(this);
R acceptReference<R>(Visitor<R> v) => v.visitBoolConstantReference(this);
- DartType getType(TypeEnvironment types) => types.coreTypes.boolLegacyRawType;
+ DartType getType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
}
/// An integer constant on a non-JS target.
@@ -6402,7 +6488,8 @@
R accept<R>(ConstantVisitor<R> v) => v.visitIntConstant(this);
R acceptReference<R>(Visitor<R> v) => v.visitIntConstantReference(this);
- DartType getType(TypeEnvironment types) => types.coreTypes.intLegacyRawType;
+ DartType getType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.intRawType(context.nonNullable);
}
/// A double constant on a non-JS target or any numeric constant on a JS target.
@@ -6417,8 +6504,8 @@
bool operator ==(Object other) =>
other is DoubleConstant && identical(value, other.value);
- DartType getType(TypeEnvironment types) =>
- types.coreTypes.doubleLegacyRawType;
+ DartType getType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.doubleRawType(context.nonNullable);
}
class StringConstant extends PrimitiveConstant<String> {
@@ -6430,8 +6517,8 @@
R accept<R>(ConstantVisitor<R> v) => v.visitStringConstant(this);
R acceptReference<R>(Visitor<R> v) => v.visitStringConstantReference(this);
- DartType getType(TypeEnvironment types) =>
- types.coreTypes.stringLegacyRawType;
+ DartType getType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.stringRawType(context.nonNullable);
}
class SymbolConstant extends Constant {
@@ -6459,8 +6546,8 @@
other.name == name &&
other.libraryReference == libraryReference);
- DartType getType(TypeEnvironment types) =>
- types.coreTypes.symbolLegacyRawType;
+ DartType getType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.symbolRawType(context.nonNullable);
}
class MapConstant extends Constant {
@@ -6497,8 +6584,8 @@
other.valueType == valueType &&
listEquals(other.entries, entries));
- DartType getType(TypeEnvironment types) =>
- types.literalMapType(keyType, valueType);
+ DartType getType(StaticTypeContext context) => context.typeEnvironment
+ .literalMapType(keyType, valueType, context.nonNullable);
}
class ConstantMapEntry {
@@ -6544,8 +6631,8 @@
other.typeArgument == typeArgument &&
listEquals(other.entries, entries));
- DartType getType(TypeEnvironment types) =>
- types.literalListType(typeArgument);
+ DartType getType(StaticTypeContext context) => context.typeEnvironment
+ .literalListType(typeArgument, context.nonNullable);
}
class SetConstant extends Constant {
@@ -6578,7 +6665,8 @@
other.typeArgument == typeArgument &&
listEquals(other.entries, entries));
- DartType getType(TypeEnvironment types) => types.literalSetType(typeArgument);
+ DartType getType(StaticTypeContext context) =>
+ context.typeEnvironment.literalSetType(typeArgument, context.nonNullable);
}
class InstanceConstant extends Constant {
@@ -6636,8 +6724,8 @@
mapEquals(other.fieldValues, fieldValues));
}
- DartType getType(TypeEnvironment types) =>
- new InterfaceType(classNode, Nullability.legacy, typeArguments);
+ DartType getType(StaticTypeContext context) =>
+ new InterfaceType(classNode, context.nonNullable, typeArguments);
}
class PartialInstantiationConstant extends Constant {
@@ -6669,8 +6757,8 @@
listEquals(other.types, types);
}
- DartType getType(TypeEnvironment typeEnvironment) {
- final FunctionType type = tearOffConstant.getType(typeEnvironment);
+ DartType getType(StaticTypeContext context) {
+ final FunctionType type = tearOffConstant.getType(context);
final mapping = <TypeParameter, DartType>{};
for (final parameter in type.typeParameters) {
mapping[parameter] = types[mapping.length];
@@ -6709,7 +6797,7 @@
other.procedureReference == procedureReference;
}
- FunctionType getType(TypeEnvironment types) =>
+ FunctionType getType(StaticTypeContext context) =>
procedure.function.functionType;
}
@@ -6734,7 +6822,8 @@
return other is TypeLiteralConstant && other.type == type;
}
- DartType getType(TypeEnvironment types) => types.coreTypes.typeLegacyRawType;
+ DartType getType(StaticTypeContext context) =>
+ context.typeEnvironment.coreTypes.typeRawType(context.nonNullable);
}
class UnevaluatedConstant extends Constant {
@@ -6752,7 +6841,8 @@
R acceptReference<R>(Visitor<R> v) =>
v.visitUnevaluatedConstantReference(this);
- DartType getType(TypeEnvironment types) => expression.getStaticType(types);
+ DartType getType(StaticTypeContext context) =>
+ expression.getStaticType(context);
@override
Expression asExpression() => expression;
@@ -7033,13 +7123,6 @@
}
}
-List<DartType> _getAsTypeArguments(List<TypeParameter> typeParameters) {
- if (typeParameters.isEmpty) return const <DartType>[];
- return new List<DartType>.generate(typeParameters.length,
- (i) => new TypeParameterType(typeParameters[i], Nullability.legacy),
- growable: false);
-}
-
class _ChildReplacer extends Transformer {
final TreeNode child;
final TreeNode replacement;
@@ -7362,3 +7445,16 @@
assert(nameParts[0].startsWith('_'));
return nameParts[0].substring(1);
}
+
+/// Computes a list of [typeParameters] taken as types.
+List<DartType> getAsTypeArguments(
+ List<TypeParameter> typeParameters, Library library) {
+ if (typeParameters.isEmpty) return const <DartType>[];
+ List<DartType> result =
+ new List<DartType>.filled(typeParameters.length, null, growable: false);
+ for (int i = 0; i < result.length; ++i) {
+ result[i] = new TypeParameterType.withDefaultNullabilityForLibrary(
+ typeParameters[i], library);
+ }
+ return result;
+}
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 141f142..50ad84c 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -1338,7 +1338,7 @@
void visitVariableGet(VariableGet node) {
_variableIndexer ??= new VariableIndexer();
int index = _variableIndexer[node.variable];
- assert(index != null);
+ assert(index != null, "No index found for ${node.variable}");
if (index & Tag.SpecializedPayloadMask == index &&
node.promotedType == null) {
writeByte(Tag.SpecializedVariableGet + index);
@@ -1357,7 +1357,7 @@
void visitVariableSet(VariableSet node) {
_variableIndexer ??= new VariableIndexer();
int index = _variableIndexer[node.variable];
- assert(index != null);
+ assert(index != null, "No index found for ${node.variable}");
if (index & Tag.SpecializedPayloadMask == index) {
writeByte(Tag.SpecializedVariableSet + index);
writeOffset(node.fileOffset);
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index dc958c9..b4a2b9a 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -522,7 +522,7 @@
newNode = new TypeParameter(node.name);
typeParams[node] = newNode;
typeSubstitution[node] =
- new TypeParameterType(newNode, Nullability.legacy);
+ new TypeParameterType.forAlphaRenaming(node, newNode);
}
}
}
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index 7524a6d..059e579 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -168,6 +168,10 @@
new Map<Class, InterfaceType>.identity();
final Map<Class, InterfaceType> _nonNullableRawTypes =
new Map<Class, InterfaceType>.identity();
+ final Map<Class, InterfaceType> _thisInterfaceTypes =
+ new Map<Class, InterfaceType>.identity();
+ final Map<Typedef, TypedefType> _thisTypedefTypes =
+ new Map<Typedef, TypedefType>.identity();
CoreTypes(Component component)
: index = new LibraryIndex.coreLibraries(component);
@@ -1229,4 +1233,28 @@
"Unsupported nullability $nullability on an InterfaceType.");
}
}
+
+ InterfaceType thisInterfaceType(Class klass, Nullability nullability) {
+ InterfaceType result = _thisInterfaceTypes[klass];
+ if (result == null) {
+ return _thisInterfaceTypes[klass] = new InterfaceType(klass, nullability,
+ getAsTypeArguments(klass.typeParameters, klass.enclosingLibrary));
+ }
+ if (result.nullability != nullability) {
+ return _thisInterfaceTypes[klass] = result.withNullability(nullability);
+ }
+ return result;
+ }
+
+ TypedefType thisTypedefType(Typedef typedef, Nullability nullability) {
+ TypedefType result = _thisTypedefTypes[typedef];
+ if (result == null) {
+ return _thisTypedefTypes[typedef] = new TypedefType(typedef, nullability,
+ getAsTypeArguments(typedef.typeParameters, typedef.enclosingLibrary));
+ }
+ if (result.nullability != nullability) {
+ return _thisTypedefTypes[typedef] = result.withNullability(nullability);
+ }
+ return result;
+ }
}
diff --git a/pkg/kernel/lib/naive_type_checker.dart b/pkg/kernel/lib/naive_type_checker.dart
index 4f78734..619d2b8 100644
--- a/pkg/kernel/lib/naive_type_checker.dart
+++ b/pkg/kernel/lib/naive_type_checker.dart
@@ -148,8 +148,8 @@
for (int i = 0; i < ownFunction.typeParameters.length; ++i) {
var subParameter = ownFunction.typeParameters[i];
var superParameter = superFunction.typeParameters[i];
- typeParameterMap[subParameter] =
- new TypeParameterType(superParameter, Nullability.legacy);
+ typeParameterMap[subParameter] = new TypeParameterType.forAlphaRenaming(
+ subParameter, superParameter);
}
ownSubstitution = Substitution.combine(
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index 0096017..a92c8d3 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -13,7 +13,6 @@
InvalidType,
NamedType,
NeverType,
- Nullability,
TypeParameter,
TypeParameterType,
Typedef,
@@ -229,7 +228,7 @@
// (https://github.com/dart-lang/sdk/blob/master/docs/language/informal/super-bounded-types.md).
FunctionType functionType = type;
FunctionType cloned = new FunctionType(functionType.positionalParameters,
- functionType.returnType, Nullability.legacy,
+ functionType.returnType, functionType.nullability,
namedParameters: functionType.namedParameters,
typeParameters: functionType.typeParameters,
requiredParameterCount: functionType.requiredParameterCount,
@@ -424,7 +423,7 @@
isCovariant: isCovariant);
}
return new InterfaceType(
- type.classNode, Nullability.legacy, replacedTypeArguments);
+ type.classNode, type.nullability, replacedTypeArguments);
} else if (type is TypedefType && type.typedefNode.typeParameters != null) {
List<DartType> replacedTypeArguments =
new List<DartType>(type.typeArguments.length);
@@ -434,7 +433,7 @@
isCovariant: isCovariant);
}
return new TypedefType(
- type.typedefNode, Nullability.legacy, replacedTypeArguments);
+ type.typedefNode, type.nullability, replacedTypeArguments);
} else if (type is FunctionType) {
var replacedReturnType = convertSuperBoundedToRegularBounded(
typeEnvironment, type.returnType,
@@ -456,7 +455,7 @@
isCovariant: !isCovariant));
}
return new FunctionType(
- replacedPositionalParameters, replacedReturnType, Nullability.legacy,
+ replacedPositionalParameters, replacedReturnType, type.nullability,
namedParameters: replacedNamedParameters,
typeParameters: type.typeParameters,
requiredParameterCount: type.requiredParameterCount,
diff --git a/pkg/kernel/lib/src/future_or.dart b/pkg/kernel/lib/src/future_or.dart
index fd2d9d0..51f35cf 100644
--- a/pkg/kernel/lib/src/future_or.dart
+++ b/pkg/kernel/lib/src/future_or.dart
@@ -30,7 +30,7 @@
if (a == Nullability.legacy || b == Nullability.legacy) {
return Nullability.legacy;
}
- return Nullability.nonNullable;
+ return Nullability.nullable;
}
Nullability computeNullabilityOfFutureOr(
diff --git a/pkg/kernel/lib/src/hierarchy_based_type_environment.dart b/pkg/kernel/lib/src/hierarchy_based_type_environment.dart
index d41962f..5ef4e9f 100644
--- a/pkg/kernel/lib/src/hierarchy_based_type_environment.dart
+++ b/pkg/kernel/lib/src/hierarchy_based_type_environment.dart
@@ -4,7 +4,7 @@
library kernel.hierarchy_based_type_environment;
-import '../ast.dart' show Class, InterfaceType;
+import '../ast.dart' show Class, InterfaceType, Member, Name;
import '../class_hierarchy.dart' show ClassHierarchy;
@@ -22,4 +22,9 @@
InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) {
return hierarchy.getTypeAsInstanceOf(type, superclass);
}
+
+ @override
+ Member getInterfaceMember(Class cls, Name name, {bool setter: false}) {
+ return hierarchy.getInterfaceMember(cls, name, setter: setter);
+ }
}
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 57673c6..afc3160 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -11,8 +11,11 @@
class TargetFlags {
final bool trackWidgetCreation;
+ final bool forceLateLoweringForTesting;
- TargetFlags({this.trackWidgetCreation = false});
+ TargetFlags(
+ {this.trackWidgetCreation = false,
+ this.forceLateLoweringForTesting = false});
}
typedef Target _TargetBuilder(TargetFlags flags);
@@ -223,6 +226,13 @@
/// literals (for const set literals).
bool get supportsSetLiterals => true;
+ /// Whether late fields and variable are support by this target.
+ ///
+ /// If `false`, late fields and variables are lowered fields, getter, setters
+ /// etc. that provide equivalent semantics. See `pkg/kernel/nnbd_api.md` for
+ /// details.
+ bool get supportsLateFields;
+
/// Builds an expression that instantiates an [Invocation] that can be passed
/// to [noSuchMethod].
Expression instantiateInvocation(CoreTypes coreTypes, Expression receiver,
@@ -268,8 +278,9 @@
class NoneTarget extends Target {
final TargetFlags flags;
+ final bool supportsLateFields;
- NoneTarget(this.flags);
+ NoneTarget(this.flags, {this.supportsLateFields: true});
String get name => 'none';
List<String> get extraRequiredLibraries => <String>[];
diff --git a/pkg/kernel/lib/testing/mock_sdk_component.dart b/pkg/kernel/lib/testing/mock_sdk_component.dart
index f37b01c..9943d3e 100644
--- a/pkg/kernel/lib/testing/mock_sdk_component.dart
+++ b/pkg/kernel/lib/testing/mock_sdk_component.dart
@@ -17,7 +17,7 @@
}
var objectClass = addClass(coreLib, new Class(name: 'Object'));
- var objectType = new InterfaceType(objectClass, Nullability.legacy);
+ var objectType = new InterfaceType(objectClass, coreLib.nonNullable);
TypeParameter typeParam(String name, [DartType bound]) {
return new TypeParameter(name, bound ?? objectType);
@@ -47,8 +47,9 @@
class_('List', typeParameters: [
T
], implementedTypes: [
- new Supertype(
- iterable, [new TypeParameterType(T, Nullability.legacy)])
+ new Supertype(iterable, [
+ new TypeParameterType.withDefaultNullabilityForLibrary(T, coreLib)
+ ])
]));
}
addClass(
diff --git a/pkg/kernel/lib/text/serializer_combinators.dart b/pkg/kernel/lib/text/serializer_combinators.dart
index e6db3ac..e166cb2 100644
--- a/pkg/kernel/lib/text/serializer_combinators.dart
+++ b/pkg/kernel/lib/text/serializer_combinators.dart
@@ -483,37 +483,39 @@
}
}
-/// Binds binders from one term in the other and adds them to the environment.
+/// Nested binding pattern that also binds binders from one term in the other.
///
-/// Serializes a [Tuple2] of [pattern] and [term], closing [term] over the
-/// binders found in [pattern]. The binders are added to the enclosing
-/// environment.
+/// Serializes a [Tuple2] of [pattern1] and [pattern2], closing [pattern2] over
+/// the binders found in [pattern1]. The binders from both [pattern1] and
+/// [pattern2] are added to the enclosing environment.
class Rebind<P, T> extends TextSerializer<Tuple2<P, T>> {
- final TextSerializer<P> pattern;
- final TextSerializer<T> term;
+ final TextSerializer<P> pattern1;
+ final TextSerializer<T> pattern2;
- const Rebind(this.pattern, this.term);
+ const Rebind(this.pattern1, this.pattern2);
Tuple2<P, T> readFrom(Iterator<Object> stream, DeserializationState state) {
- P first = pattern.readFrom(stream, state);
+ P first = pattern1.readFrom(stream, state);
var closedState = new DeserializationState(
new DeserializationEnvironment(state.environment)
..binders.addAll(state.environment.binders)
..close(),
state.nameRoot);
- T second = term.readFrom(stream, closedState);
+ T second = pattern2.readFrom(stream, closedState);
+ state.environment.binders.addAll(closedState.environment.binders);
return new Tuple2(first, second);
}
void writeTo(
StringBuffer buffer, Tuple2<P, T> tuple, SerializationState state) {
- pattern.writeTo(buffer, tuple.first, state);
+ pattern1.writeTo(buffer, tuple.first, state);
var closedState =
new SerializationState(new SerializationEnvironment(state.environment)
..binders.addAll(state.environment.binders)
..close());
buffer.write(' ');
- term.writeTo(buffer, tuple.second, closedState);
+ pattern2.writeTo(buffer, tuple.second, closedState);
+ state.environment.binders.addAll(closedState.environment.binders);
}
}
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index 6aa0943..d2a9bb6 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -115,6 +115,8 @@
? "invoke-const-constructor"
: "invoke-constructor";
}
+
+ String visitFunctionExpression(FunctionExpression _) => "fun";
}
TextSerializer<InvalidExpression> invalidExpressionSerializer = new Wrapped(
@@ -691,6 +693,17 @@
isConst: true);
}
+TextSerializer<FunctionExpression> functionExpressionSerializer = new Wrapped(
+ unwrapFunctionExpression, wrapFunctionExpression, functionNodeSerializer);
+
+FunctionNode unwrapFunctionExpression(FunctionExpression expression) {
+ return expression.function;
+}
+
+FunctionExpression wrapFunctionExpression(FunctionNode node) {
+ return new FunctionExpression(node);
+}
+
Case<Expression> expressionSerializer =
new Case.uninitialized(const ExpressionTagger());
@@ -975,6 +988,7 @@
String tag(Statement statement) => statement.accept(this);
String visitExpressionStatement(ExpressionStatement _) => "expr";
+ String visitReturnStatement(ReturnStatement _) => "ret";
}
TextSerializer<ExpressionStatement> expressionStatementSerializer = new Wrapped(
@@ -988,9 +1002,231 @@
return new ExpressionStatement(expression);
}
+TextSerializer<ReturnStatement> returnStatementSerializer = new Wrapped(
+ unwrapReturnStatement, wrapReturnStatement, expressionSerializer);
+
+Expression unwrapReturnStatement(ReturnStatement statement) {
+ return statement.expression;
+}
+
+ReturnStatement wrapReturnStatement(Expression expression) {
+ return new ReturnStatement(expression);
+}
+
Case<Statement> statementSerializer =
new Case.uninitialized(const StatementTagger());
+class FunctionNodeTagger implements Tagger<FunctionNode> {
+ const FunctionNodeTagger();
+
+ String tag(FunctionNode node) {
+ switch (node.asyncMarker) {
+ case AsyncMarker.Async:
+ return "async";
+ case AsyncMarker.Sync:
+ return "sync";
+ case AsyncMarker.AsyncStar:
+ return "async-star";
+ case AsyncMarker.SyncStar:
+ return "sync-star";
+ case AsyncMarker.SyncYielding:
+ return "sync-yielding";
+ }
+ throw new UnsupportedError("${node.asyncMarker}");
+ }
+}
+
+TextSerializer<FunctionNode> syncFunctionNodeSerializer = new Wrapped(
+ unwrapFunctionNode,
+ wrapSyncFunctionNode,
+ new Bind(
+ new Rebind(
+ typeParametersSerializer,
+ new Tuple3Serializer(
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)),
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)),
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)))),
+ new Tuple2Serializer(dartTypeSerializer, statementSerializer)));
+
+Tuple2<
+ Tuple2<
+ List<TypeParameter>,
+ Tuple3<List<VariableDeclaration>, List<VariableDeclaration>,
+ List<VariableDeclaration>>>,
+ Tuple2<DartType, Statement>> unwrapFunctionNode(FunctionNode node) {
+ return new Tuple2(
+ new Tuple2(
+ node.typeParameters,
+ new Tuple3(
+ node.positionalParameters.sublist(0, node.requiredParameterCount),
+ node.positionalParameters.sublist(node.requiredParameterCount),
+ node.namedParameters)),
+ new Tuple2(node.returnType, node.body));
+}
+
+FunctionNode wrapSyncFunctionNode(
+ Tuple2<
+ Tuple2<
+ List<TypeParameter>,
+ Tuple3<List<VariableDeclaration>, List<VariableDeclaration>,
+ List<VariableDeclaration>>>,
+ Tuple2<DartType, Statement>>
+ tuple) {
+ return new FunctionNode(tuple.second.second,
+ typeParameters: tuple.first.first,
+ positionalParameters:
+ tuple.first.second.first + tuple.first.second.second,
+ namedParameters: tuple.first.second.third,
+ requiredParameterCount: tuple.first.second.first.length,
+ returnType: tuple.second.first,
+ asyncMarker: AsyncMarker.Sync);
+}
+
+TextSerializer<FunctionNode> asyncFunctionNodeSerializer = new Wrapped(
+ unwrapFunctionNode,
+ wrapAsyncFunctionNode,
+ new Bind(
+ new Rebind(
+ typeParametersSerializer,
+ new Tuple3Serializer(
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)),
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)),
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)))),
+ new Tuple2Serializer(dartTypeSerializer, statementSerializer)));
+
+FunctionNode wrapAsyncFunctionNode(
+ Tuple2<
+ Tuple2<
+ List<TypeParameter>,
+ Tuple3<List<VariableDeclaration>, List<VariableDeclaration>,
+ List<VariableDeclaration>>>,
+ Tuple2<DartType, Statement>>
+ tuple) {
+ return new FunctionNode(tuple.second.second,
+ typeParameters: tuple.first.first,
+ positionalParameters:
+ tuple.first.second.first + tuple.first.second.second,
+ namedParameters: tuple.first.second.third,
+ requiredParameterCount: tuple.first.second.first.length,
+ returnType: tuple.second.first,
+ asyncMarker: AsyncMarker.Async);
+}
+
+TextSerializer<FunctionNode> syncStarFunctionNodeSerializer = new Wrapped(
+ unwrapFunctionNode,
+ wrapSyncStarFunctionNode,
+ new Bind(
+ new Rebind(
+ typeParametersSerializer,
+ new Tuple3Serializer(
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)),
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)),
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)))),
+ new Tuple2Serializer(dartTypeSerializer, statementSerializer)));
+
+FunctionNode wrapSyncStarFunctionNode(
+ Tuple2<
+ Tuple2<
+ List<TypeParameter>,
+ Tuple3<List<VariableDeclaration>, List<VariableDeclaration>,
+ List<VariableDeclaration>>>,
+ Tuple2<DartType, Statement>>
+ tuple) {
+ return new FunctionNode(tuple.second.second,
+ typeParameters: tuple.first.first,
+ positionalParameters:
+ tuple.first.second.first + tuple.first.second.second,
+ namedParameters: tuple.first.second.third,
+ requiredParameterCount: tuple.first.second.first.length,
+ returnType: tuple.second.first,
+ asyncMarker: AsyncMarker.SyncStar);
+}
+
+TextSerializer<FunctionNode> asyncStarFunctionNodeSerializer = new Wrapped(
+ unwrapFunctionNode,
+ wrapAsyncStarFunctionNode,
+ new Bind(
+ new Rebind(
+ typeParametersSerializer,
+ new Tuple3Serializer(
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)),
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)),
+ new ListSerializer(new Binder(variableDeclarationSerializer,
+ getVariableDeclarationName, setVariableDeclarationName)))),
+ new Tuple2Serializer(dartTypeSerializer, statementSerializer)));
+
+FunctionNode wrapAsyncStarFunctionNode(
+ Tuple2<
+ Tuple2<
+ List<TypeParameter>,
+ Tuple3<List<VariableDeclaration>, List<VariableDeclaration>,
+ List<VariableDeclaration>>>,
+ Tuple2<DartType, Statement>>
+ tuple) {
+ return new FunctionNode(tuple.second.second,
+ typeParameters: tuple.first.first,
+ positionalParameters:
+ tuple.first.second.first + tuple.first.second.second,
+ namedParameters: tuple.first.second.third,
+ requiredParameterCount: tuple.first.second.first.length,
+ returnType: tuple.second.first,
+ asyncMarker: AsyncMarker.AsyncStar);
+}
+
+TextSerializer<FunctionNode> syncYieldingStarFunctionNodeSerializer =
+ new Wrapped(
+ unwrapFunctionNode,
+ wrapSyncYieldingFunctionNode,
+ new Bind(
+ new Rebind(
+ typeParametersSerializer,
+ new Tuple3Serializer(
+ new ListSerializer(new Binder(
+ variableDeclarationSerializer,
+ getVariableDeclarationName,
+ setVariableDeclarationName)),
+ new ListSerializer(new Binder(
+ variableDeclarationSerializer,
+ getVariableDeclarationName,
+ setVariableDeclarationName)),
+ new ListSerializer(new Binder(
+ variableDeclarationSerializer,
+ getVariableDeclarationName,
+ setVariableDeclarationName)))),
+ new Tuple2Serializer(dartTypeSerializer, statementSerializer)));
+
+FunctionNode wrapSyncYieldingFunctionNode(
+ Tuple2<
+ Tuple2<
+ List<TypeParameter>,
+ Tuple3<List<VariableDeclaration>, List<VariableDeclaration>,
+ List<VariableDeclaration>>>,
+ Tuple2<DartType, Statement>>
+ tuple) {
+ return new FunctionNode(tuple.second.second,
+ typeParameters: tuple.first.first,
+ positionalParameters:
+ tuple.first.second.first + tuple.first.second.second,
+ namedParameters: tuple.first.second.third,
+ requiredParameterCount: tuple.first.second.first.length,
+ returnType: tuple.second.first,
+ asyncMarker: AsyncMarker.SyncYielding);
+}
+
+Case<FunctionNode> functionNodeSerializer =
+ new Case.uninitialized(const FunctionNodeTagger());
+
void initializeSerializers() {
expressionSerializer.tags.addAll([
"string",
@@ -1036,6 +1272,7 @@
"invoke-direct-method",
"invoke-constructor",
"invoke-const-constructor",
+ "fun",
]);
expressionSerializer.serializers.addAll([
stringLiteralSerializer,
@@ -1081,6 +1318,7 @@
directMethodInvocationSerializer,
constructorInvocationSerializer,
constConstructorInvocationSerializer,
+ functionExpressionSerializer,
]);
dartTypeSerializer.tags.addAll([
"invalid",
@@ -1100,8 +1338,24 @@
]);
statementSerializer.tags.addAll([
"expr",
+ "ret",
]);
statementSerializer.serializers.addAll([
expressionStatementSerializer,
+ returnStatementSerializer,
+ ]);
+ functionNodeSerializer.tags.addAll([
+ "sync",
+ "async",
+ "sync-star",
+ "async-star",
+ "sync-yielding",
+ ]);
+ functionNodeSerializer.serializers.addAll([
+ syncFunctionNodeSerializer,
+ asyncFunctionNodeSerializer,
+ syncStarFunctionNodeSerializer,
+ asyncStarFunctionNodeSerializer,
+ syncYieldingStarFunctionNodeSerializer,
]);
}
diff --git a/pkg/kernel/lib/transformations/async.dart b/pkg/kernel/lib/transformations/async.dart
index caa4ffd..ee85e03 100644
--- a/pkg/kernel/lib/transformations/async.dart
+++ b/pkg/kernel/lib/transformations/async.dart
@@ -5,6 +5,7 @@
library kernel.transformations.async;
import '../kernel.dart';
+import '../type_environment.dart';
import 'continuation.dart';
/// A transformer that introduces temporary variables for all subexpressions
@@ -80,6 +81,9 @@
ExpressionLifter(this.continuationRewriter);
+ StaticTypeContext get _staticTypeContext =>
+ continuationRewriter.staticTypeContext;
+
Block blockOf(List<Statement> statements) {
return new Block(statements.reversed.toList());
}
@@ -115,14 +119,16 @@
// Name an expression by emitting an assignment to a temporary variable.
VariableGet name(Expression expr) {
- VariableDeclaration temp = allocateTemporary(nameIndex);
+ VariableDeclaration temp =
+ allocateTemporary(nameIndex, expr.getStaticType(_staticTypeContext));
statements.add(new ExpressionStatement(new VariableSet(temp, expr)));
return new VariableGet(temp);
}
- VariableDeclaration allocateTemporary(int index) {
+ VariableDeclaration allocateTemporary(int index, DartType type) {
for (var i = variables.length; i <= index; i++) {
- variables.add(new VariableDeclaration(":async_temporary_${i}"));
+ variables
+ .add(new VariableDeclaration(":async_temporary_${i}", type: type));
}
return variables[index];
}
@@ -332,7 +338,10 @@
// so any statements it emits occur after in the accumulated list (that is,
// so they occur before in the corresponding block).
var rightBody = blockOf(rightStatements);
- var result = allocateTemporary(nameIndex);
+ var result = allocateTemporary(
+ nameIndex,
+ _staticTypeContext.typeEnvironment.coreTypes
+ .boolRawType(_staticTypeContext.nonNullable));
rightBody.addStatement(new ExpressionStatement(new VariableSet(
result,
new MethodInvocation(expr.right, new Name('=='),
@@ -394,7 +403,7 @@
// } else {
// t = [right];
// }
- var result = allocateTemporary(nameIndex);
+ var result = allocateTemporary(nameIndex, expr.staticType);
var thenBody = blockOf(thenStatements);
var otherwiseBody = blockOf(otherwiseStatements);
thenBody.addStatement(
@@ -416,7 +425,20 @@
TreeNode visitAwaitExpression(AwaitExpression expr) {
final R = continuationRewriter;
var shouldName = seenAwait;
- var result = new VariableGet(asyncResult);
+ var type = expr.getStaticType(_staticTypeContext);
+ Expression result = new VariableGet(asyncResult);
+ if (type is! DynamicType) {
+ int fileOffset = expr.operand.fileOffset;
+ if (fileOffset == TreeNode.noOffset) {
+ fileOffset = expr.fileOffset;
+ }
+ assert(fileOffset != TreeNode.noOffset);
+ result = new StaticInvocation(
+ continuationRewriter.helper.unsafeCast,
+ new Arguments(<Expression>[result], types: <DartType>[type])
+ ..fileOffset = fileOffset)
+ ..fileOffset = fileOffset;
+ }
// The statements are in reverse order, so name the result first if
// necessary and then add the two other statements in reverse.
@@ -504,8 +526,8 @@
}
visitFunctionNode(FunctionNode node) {
- var nestedRewriter =
- new RecursiveContinuationRewriter(continuationRewriter.helper);
+ var nestedRewriter = new RecursiveContinuationRewriter(
+ continuationRewriter.helper, _staticTypeContext);
return node.accept(nestedRewriter);
}
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index d77ba82..71bba56 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -8,6 +8,7 @@
import '../ast.dart';
import '../core_types.dart';
+import '../type_environment.dart';
import '../visitor.dart';
import 'async.dart';
@@ -25,26 +26,35 @@
static String stackTraceVar(int depth) => ':stack_trace$depth';
}
-void transformLibraries(CoreTypes coreTypes, List<Library> libraries,
+void transformLibraries(
+ TypeEnvironment typeEnvironment, List<Library> libraries,
{bool productMode}) {
- var helper = new HelperNodes.fromCoreTypes(coreTypes, productMode);
- var rewriter = new RecursiveContinuationRewriter(helper);
+ var helper =
+ new HelperNodes.fromCoreTypes(typeEnvironment.coreTypes, productMode);
+ var rewriter = new RecursiveContinuationRewriter(
+ helper, new StatefulStaticTypeContext.stacked(typeEnvironment));
for (var library in libraries) {
rewriter.rewriteLibrary(library);
}
}
-Component transformComponent(CoreTypes coreTypes, Component component,
+Component transformComponent(
+ TypeEnvironment typeEnvironment, Component component,
{bool productMode}) {
- var helper = new HelperNodes.fromCoreTypes(coreTypes, productMode);
- var rewriter = new RecursiveContinuationRewriter(helper);
+ var helper =
+ new HelperNodes.fromCoreTypes(typeEnvironment.coreTypes, productMode);
+ var rewriter = new RecursiveContinuationRewriter(
+ helper, new StatefulStaticTypeContext.stacked(typeEnvironment));
return rewriter.rewriteComponent(component);
}
-Procedure transformProcedure(CoreTypes coreTypes, Procedure procedure,
+Procedure transformProcedure(
+ TypeEnvironment typeEnvironment, Procedure procedure,
{bool productMode}) {
- var helper = new HelperNodes.fromCoreTypes(coreTypes, productMode);
- var rewriter = new RecursiveContinuationRewriter(helper);
+ var helper =
+ new HelperNodes.fromCoreTypes(typeEnvironment.coreTypes, productMode);
+ var rewriter = new RecursiveContinuationRewriter(
+ helper, new StatefulStaticTypeContext.stacked(typeEnvironment));
return rewriter.visitProcedure(procedure);
}
@@ -57,7 +67,9 @@
final VariableDeclaration asyncContextVariable =
new VariableDeclaration(ContinuationVariables.awaitContextVar);
- RecursiveContinuationRewriter(this.helper);
+ StatefulStaticTypeContext staticTypeContext;
+
+ RecursiveContinuationRewriter(this.helper, this.staticTypeContext);
Component rewriteComponent(Component node) {
return node.accept<TreeNode>(this);
@@ -67,22 +79,53 @@
return node.accept<TreeNode>(this);
}
- visitProcedure(Procedure node) {
- return node.isAbstract ? node : super.visitProcedure(node);
+ visitField(Field node) {
+ staticTypeContext.enterMember(node);
+ final result = super.visitField(node);
+ staticTypeContext.leaveMember(node);
+ return result;
}
+ visitConstructor(Constructor node) {
+ staticTypeContext.enterMember(node);
+ final result = super.visitConstructor(node);
+ staticTypeContext.leaveMember(node);
+ return result;
+ }
+
+ @override
+ visitProcedure(Procedure node) {
+ staticTypeContext.enterMember(node);
+ final result = node.isAbstract ? node : super.visitProcedure(node);
+ staticTypeContext.leaveMember(node);
+ return result;
+ }
+
+ @override
+ visitLibrary(Library node) {
+ staticTypeContext.enterLibrary(node);
+ Library result = super.visitLibrary(node);
+ staticTypeContext.leaveLibrary(node);
+ return result;
+ }
+
+ @override
visitFunctionNode(FunctionNode node) {
switch (node.asyncMarker) {
case AsyncMarker.Sync:
case AsyncMarker.SyncYielding:
- node.transformChildren(new RecursiveContinuationRewriter(helper));
+ node.transformChildren(
+ new RecursiveContinuationRewriter(helper, staticTypeContext));
return node;
case AsyncMarker.SyncStar:
- return new SyncStarFunctionRewriter(helper, node).rewrite();
+ return new SyncStarFunctionRewriter(helper, node, staticTypeContext)
+ .rewrite();
case AsyncMarker.Async:
- return new AsyncFunctionRewriter(helper, node).rewrite();
+ return new AsyncFunctionRewriter(helper, node, staticTypeContext)
+ .rewrite();
case AsyncMarker.AsyncStar:
- return new AsyncStarFunctionRewriter(helper, node).rewrite();
+ return new AsyncStarFunctionRewriter(helper, node, staticTypeContext)
+ .rewrite();
default:
return null;
}
@@ -97,8 +140,9 @@
int capturedTryDepth = 0; // Deepest yield point within a try-block.
int capturedCatchDepth = 0; // Deepest yield point within a catch-block.
- ContinuationRewriterBase(HelperNodes helper, this.enclosingFunction)
- : super(helper);
+ ContinuationRewriterBase(HelperNodes helper, this.enclosingFunction,
+ StatefulStaticTypeContext staticTypeContext)
+ : super(helper, staticTypeContext);
/// Given a container [type], which is an instantiation of the given
/// [containerClass] extract its element type.
@@ -175,23 +219,27 @@
new VariableDeclaration(ContinuationVariables.stackTraceVar(depth)),
]);
- List<VariableDeclaration> variableDeclarations() =>
- [asyncJumpVariable, asyncContextVariable]
- ..addAll(createCapturedTryVariables())
- ..addAll(createCapturedCatchVariables());
+ List<VariableDeclaration> variableDeclarations() {
+ asyncJumpVariable.type = staticTypeContext.typeEnvironment.coreTypes
+ .intRawType(staticTypeContext.nonNullable);
+ return [asyncJumpVariable, asyncContextVariable]
+ ..addAll(createCapturedTryVariables())
+ ..addAll(createCapturedCatchVariables());
+ }
}
class SyncStarFunctionRewriter extends ContinuationRewriterBase {
final VariableDeclaration iteratorVariable;
- SyncStarFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction)
+ SyncStarFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
+ StatefulStaticTypeContext staticTypeContext)
: iteratorVariable = new VariableDeclaration(':iterator')
- ..type =
- new InterfaceType(helper.syncIteratorClass, Nullability.legacy, [
+ ..type = new InterfaceType(
+ helper.syncIteratorClass, staticTypeContext.nullable, [
ContinuationRewriterBase.elementTypeFrom(
helper.iterableClass, enclosingFunction.returnType)
]),
- super(helper, enclosingFunction);
+ super(helper, enclosingFunction, staticTypeContext);
FunctionNode rewrite() {
// :sync_op(:iterator) {
@@ -286,8 +334,9 @@
ExpressionLifter expressionRewriter;
- AsyncRewriterBase(HelperNodes helper, FunctionNode enclosingFunction)
- : super(helper, enclosingFunction) {}
+ AsyncRewriterBase(HelperNodes helper, FunctionNode enclosingFunction,
+ StaticTypeContext staticTypeContext)
+ : super(helper, enclosingFunction, staticTypeContext) {}
void setupAsyncContinuations(List<Statement> statements) {
expressionRewriter = new ExpressionLifter(this);
@@ -751,7 +800,7 @@
new Arguments(<Expression>[new VariableGet(streamVariable)],
types: [valueVariable.type])),
type: new InterfaceType(helper.streamIteratorClass,
- Nullability.legacy, [valueVariable.type]));
+ staticTypeContext.nullable, [valueVariable.type]));
// await :for-iterator.moveNext()
var condition = new AwaitExpression(new MethodInvocation(
@@ -905,8 +954,9 @@
class AsyncStarFunctionRewriter extends AsyncRewriterBase {
VariableDeclaration controllerVariable;
- AsyncStarFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction)
- : super(helper, enclosingFunction);
+ AsyncStarFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
+ StaticTypeContext staticTypeContext)
+ : super(helper, enclosingFunction, staticTypeContext);
FunctionNode rewrite() {
var statements = <Statement>[];
@@ -916,7 +966,7 @@
// _AsyncStarStreamController<T> :controller;
controllerVariable = new VariableDeclaration(":controller",
type: new InterfaceType(helper.asyncStarStreamControllerClass,
- Nullability.legacy, [elementType]));
+ staticTypeContext.nullable, [elementType]));
statements.add(controllerVariable);
// dynamic :controller_stream;
@@ -1022,8 +1072,9 @@
VariableDeclaration completerVariable;
VariableDeclaration returnVariable;
- AsyncFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction)
- : super(helper, enclosingFunction);
+ AsyncFunctionRewriter(HelperNodes helper, FunctionNode enclosingFunction,
+ StaticTypeContext staticTypeContext)
+ : super(helper, enclosingFunction, staticTypeContext);
FunctionNode rewrite() {
var statements = <Statement>[];
@@ -1037,12 +1088,12 @@
if (valueType == const DynamicType()) {
valueType = elementTypeFromReturnType(helper.futureOrClass);
}
- final DartType returnType = new InterfaceType(
- helper.futureOrClass, Nullability.legacy, <DartType>[valueType]);
+ final DartType returnType = new InterfaceType(helper.futureOrClass,
+ staticTypeContext.nullable, <DartType>[valueType]);
var completerTypeArguments = <DartType>[valueType];
final completerType = new InterfaceType(helper.asyncAwaitCompleterClass,
- Nullability.legacy, completerTypeArguments);
+ staticTypeContext.nonNullable, completerTypeArguments);
// final Completer<T> :async_completer = new _AsyncAwaitCompleter<T>();
completerVariable = new VariableDeclaration(":async_completer",
initializer: new ConstructorInvocation(
@@ -1150,6 +1201,7 @@
final Member syncIteratorCurrent;
final Member syncIteratorYieldEachIterable;
final Class boolClass;
+ final Procedure unsafeCast;
bool productMode;
@@ -1189,7 +1241,8 @@
this.syncIteratorCurrent,
this.syncIteratorYieldEachIterable,
this.boolClass,
- this.productMode);
+ this.productMode,
+ this.unsafeCast);
factory HelperNodes.fromCoreTypes(CoreTypes coreTypes, bool productMode) {
return new HelperNodes._(
@@ -1228,6 +1281,7 @@
coreTypes.syncIteratorCurrent,
coreTypes.syncIteratorYieldEachIterable,
coreTypes.boolClass,
- productMode);
+ productMode,
+ coreTypes.index.getTopLevelMember('dart:_internal', 'unsafeCast'));
}
}
diff --git a/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart b/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
index c2289a5..46c0f61 100644
--- a/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
+++ b/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
@@ -129,6 +129,12 @@
WidgetCreatorTracker _tracker;
+ /// Library that contains the transformed call sites.
+ ///
+ /// The transformation of the call sites is affected by the NNBD opt-in status
+ /// of the library.
+ Library _currentLibrary;
+
_WidgetCallSiteTransformer(
{@required Class widgetClass,
@required Class locationClass,
@@ -271,11 +277,26 @@
location,
parameterLocations: new ListLiteral(
parameterLocations,
- typeArgument: _locationClass.thisType,
+ typeArgument:
+ new InterfaceType(_locationClass, _currentLibrary.nonNullable),
isConst: true,
),
);
}
+
+ void enterLibrary(Library library) {
+ assert(
+ _currentLibrary == null,
+ "Attempting to enter library '${library.fileUri}' "
+ "without having exited library '${_currentLibrary.fileUri}'.");
+ _currentLibrary = library;
+ }
+
+ void exitLibrary() {
+ assert(_currentLibrary != null,
+ "Attempting to exit a library without having entered one.");
+ _currentLibrary = null;
+ }
}
/// Rewrites all widget constructors and constructor invocations to add a
@@ -345,7 +366,8 @@
_hasCreationLocationClass.enclosingLibrary,
);
final Field locationField = new Field(fieldName,
- type: new InterfaceType(_locationClass, Nullability.legacy),
+ type: new InterfaceType(
+ _locationClass, clazz.enclosingLibrary.nonNullable),
isFinal: true,
reference: clazz.reference.canonicalName
?.getChildFromFieldWithName(fieldName)
@@ -365,7 +387,8 @@
));
final VariableDeclaration variable = new VariableDeclaration(
_creationLocationParameterName,
- type: _locationClass.thisType,
+ type: new InterfaceType(
+ _locationClass, clazz.enclosingLibrary.nonNullable),
);
if (!_maybeAddNamedParameter(constructor.function, variable)) {
return;
@@ -458,7 +481,9 @@
if (library.isExternal) {
continue;
}
+ callsiteTransformer.enterLibrary(library);
library.transformChildren(callsiteTransformer);
+ callsiteTransformer.exitLibrary();
}
}
@@ -497,10 +522,10 @@
if (procedure.isFactory) {
_maybeAddNamedParameter(
procedure.function,
- new VariableDeclaration(
- _creationLocationParameterName,
- type: _locationClass.thisType,
- ),
+ new VariableDeclaration(_creationLocationParameterName,
+ type: new InterfaceType(
+ _locationClass, clazz.enclosingLibrary.nonNullable),
+ isRequired: clazz.enclosingLibrary.isNonNullableByDefault),
);
}
}
@@ -521,9 +546,10 @@
}
final VariableDeclaration variable = new VariableDeclaration(
- _creationLocationParameterName,
- type: _locationClass.thisType,
- );
+ _creationLocationParameterName,
+ type: new InterfaceType(
+ _locationClass, clazz.enclosingLibrary.nonNullable),
+ isRequired: clazz.enclosingLibrary.isNonNullableByDefault);
if (_hasNamedParameter(
constructor.function, _creationLocationParameterName)) {
// Constructor was already rewritten. TODO(jacobr): is this case actually hit?
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index e7b810b..87ac4a0 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -114,8 +114,8 @@
growable: true);
var map = <TypeParameter, DartType>{};
for (int i = 0; i < typeParameters.length; ++i) {
- map[typeParameters[i]] =
- new TypeParameterType(freshParameters[i], Nullability.legacy);
+ map[typeParameters[i]] = new TypeParameterType.forAlphaRenaming(
+ typeParameters[i], freshParameters[i]);
}
CloneVisitor cloner;
for (int i = 0; i < typeParameters.length; ++i) {
@@ -293,7 +293,7 @@
const _NullSubstitution();
DartType getSubstitute(TypeParameter parameter, bool upperBound) {
- return new TypeParameterType(parameter, Nullability.legacy);
+ return new TypeParameterType.forAlphaRenaming(parameter, parameter);
}
@override
@@ -388,7 +388,7 @@
TypeParameter freshTypeParameter(TypeParameter node) {
var fresh = new TypeParameter(node.name);
- substitution[node] = new TypeParameterType(fresh, Nullability.legacy);
+ substitution[node] = new TypeParameterType.forAlphaRenaming(node, fresh);
fresh.bound = visit(node.bound);
if (node.defaultType != null) {
fresh.defaultType = visit(node.defaultType);
@@ -719,8 +719,8 @@
var rightInstance = <TypeParameter, DartType>{};
for (int i = 0; i < type1.typeParameters.length; ++i) {
var instantiator = new TypeParameter(type1.typeParameters[i].name);
- var instantiatorType =
- new TypeParameterType(instantiator, Nullability.legacy);
+ var instantiatorType = new TypeParameterType.forAlphaRenaming(
+ type1.typeParameters[i], instantiator);
leftInstance[type1.typeParameters[i]] = instantiatorType;
rightInstance[type2.typeParameters[i]] = instantiatorType;
_universallyQuantifiedVariables.add(instantiator);
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 53eec114..ba3e192 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -18,6 +18,8 @@
final ClassHierarchy hierarchy;
final bool ignoreSdk;
TypeEnvironment environment;
+ Library currentLibrary;
+ InterfaceType currentThisType;
TypeChecker(this.coreTypes, this.hierarchy, {this.ignoreSdk: true})
: environment = new TypeEnvironment(coreTypes, hierarchy);
@@ -34,9 +36,11 @@
}
var visitor = new TypeCheckingVisitor(this, environment, hierarchy);
for (var library in component.libraries) {
+ currentLibrary = library;
if (ignoreSdk && library.importUri.scheme == 'dart') continue;
for (var class_ in library.classes) {
- environment.thisType = class_.thisType;
+ currentThisType = coreTypes.thisInterfaceType(
+ class_, class_.enclosingLibrary.nonNullable);
for (var field in class_.fields) {
visitor.visitField(field);
}
@@ -47,13 +51,14 @@
visitor.visitProcedure(procedure);
}
}
- environment.thisType = null;
+ currentThisType = null;
for (var procedure in library.procedures) {
visitor.visitProcedure(procedure);
}
for (var field in library.fields) {
visitor.visitField(field);
}
+ currentLibrary = null;
}
}
@@ -117,7 +122,13 @@
final ClassHierarchy hierarchy;
CoreTypes get coreTypes => environment.coreTypes;
- Class get currentClass => environment.thisType.classNode;
+ Library get currentLibrary => checker.currentLibrary;
+ Class get currentClass => checker.currentThisType.classNode;
+ InterfaceType get currentThisType => checker.currentThisType;
+
+ DartType currentReturnType;
+ DartType currentYieldType;
+ AsyncMarker currentAsyncMarker = AsyncMarker.Sync;
TypeCheckingVisitor(this.checker, this.environment, this.hierarchy);
@@ -181,26 +192,26 @@
}
visitConstructor(Constructor node) {
- environment.returnType = null;
- environment.yieldType = null;
+ currentReturnType = null;
+ currentYieldType = null;
node.initializers.forEach(visitInitializer);
handleFunctionNode(node.function);
}
visitProcedure(Procedure node) {
- environment.returnType = _getInternalReturnType(node.function);
- environment.yieldType = _getYieldType(node.function);
+ currentReturnType = _getInternalReturnType(node.function);
+ currentYieldType = _getYieldType(node.function);
handleFunctionNode(node.function);
}
visitRedirectingFactoryConstructor(RedirectingFactoryConstructor node) {
- environment.returnType = null;
- environment.yieldType = null;
+ currentReturnType = null;
+ currentYieldType = null;
}
void handleFunctionNode(FunctionNode node) {
- var oldAsyncMarker = environment.currentAsyncMarker;
- environment.currentAsyncMarker = node.asyncMarker;
+ var oldAsyncMarker = currentAsyncMarker;
+ currentAsyncMarker = node.asyncMarker;
node.positionalParameters
.skip(node.requiredParameterCount)
.forEach(handleOptionalParameter);
@@ -208,17 +219,17 @@
if (node.body != null) {
visitStatement(node.body);
}
- environment.currentAsyncMarker = oldAsyncMarker;
+ currentAsyncMarker = oldAsyncMarker;
}
void handleNestedFunctionNode(FunctionNode node) {
- var oldReturn = environment.returnType;
- var oldYield = environment.yieldType;
- environment.returnType = _getInternalReturnType(node);
- environment.yieldType = _getYieldType(node);
+ var oldReturn = currentReturnType;
+ var oldYield = currentYieldType;
+ currentReturnType = _getInternalReturnType(node);
+ currentYieldType = _getYieldType(node);
handleFunctionNode(node);
- environment.returnType = oldReturn;
- environment.yieldType = oldYield;
+ currentReturnType = oldReturn;
+ currentYieldType = oldYield;
}
void handleOptionalParameter(VariableDeclaration parameter) {
@@ -427,7 +438,7 @@
handleCall(arguments, target.function.thisFunctionType,
typeParameters: class_.typeParameters);
return new InterfaceType(
- target.enclosingClass, Nullability.legacy, arguments.types);
+ target.enclosingClass, currentLibrary.nonNullable, arguments.types);
}
@override
@@ -516,7 +527,8 @@
node.expressions[i] =
checkAndDowncastExpression(node.expressions[i], node.typeArgument);
}
- return environment.literalListType(node.typeArgument);
+ return environment.literalListType(
+ node.typeArgument, currentLibrary.nonNullable);
}
@override
@@ -525,7 +537,8 @@
node.expressions[i] =
checkAndDowncastExpression(node.expressions[i], node.typeArgument);
}
- return environment.literalSetType(node.typeArgument);
+ return environment.literalSetType(
+ node.typeArgument, currentLibrary.nonNullable);
}
@override
@@ -543,7 +556,8 @@
entry.key = checkAndDowncastExpression(entry.key, node.keyType);
entry.value = checkAndDowncastExpression(entry.value, node.valueType);
}
- return environment.literalMapType(node.keyType, node.valueType);
+ return environment.literalMapType(
+ node.keyType, node.valueType, currentLibrary.nonNullable);
}
DartType handleDynamicCall(DartType receiver, Arguments arguments) {
@@ -693,7 +707,8 @@
@override
DartType visitListConcatenation(ListConcatenation node) {
- DartType type = environment.literalListType(node.typeArgument);
+ DartType type = environment.literalListType(
+ node.typeArgument, currentLibrary.nonNullable);
for (Expression part in node.lists) {
DartType partType = visitExpression(part);
checkAssignable(node, type, partType);
@@ -703,7 +718,8 @@
@override
DartType visitSetConcatenation(SetConcatenation node) {
- DartType type = environment.literalSetType(node.typeArgument);
+ DartType type = environment.literalSetType(
+ node.typeArgument, currentLibrary.nonNullable);
for (Expression part in node.sets) {
DartType partType = visitExpression(part);
checkAssignable(node, type, partType);
@@ -713,7 +729,8 @@
@override
DartType visitMapConcatenation(MapConcatenation node) {
- DartType type = environment.literalMapType(node.keyType, node.valueType);
+ DartType type = environment.literalMapType(
+ node.keyType, node.valueType, currentLibrary.nonNullable);
for (Expression part in node.maps) {
DartType partType = visitExpression(part);
checkAssignable(node, type, partType);
@@ -731,7 +748,7 @@
checkAssignable(node, fieldType, valueType);
});
return new InterfaceType(
- node.classNode, Nullability.legacy, node.typeArguments);
+ node.classNode, currentLibrary.nonNullable, node.typeArguments);
}
@override
@@ -747,8 +764,8 @@
@override
DartType visitSuperMethodInvocation(SuperMethodInvocation node) {
if (node.interfaceTarget == null) {
- checkUnresolvedInvocation(environment.thisType, node);
- return handleDynamicCall(environment.thisType, node.arguments);
+ checkUnresolvedInvocation(currentThisType, node);
+ return handleDynamicCall(currentThisType, node.arguments);
} else {
return handleCall(node.arguments, node.interfaceTarget.getterType,
receiver: getSuperReceiverType(node.interfaceTarget));
@@ -758,7 +775,7 @@
@override
DartType visitSuperPropertyGet(SuperPropertyGet node) {
if (node.interfaceTarget == null) {
- checkUnresolvedInvocation(environment.thisType, node);
+ checkUnresolvedInvocation(currentThisType, node);
return const DynamicType();
} else {
var receiver = getSuperReceiverType(node.interfaceTarget);
@@ -777,7 +794,7 @@
receiver.substituteType(node.interfaceTarget.setterType,
contravariant: true));
} else {
- checkUnresolvedInvocation(environment.thisType, node);
+ checkUnresolvedInvocation(currentThisType, node);
}
return value;
}
@@ -789,7 +806,7 @@
@override
DartType visitThisExpression(ThisExpression node) {
- return environment.thisType;
+ return currentThisType;
}
@override
@@ -817,7 +834,8 @@
@override
DartType visitLoadLibrary(LoadLibrary node) {
- return environment.futureType(const DynamicType(), Nullability.legacy);
+ return environment.futureType(
+ const DynamicType(), currentLibrary.nonNullable);
}
@override
@@ -952,14 +970,14 @@
@override
visitReturnStatement(ReturnStatement node) {
if (node.expression != null) {
- if (environment.returnType == null) {
+ if (currentReturnType == null) {
fail(node, 'Return of a value from void method');
} else {
var type = visitExpression(node.expression);
- if (environment.currentAsyncMarker == AsyncMarker.Async) {
+ if (currentAsyncMarker == AsyncMarker.Async) {
type = environment.unfutureType(type);
}
- checkAssignable(node.expression, type, environment.returnType);
+ checkAssignable(node.expression, type, currentReturnType);
}
}
}
@@ -1005,7 +1023,7 @@
@override
visitYieldStatement(YieldStatement node) {
if (node.isYieldStar) {
- Class container = environment.currentAsyncMarker == AsyncMarker.AsyncStar
+ Class container = currentAsyncMarker == AsyncMarker.AsyncStar
? coreTypes.streamClass
: coreTypes.iterableClass;
var type = visitExpression(node.expression);
@@ -1013,14 +1031,14 @@
? hierarchy.getTypeAsInstanceOf(type, container)
: null;
if (asContainer != null) {
- checkAssignable(node.expression, asContainer.typeArguments[0],
- environment.yieldType);
+ checkAssignable(
+ node.expression, asContainer.typeArguments[0], currentYieldType);
} else {
fail(node.expression, '$type is not an instance of $container');
}
} else {
node.expression =
- checkAndDowncastExpression(node.expression, environment.yieldType);
+ checkAndDowncastExpression(node.expression, currentYieldType);
}
}
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index 028df5e..dabc13c 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -17,12 +17,6 @@
abstract class TypeEnvironment extends SubtypeTester {
final CoreTypes coreTypes;
- InterfaceType thisType;
-
- DartType returnType;
- DartType yieldType;
- AsyncMarker currentAsyncMarker = AsyncMarker.Sync;
-
/// An error handler for use in debugging, or `null` if type errors should not
/// be tolerated. See [typeError].
ErrorHandler errorHandler;
@@ -44,33 +38,33 @@
InterfaceType get nullType => coreTypes.nullType;
InterfaceType get functionLegacyRawType => coreTypes.functionLegacyRawType;
- InterfaceType literalListType(DartType elementType) {
+ InterfaceType literalListType(DartType elementType, Nullability nullability) {
return new InterfaceType(
- coreTypes.listClass, Nullability.legacy, <DartType>[elementType]);
+ coreTypes.listClass, nullability, <DartType>[elementType]);
}
- InterfaceType literalSetType(DartType elementType) {
+ InterfaceType literalSetType(DartType elementType, Nullability nullability) {
return new InterfaceType(
- coreTypes.setClass, Nullability.legacy, <DartType>[elementType]);
+ coreTypes.setClass, nullability, <DartType>[elementType]);
}
- InterfaceType literalMapType(DartType key, DartType value) {
+ InterfaceType literalMapType(
+ DartType key, DartType value, Nullability nullability) {
return new InterfaceType(
- coreTypes.mapClass, Nullability.legacy, <DartType>[key, value]);
+ coreTypes.mapClass, nullability, <DartType>[key, value]);
}
- InterfaceType iterableType(DartType type) {
+ InterfaceType iterableType(DartType type, Nullability nullability) {
return new InterfaceType(
- coreTypes.iterableClass, Nullability.legacy, <DartType>[type]);
+ coreTypes.iterableClass, nullability, <DartType>[type]);
}
- InterfaceType streamType(DartType type) {
+ InterfaceType streamType(DartType type, Nullability nullability) {
return new InterfaceType(
- coreTypes.streamClass, Nullability.legacy, <DartType>[type]);
+ coreTypes.streamClass, nullability, <DartType>[type]);
}
- InterfaceType futureType(DartType type,
- [Nullability nullability = Nullability.legacy]) {
+ InterfaceType futureType(DartType type, Nullability nullability) {
return new InterfaceType(
coreTypes.futureClass, nullability, <DartType>[type]);
}
@@ -159,6 +153,17 @@
return coreTypes.numRawType(type1.nullability);
}
+
+ /// Returns the possibly abstract interface member of [class_] with the given
+ /// [name].
+ ///
+ /// If [setter] is `false`, only fields, methods, and getters with that name
+ /// will be found. If [setter] is `true`, only non-final fields and setters
+ /// will be found.
+ ///
+ /// If multiple members with that name are inherited and not overridden, the
+ /// member from the first declared supertype is returned.
+ Member getInterfaceMember(Class cls, Name name, {bool setter: false});
}
/// Tri-state logical result of a nullability-aware subtype check.
@@ -235,6 +240,16 @@
/// types `List<int>?` and `List<num>*`.
factory IsSubtypeOf.basedSolelyOnNullabilities(
DartType subtype, DartType supertype) {
+ if (subtype is InvalidType) {
+ if (supertype is InvalidType) {
+ return const IsSubtypeOf.always();
+ }
+ return const IsSubtypeOf.onlyIfIgnoringNullabilities();
+ }
+ if (supertype is InvalidType) {
+ return const IsSubtypeOf.onlyIfIgnoringNullabilities();
+ }
+
if (subtype.isPotentiallyNullable && supertype.isPotentiallyNonNullable) {
return const IsSubtypeOf.onlyIfIgnoringNullabilities();
}
@@ -332,8 +347,7 @@
Class get objectClass;
Class get functionClass;
Class get futureOrClass;
- InterfaceType futureType(DartType type,
- [Nullability nullability = Nullability.legacy]);
+ InterfaceType futureType(DartType type, Nullability nullability);
static List<Object> typeChecks;
@@ -560,8 +574,8 @@
for (int i = 0; i < subtype.typeParameters.length; ++i) {
var subParameter = subtype.typeParameters[i];
var superParameter = supertype.typeParameters[i];
- substitution[subParameter] =
- new TypeParameterType(superParameter, Nullability.legacy);
+ substitution[subParameter] = new TypeParameterType.forAlphaRenaming(
+ subParameter, superParameter);
}
for (int i = 0; i < subtype.typeParameters.length; ++i) {
var subParameter = subtype.typeParameters[i];
@@ -615,3 +629,266 @@
.and(new IsSubtypeOf.basedSolelyOnNullabilities(subtype, supertype));
}
}
+
+/// Context object needed for computing `Expression.getStaticType`.
+///
+/// The [StaticTypeContext] provides access to the [TypeEnvironment] and the
+/// current 'this type' as well as determining the nullability state of the
+/// enclosing library.
+// TODO(johnniwinther): Support static type caching through [StaticTypeContext].
+class StaticTypeContext {
+ /// The [TypeEnvironment] used for the static type computation.
+ ///
+ /// This provides access to the core types and the class hierarchy.
+ final TypeEnvironment typeEnvironment;
+
+ /// The library in which the static type is computed.
+ ///
+ /// The `library.isNonNullableByDefault` property is used to determine the
+ /// nullabilities of the static types.
+ final Library _library;
+
+ /// The static type of a `this` expression.
+ final InterfaceType thisType;
+
+ /// Creates a static type context for computing static types in the body
+ /// of [member].
+ StaticTypeContext(Member member, this.typeEnvironment)
+ : _library = member.enclosingLibrary,
+ thisType = member.enclosingClass?.getThisType(
+ typeEnvironment.coreTypes, member.enclosingLibrary.nonNullable);
+
+ /// Creates a static type context for computing static types of annotations
+ /// in [library].
+ StaticTypeContext.forAnnotations(this._library, this.typeEnvironment)
+ : thisType = null;
+
+ /// The [Nullability] used for non-nullable types.
+ ///
+ /// For opt out libraries this is [Nullability.legacy].
+ Nullability get nonNullable => _library.nonNullable;
+
+ /// The [Nullability] used for nullable types.
+ ///
+ /// For opt out libraries this is [Nullability.legacy].
+ Nullability get nullable => _library.nullable;
+}
+
+/// Implementation of [StaticTypeContext] that update its state when entering
+/// and leaving libraries and members.
+abstract class StatefulStaticTypeContext implements StaticTypeContext {
+ @override
+ final TypeEnvironment typeEnvironment;
+
+ /// Creates a [StatefulStaticTypeContext] that supports entering multiple
+ /// libraries and/or members successively.
+ factory StatefulStaticTypeContext.stacked(TypeEnvironment typeEnvironment) =
+ _StackedStatefulStaticTypeContext;
+
+ /// Creates a [StatefulStaticTypeContext] that only supports entering one
+ /// library and/or member at a time.
+ factory StatefulStaticTypeContext.flat(TypeEnvironment typeEnvironment) =
+ _FlatStatefulStaticTypeContext;
+
+ StatefulStaticTypeContext._internal(this.typeEnvironment);
+
+ /// Updates the [nonNullable] and [thisType] to match static type context for
+ /// the member [node].
+ ///
+ /// This should be called before computing static types on the body of member
+ /// [node].
+ void enterMember(Member node);
+
+ /// Reverts the [nonNullable] and [thisType] values to the previous state.
+ ///
+ /// This should be called after computing static types on the body of member
+ /// [node].
+ void leaveMember(Member node);
+
+ /// Updates the [nonNullable] and [thisType] to match static type context for
+ /// the library [node].
+ ///
+ /// This should be called before computing static types on annotations in the
+ /// library [node].
+ void enterLibrary(Library node);
+
+ /// Reverts the [nonNullable] and [thisType] values to the previous state.
+ ///
+ /// This should be called after computing static types on annotations in the
+ /// library [node].
+ void leaveLibrary(Library node);
+}
+
+/// Implementation of [StatefulStaticTypeContext] that only supports entering
+/// one library and/or at a time.
+class _FlatStatefulStaticTypeContext extends StatefulStaticTypeContext {
+ Library _currentLibrary;
+ Member _currentMember;
+
+ _FlatStatefulStaticTypeContext(TypeEnvironment typeEnvironment)
+ : super._internal(typeEnvironment);
+
+ @override
+ Library get _library {
+ Library library = _currentLibrary ?? _currentMember?.enclosingLibrary;
+ assert(library != null,
+ "No library currently associated with StaticTypeContext.");
+ return library;
+ }
+
+ @override
+ InterfaceType get thisType {
+ assert(_currentMember != null,
+ "No member currently associated with StaticTypeContext.");
+ return _currentMember?.enclosingClass?.getThisType(
+ typeEnvironment.coreTypes, _currentMember.enclosingLibrary.nonNullable);
+ }
+
+ @override
+ Nullability get nonNullable => _library?.nonNullable;
+
+ @override
+ Nullability get nullable => _library?.nullable;
+
+ /// Updates the [nonNullable] and [thisType] to match static type context for
+ /// the member [node].
+ ///
+ /// This should be called before computing static types on the body of member
+ /// [node].
+ ///
+ /// Only one member can be entered at a time.
+ @override
+ void enterMember(Member node) {
+ assert(_currentMember == null, "Already in context of $_currentMember");
+ _currentMember = node;
+ }
+
+ /// Reverts the [nonNullable] and [thisType] values to the previous state.
+ ///
+ /// This should be called after computing static types on the body of member
+ /// [node].
+ @override
+ void leaveMember(Member node) {
+ assert(
+ _currentMember == node,
+ "Inconsistent static type context stack: "
+ "Trying to leave $node but current is ${_currentMember}.");
+ _currentMember = null;
+ }
+
+ /// Updates the [nonNullable] and [thisType] to match static type context for
+ /// the library [node].
+ ///
+ /// This should be called before computing static types on annotations in the
+ /// library [node].
+ ///
+ /// Only one library can be entered at a time, and not while a member is
+ /// entered through [enterMember].
+ @override
+ void enterLibrary(Library node) {
+ assert(_currentLibrary == null, "Already in context of $_currentLibrary");
+ assert(_currentMember == null, "Already in context of $_currentMember");
+ _currentLibrary = node;
+ }
+
+ /// Reverts the [nonNullable] and [thisType] values to the previous state.
+ ///
+ /// This should be called after computing static types on annotations in the
+ /// library [node].
+ @override
+ void leaveLibrary(Library node) {
+ assert(
+ _currentLibrary == node,
+ "Inconsistent static type context stack: "
+ "Trying to leave $node but current is ${_currentLibrary}.");
+ _currentLibrary = null;
+ }
+}
+
+/// Implementation of [StatefulStaticTypeContext] that use a stack to change state
+/// when entering and leaving libraries and members.
+class _StackedStatefulStaticTypeContext extends StatefulStaticTypeContext {
+ final List<_StaticTypeContextState> _contextStack =
+ <_StaticTypeContextState>[];
+
+ _StackedStatefulStaticTypeContext(TypeEnvironment typeEnvironment)
+ : super._internal(typeEnvironment);
+
+ @override
+ Library get _library {
+ assert(_contextStack.isNotEmpty,
+ "No library currently associated with StaticTypeContext.");
+ return _contextStack.last._library;
+ }
+
+ @override
+ InterfaceType get thisType {
+ assert(_contextStack.isNotEmpty,
+ "No this type currently associated with StaticTypeContext.");
+ return _contextStack.last._thisType;
+ }
+
+ @override
+ Nullability get nonNullable => _library?.nonNullable;
+
+ @override
+ Nullability get nullable => _library?.nullable;
+
+ /// Updates the [library] and [thisType] to match static type context for
+ /// the member [node].
+ ///
+ /// This should be called before computing static types on the body of member
+ /// [node].
+ @override
+ void enterMember(Member node) {
+ _contextStack.add(new _StaticTypeContextState(
+ node,
+ node.enclosingLibrary,
+ node.enclosingClass?.getThisType(
+ typeEnvironment.coreTypes, node.enclosingLibrary.nonNullable)));
+ }
+
+ /// Reverts the [library] and [thisType] values to the previous state.
+ ///
+ /// This should be called after computing static types on the body of member
+ /// [node].
+ @override
+ void leaveMember(Member node) {
+ _StaticTypeContextState state = _contextStack.removeLast();
+ assert(
+ state._node == node,
+ "Inconsistent static type context stack: "
+ "Trying to leave $node but current is ${state._node}.");
+ }
+
+ /// Updates the [library] and [thisType] to match static type context for
+ /// the library [node].
+ ///
+ /// This should be called before computing static types on annotations in the
+ /// library [node].
+ @override
+ void enterLibrary(Library node) {
+ _contextStack.add(new _StaticTypeContextState(node, node, null));
+ }
+
+ /// Reverts the [library] and [thisType] values to the previous state.
+ ///
+ /// This should be called after computing static types on annotations in the
+ /// library [node].
+ @override
+ void leaveLibrary(Library node) {
+ _StaticTypeContextState state = _contextStack.removeLast();
+ assert(
+ state._node == node,
+ "Inconsistent static type context stack: "
+ "Trying to leave $node but current is ${state._node}.");
+ }
+}
+
+class _StaticTypeContextState {
+ final TreeNode _node;
+ final Library _library;
+ final InterfaceType _thisType;
+
+ _StaticTypeContextState(this._node, this._library, this._thisType);
+}
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index f47c3e7..c37656d 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -5,6 +5,7 @@
import 'ast.dart';
import 'transformations/flags.dart';
+import 'type_environment.dart' show StatefulStaticTypeContext, TypeEnvironment;
void verifyComponent(Component component, {bool isOutline, bool afterConst}) {
VerifyingVisitor.check(component,
@@ -764,6 +765,65 @@
}
}
+void verifyGetStaticType(TypeEnvironment env, Component component) {
+ component.accept(new VerifyGetStaticType(env));
+}
+
+class VerifyGetStaticType extends RecursiveVisitor {
+ final TypeEnvironment env;
+ Member currentMember;
+ final StatefulStaticTypeContext _staticTypeContext;
+
+ VerifyGetStaticType(this.env)
+ : _staticTypeContext = new StatefulStaticTypeContext.stacked(env);
+
+ @override
+ visitLibrary(Library node) {
+ _staticTypeContext.enterLibrary(node);
+ super.visitLibrary(node);
+ _staticTypeContext.leaveLibrary(node);
+ }
+
+ @override
+ visitField(Field node) {
+ currentMember = node;
+ _staticTypeContext.enterMember(node);
+ super.visitField(node);
+ _staticTypeContext.leaveMember(node);
+ currentMember = node;
+ }
+
+ @override
+ visitProcedure(Procedure node) {
+ currentMember = node;
+ _staticTypeContext.enterMember(node);
+ super.visitProcedure(node);
+ _staticTypeContext.leaveMember(node);
+ currentMember = node;
+ }
+
+ @override
+ visitConstructor(Constructor node) {
+ currentMember = node;
+ _staticTypeContext.enterMember(node);
+ super.visitConstructor(node);
+ _staticTypeContext.leaveMember(node);
+ currentMember = null;
+ }
+
+ @override
+ defaultExpression(Expression node) {
+ try {
+ node.getStaticType(_staticTypeContext);
+ } catch (_) {
+ print('Error in $currentMember in ${currentMember?.fileUri}: '
+ '$node (${node.runtimeType})');
+ rethrow;
+ }
+ super.defaultExpression(node);
+ }
+}
+
class CheckParentPointers extends Visitor {
static void check(TreeNode node) {
node.accept(new CheckParentPointers(node.parent));
diff --git a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
index ad2354e..7eb39c7 100644
--- a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
+++ b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
@@ -59,9 +59,9 @@
type: const DynamicType(), initializer: new IntLiteral(42));
return new ExpressionStatement(new Let(x, new VariableGet(x)));
}(),
- expectation: ""
- "(expr (let (var \"x^0\" (dynamic) (int 42) ())"
- " (get-var \"x^0\" _)))"),
+ expectation: ''
+ '(expr (let (var "x^0" (dynamic) (int 42) ())'
+ ' (get-var "x^0" _)))'),
new TestCase(
name: "let dynamic x = 42 in let Bottom x^0 = null in x;",
node: () {
@@ -72,10 +72,10 @@
return new ExpressionStatement(new Let(outterLetVar,
new Let(innerLetVar, new VariableGet(outterLetVar))));
}(),
- expectation: ""
- "(expr (let (var \"x^0\" (dynamic) (int 42) ())"
- " (let (var \"x^1\" (bottom) (null) ())"
- " (get-var \"x^0\" _))))"),
+ expectation: ''
+ '(expr (let (var "x^0" (dynamic) (int 42) ())'
+ ' (let (var "x^1" (bottom) (null) ())'
+ ' (get-var "x^0" _))))'),
new TestCase(
name: "let dynamic x = 42 in let Bottom x^0 = null in x^0;",
node: () {
@@ -86,17 +86,17 @@
return new ExpressionStatement(new Let(outterLetVar,
new Let(innerLetVar, new VariableGet(innerLetVar))));
}(),
- expectation: ""
- "(expr (let (var \"x^0\" (dynamic) (int 42) ())"
- " (let (var \"x^1\" (bottom) (null) ())"
- " (get-var \"x^1\" _))))"),
+ expectation: ''
+ '(expr (let (var "x^0" (dynamic) (int 42) ())'
+ ' (let (var "x^1" (bottom) (null) ())'
+ ' (get-var "x^1" _))))'),
() {
VariableDeclaration x =
new VariableDeclaration("x", type: const DynamicType());
return new TestCase(
name: "/* suppose: dynamic x; */ x = 42;",
node: new ExpressionStatement(new VariableSet(x, new IntLiteral(42))),
- expectation: "(expr (set-var \"x^0\" (int 42)))",
+ expectation: '(expr (set-var "x^0" (int 42)))',
serializationState: new SerializationState(
new SerializationEnvironment(null)
..addBinder(x, "x^0")
@@ -118,8 +118,8 @@
return new TestCase(
name: "/* suppose top-level: dynamic field; */ field;",
node: new ExpressionStatement(new StaticGet(field)),
- expectation: ""
- "(expr (get-static \"package:foo/bar.dart::@fields::field\"))",
+ expectation: ''
+ '(expr (get-static "package:foo/bar.dart::@fields::field"))',
serializationState: new SerializationState(null),
deserializationState: new DeserializationState(null, component.root));
}(),
@@ -134,9 +134,9 @@
name: "/* suppose top-level: dynamic field; */ field = 1;",
node:
new ExpressionStatement(new StaticSet(field, new IntLiteral(1))),
- expectation: ""
- "(expr"
- " (set-static \"package:foo/bar.dart::@fields::field\" (int 1)))",
+ expectation: ''
+ '(expr'
+ ' (set-static "package:foo/bar.dart::@fields::field" (int 1)))',
serializationState: new SerializationState(null),
deserializationState: new DeserializationState(null, component.root));
}(),
@@ -159,9 +159,9 @@
topLevelProcedure.reference,
new Arguments(<Expression>[new IntLiteral(42)]),
isConst: false)),
- expectation: ""
- "(expr (invoke-static \"package:foo/bar.dart::@methods::foo\""
- " () ((int 42)) ()))",
+ expectation: ''
+ '(expr (invoke-static "package:foo/bar.dart::@methods::foo"'
+ ' () ((int 42)) ()))',
serializationState: new SerializationState(null),
deserializationState: new DeserializationState(null, component.root));
}(),
@@ -183,10 +183,10 @@
node: new ExpressionStatement(new StaticInvocation.byReference(
factoryConstructor.reference, new Arguments([]),
isConst: true)),
- expectation: ""
- "(expr (invoke-const-static"
- " \"package:foo/bar.dart::A::@factories::foo\""
- " () () ()))",
+ expectation: ''
+ '(expr (invoke-const-static'
+ ' "package:foo/bar.dart::A::@factories::foo"'
+ ' () () ()))',
serializationState: new SerializationState(null),
deserializationState: new DeserializationState(null, component.root));
}(),
@@ -205,9 +205,9 @@
name: "/* suppose A {dynamic field;} A x; */ x.{A::field};",
node: new ExpressionStatement(new DirectPropertyGet.byReference(
new VariableGet(x), field.reference)),
- expectation: ""
- "(expr (get-direct-prop (get-var \"x^0\" _)"
- " \"package:foo/bar.dart::A::@fields::field\"))",
+ expectation: ''
+ '(expr (get-direct-prop (get-var "x^0" _)'
+ ' "package:foo/bar.dart::A::@fields::field"))',
serializationState:
new SerializationState(new SerializationEnvironment(null)
..addBinder(x, "x^0")
@@ -233,9 +233,9 @@
name: "/* suppose A {dynamic field;} A x; */ x.{A::field} = 42;",
node: new ExpressionStatement(new DirectPropertySet.byReference(
new VariableGet(x), field.reference, new IntLiteral(42))),
- expectation: ""
- "(expr (set-direct-prop (get-var \"x^0\" _)"
- " \"package:foo/bar.dart::A::@fields::field\" (int 42)))",
+ expectation: ''
+ '(expr (set-direct-prop (get-var "x^0" _)'
+ ' "package:foo/bar.dart::A::@fields::field" (int 42)))',
serializationState:
new SerializationState(new SerializationEnvironment(null)
..addBinder(x, "x^0")
@@ -263,10 +263,10 @@
name: "/* suppose A {foo() {...}} A x; */ x.{A::foo}();",
node: new ExpressionStatement(new DirectMethodInvocation.byReference(
new VariableGet(x), method.reference, new Arguments([]))),
- expectation: ""
- "(expr (invoke-direct-method (get-var \"x^0\" _)"
- " \"package:foo/bar.dart::A::@methods::foo\""
- " () () ()))",
+ expectation: ''
+ '(expr (invoke-direct-method (get-var "x^0" _)'
+ ' "package:foo/bar.dart::A::@methods::foo"'
+ ' () () ()))',
serializationState:
new SerializationState(new SerializationEnvironment(null)
..addBinder(x, "x^0")
@@ -291,10 +291,10 @@
name: "/* suppose A {A.foo();} */ new A();",
node: new ExpressionStatement(new ConstructorInvocation.byReference(
constructor.reference, new Arguments([]))),
- expectation: ""
- "(expr (invoke-constructor"
- " \"package:foo/bar.dart::A::@constructors::foo\""
- " () () ()))",
+ expectation: ''
+ '(expr (invoke-constructor'
+ ' "package:foo/bar.dart::A::@constructors::foo"'
+ ' () () ()))',
serializationState: new SerializationState(null),
deserializationState: new DeserializationState(null, component.root));
}(),
@@ -313,10 +313,10 @@
node: new ExpressionStatement(new ConstructorInvocation.byReference(
constructor.reference, new Arguments([]),
isConst: true)),
- expectation: ""
- "(expr (invoke-const-constructor"
- " \"package:foo/bar.dart::A::@constructors::foo\""
- " () () ()))",
+ expectation: ''
+ '(expr (invoke-const-constructor'
+ ' "package:foo/bar.dart::A::@constructors::foo"'
+ ' () () ()))',
serializationState: new SerializationState(null),
deserializationState: new DeserializationState(null, component.root));
}(),
@@ -338,10 +338,36 @@
new TypeParameterType(outterParam, Nullability.legacy),
Nullability.legacy,
typeParameters: [outterParam]))),
- expectation: ""
- "(expr (type (-> (\"T^0\") ((dynamic)) ((dynamic)) "
- "((-> (\"T^1\") ((dynamic)) ((dynamic)) () () () "
- "(par \"T^1\" _))) () () (par \"T^0\" _))))",
+ expectation: ''
+ '(expr (type (-> ("T^0") ((dynamic)) ((dynamic)) '
+ '((-> ("T^1") ((dynamic)) ((dynamic)) () () () '
+ '(par "T^1" _))) () () (par "T^0" _))))',
+ serializationState:
+ new SerializationState(new SerializationEnvironment(null)),
+ deserializationState: new DeserializationState(
+ new DeserializationEnvironment(null), null));
+ }(),
+ () {
+ TypeParameter t =
+ new TypeParameter("T", const DynamicType(), const DynamicType());
+ VariableDeclaration t1 = new VariableDeclaration("t1",
+ type: new TypeParameterType(t, Nullability.legacy));
+ VariableDeclaration t2 = new VariableDeclaration("t2",
+ type: new TypeParameterType(t, Nullability.legacy));
+ return new TestCase(
+ name: "/* <T>(T t1, [T t2]) => t1; */",
+ node: new ExpressionStatement(new FunctionExpression(new FunctionNode(
+ new ReturnStatement(new VariableGet(t1)),
+ typeParameters: [t],
+ positionalParameters: [t1, t2],
+ requiredParameterCount: 1,
+ namedParameters: [],
+ returnType: new TypeParameterType(t, Nullability.legacy),
+ asyncMarker: AsyncMarker.Sync))),
+ expectation: ''
+ '(expr (fun (sync ("T^0") ((dynamic)) ((dynamic)) ((var '
+ '"t1^1" (par "T^0" _) _ ())) ((var "t2^2" (par "T^0" _) '
+ '_ ())) () (par "T^0" _) (ret (get-var "t1^1" _)))))',
serializationState:
new SerializationState(new SerializationEnvironment(null)),
deserializationState: new DeserializationState(
diff --git a/pkg/kernel/test/text_serializer_test.dart b/pkg/kernel/test/text_serializer_test.dart
index ae80281..fadf1e2 100644
--- a/pkg/kernel/test/text_serializer_test.dart
+++ b/pkg/kernel/test/text_serializer_test.dart
@@ -35,61 +35,61 @@
void test() {
List<String> failures = [];
List<String> tests = [
- "(get-prop (int 0) (public \"hashCode\"))",
- "(get-super (public \"hashCode\"))",
- "(invoke-method (int 0) (public \"foo\") () ((int 1) (int 2)) ())",
- "(invoke-method (int 0) (public \"foo\") ((dynamic) (void)) "
- "((int 1) (int 2)) (\"others\" (list (dynamic) ((int 3) (int 4)))))",
- "(let (var \"x^0\" (dynamic) (int 0) ()) (null))",
- "(let (var \"x^0\" (dynamic) _ ()) (null))",
- "(let (const \"x^0\" (dynamic) (int 0) ()) (null))",
- "(let (const \"x^0\" (dynamic) _ ()) (null))",
- "(let (final \"x^0\" (dynamic) (int 0) ()) (null))",
- "(let (final \"x^0\" (dynamic) _ ()) (null))",
- "(string \"Hello, 'string'!\")",
- "(string \"Hello, \\\"string\\\"!\")",
- "(string \"Yeah nah yeah, here is\\nthis really long string haiku\\n"
- "blowing in the wind\\n\")",
- "(int 42)",
- "(int 0)",
- "(int -1001)",
- "(double 3.14159)",
- "(bool true)",
- "(bool false)",
- "(null)",
- "(invalid \"You can't touch this\")",
- "(not (bool true))",
- "(&& (bool true) (bool false))",
- "(|| (&& (bool true) (not (bool true))) (bool true))",
- "(concat ((string \"The opposite of \") (int 3) "
- "(string \" is \") (int 7)))",
- "(symbol \"unquote-splicing\")",
- "(this)",
- "(rethrow)",
- "(throw (string \"error\"))",
- "(await (null))",
- "(cond (bool true) (dynamic) (int 0) (int 1))",
- "(is (bool true) (invalid))",
- "(as (bool true) (void))",
- "(type (bottom))",
- "(list (dynamic) ((null) (null) (null)))",
- "(const-list (dynamic) ((int 0) (int 1) (int 2)))",
- "(set (dynamic) ((bool true) (bool false) (int 0)))",
- "(const-set (dynamic) ((int 0) (int 1) (int 2)))",
- "(map (dynamic) (void) ((int 0) (null) (int 1) (null) (int 2) (null)))",
- "(const-map (dynamic) (void) ((int 0) (null) (int 1) (null) "
- "(int 2) (null)))",
- "(type (-> () () () ((dynamic)) () () (dynamic)))",
- "(type (-> () () () () ((dynamic)) () (dynamic)))",
- "(type (-> () () () ((dynamic) (dynamic)) () () (dynamic)))",
- "(type (-> () () () () () () (dynamic)))",
- "(type (-> () () () ((-> () () () ((dynamic)) () () (dynamic))) () () "
- "(dynamic)))",
- "(type (-> (\"T^0\") ((dynamic)) ((dynamic)) () () () (dynamic)))",
- "(type (-> (\"T^0\") ((dynamic)) ((dynamic)) ((par \"T^0\" _)) () () "
- "(par \"T^0\" _)))",
- "(type (-> (\"T^0\" \"S^1\") ((par \"S^1\" _) (par \"T^0\" _)) ((dynamic) "
- "(dynamic)) () () () (dynamic)))",
+ '(get-prop (int 0) (public "hashCode"))',
+ '(get-super (public "hashCode"))',
+ '(invoke-method (int 0) (public "foo") () ((int 1) (int 2)) ())',
+ '(invoke-method (int 0) (public "foo") ((dynamic) (void)) '
+ '((int 1) (int 2)) ("others" (list (dynamic) ((int 3) (int 4)))))',
+ '(let (var "x^0" (dynamic) (int 0) ()) (null))',
+ '(let (var "x^0" (dynamic) _ ()) (null))',
+ '(let (const "x^0" (dynamic) (int 0) ()) (null))',
+ '(let (const "x^0" (dynamic) _ ()) (null))',
+ '(let (final "x^0" (dynamic) (int 0) ()) (null))',
+ '(let (final "x^0" (dynamic) _ ()) (null))',
+ r'''(string "Hello, 'string'!")''',
+ r'''(string "Hello, \"string\"!")''',
+ r'''(string "Yeah nah yeah, here is\nthis really long string haiku\n'''
+ r'''blowing in the wind\n")''',
+ '(int 42)',
+ '(int 0)',
+ '(int -1001)',
+ '(double 3.14159)',
+ '(bool true)',
+ '(bool false)',
+ '(null)',
+ r'''(invalid "You can't touch this")''',
+ '(not (bool true))',
+ '(&& (bool true) (bool false))',
+ '(|| (&& (bool true) (not (bool true))) (bool true))',
+ '(concat ((string "The opposite of ") (int 3) '
+ '(string " is ") (int 7)))',
+ '(symbol "unquote-splicing")',
+ '(this)',
+ '(rethrow)',
+ '(throw (string "error"))',
+ '(await (null))',
+ '(cond (bool true) (dynamic) (int 0) (int 1))',
+ '(is (bool true) (invalid))',
+ '(as (bool true) (void))',
+ '(type (bottom))',
+ '(list (dynamic) ((null) (null) (null)))',
+ '(const-list (dynamic) ((int 0) (int 1) (int 2)))',
+ '(set (dynamic) ((bool true) (bool false) (int 0)))',
+ '(const-set (dynamic) ((int 0) (int 1) (int 2)))',
+ '(map (dynamic) (void) ((int 0) (null) (int 1) (null) (int 2) (null)))',
+ '(const-map (dynamic) (void) ((int 0) (null) (int 1) (null) '
+ '(int 2) (null)))',
+ '(type (-> () () () ((dynamic)) () () (dynamic)))',
+ '(type (-> () () () () ((dynamic)) () (dynamic)))',
+ '(type (-> () () () ((dynamic) (dynamic)) () () (dynamic)))',
+ '(type (-> () () () () () () (dynamic)))',
+ '(type (-> () () () ((-> () () () ((dynamic)) () () (dynamic))) () () '
+ '(dynamic)))',
+ '(type (-> ("T^0") ((dynamic)) ((dynamic)) () () () (dynamic)))',
+ '(type (-> ("T^0") ((dynamic)) ((dynamic)) ((par "T^0" _)) () () '
+ '(par "T^0" _)))',
+ '(type (-> ("T^0" "S^1") ((par "S^1" _) (par "T^0" _)) ((dynamic) '
+ '(dynamic)) () () () (dynamic)))',
];
for (var test in tests) {
var literal = readExpression(test);
diff --git a/pkg/nnbd_migration/lib/instrumentation.dart b/pkg/nnbd_migration/lib/instrumentation.dart
index 31872c2..013e433 100644
--- a/pkg/nnbd_migration/lib/instrumentation.dart
+++ b/pkg/nnbd_migration/lib/instrumentation.dart
@@ -131,19 +131,30 @@
dynamicAssignment,
expressionChecks,
fieldFormalParameter,
+ fieldNotInitialized,
forEachVariable,
greatestLowerBound,
ifNull,
implicitMixinSuperCall,
- inheritance,
initializerInference,
+ instanceCreation,
instantiateToBounds,
isCheckComponentType,
isCheckMainType,
+ literal,
namedParameterNotSupplied,
+ nonNullableBoolType,
+ nonNullableObjectSuperclass,
+ nonNullableUsage,
nonNullAssertion,
nullabilityComment,
optionalFormalParameter,
+ parameterInheritance,
+ returnTypeInheritance,
+ stackTraceTypeOrigin,
+ thisOrSuper,
+ throw_,
+ uninitializedRead,
}
/// Interface used by the migration engine to expose information to its client
@@ -180,8 +191,8 @@
/// and why it was created.
void graphEdge(EdgeInfo edge, EdgeOriginInfo originInfo);
- /// Called when the migration engine start up, to report information about the
- /// immutable migration nodes [never] and [always] that are used as the
+ /// Called when the migration engine starts up, to report information about
+ /// the immutable migration nodes [never] and [always] that are used as the
/// starting point for nullability propagation.
void immutableNodes(NullabilityNodeInfo never, NullabilityNodeInfo always);
@@ -226,6 +237,17 @@
/// Information exposed to the migration client about a single node in the
/// nullability graph.
abstract class NullabilityNodeInfo implements FixReasonInfo {
+ /// List of compound nodes wrapping this node.
+ final List<NullabilityNodeInfo> outerCompoundNodes = <NullabilityNodeInfo>[];
+
+ /// Some nodes get nullability from downstream, so the downstream edges are
+ /// available to query as well.
+ Iterable<EdgeInfo> get downstreamEdges;
+
+ /// After migration is complete, this getter can be used to query whether
+ /// the type associated with this node was determined to be "exact nullable."
+ bool get isExactNullable;
+
/// Indicates whether the node is immutable. The only immutable nodes in the
/// nullability graph are the nodes `never` and `always` that are used as the
/// starting points for nullability propagation.
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index 145054a..b81c0c6 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -16,46 +16,65 @@
/// "then" branch discarded.
static const discardThen = const NullabilityFixDescription._(
appliedMessage: 'Discarded an unreachable conditional then branch',
+ kind: NullabilityFixKind.discardThen,
);
/// An if-test or conditional expression needs to have its condition
/// discarded.
static const discardCondition = const NullabilityFixDescription._(
appliedMessage: 'Discarded a condition which is always true',
+ kind: NullabilityFixKind.discardCondition,
);
/// An if-test or conditional expression needs to have its condition and
/// "else" branch discarded.
static const discardElse = const NullabilityFixDescription._(
appliedMessage: 'Discarded an unreachable conditional else branch',
+ kind: NullabilityFixKind.discardElse,
);
/// An expression's value needs to be null-checked.
static const checkExpression = const NullabilityFixDescription._(
appliedMessage: 'Added a non-null assertion to nullable expression',
+ kind: NullabilityFixKind.checkExpression,
);
/// A message used by dartfix to indicate a fix has been applied.
final String appliedMessage;
+ /// The kind of fix described.
+ final NullabilityFixKind kind;
+
/// A formal parameter needs to have a required keyword added.
factory NullabilityFixDescription.addRequired(
String className, String functionName, String paramName) =>
NullabilityFixDescription._(
- appliedMessage:
- "Add 'required' keyword to parameter '$paramName' in " +
- (className == null
- ? functionName
- : "'$className.$functionName'"));
+ appliedMessage: "Add 'required' keyword to parameter '$paramName' in " +
+ (className == null ? functionName : "'$className.$functionName'"),
+ kind: NullabilityFixKind.addRequired,
+ );
/// An explicit type mentioned in the source program needs to be made
/// nullable.
factory NullabilityFixDescription.makeTypeNullable(String type) =>
NullabilityFixDescription._(
appliedMessage: "Changed type '$type' to be nullable",
+ kind: NullabilityFixKind.makeTypeNullable,
);
- const NullabilityFixDescription._({@required this.appliedMessage});
+ const NullabilityFixDescription._(
+ {@required this.appliedMessage, @required this.kind});
+}
+
+/// An enumeration of the various kinds of nullability fixes.
+enum NullabilityFixKind {
+ addRequired,
+ checkExpression,
+ discardCondition,
+ discardElse,
+ discardThen,
+ makeTypeNullable,
+ noModification,
}
/// Provisional API for DartFix to perform nullability migration.
@@ -106,8 +125,8 @@
/// What kind of fix this is.
NullabilityFixDescription get description;
- /// Location of the change, for reporting to the user.
- Location get location;
+ /// Locations of the change, for reporting to the user.
+ List<Location> get locations;
/// File to change.
Source get source;
diff --git a/pkg/nnbd_migration/lib/src/decorated_type.dart b/pkg/nnbd_migration/lib/src/decorated_type.dart
index a7a3a60..48e41f2 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type.dart
@@ -149,10 +149,8 @@
factory DecoratedType.forImplicitType(
TypeProvider typeProvider, DartType type, NullabilityGraph graph,
{List<DecoratedType> typeArguments}) {
- if (type.isDynamic || type.isVoid) {
- assert(typeArguments == null);
- return DecoratedType(type, graph.always);
- } else if (type is InterfaceType) {
+ var nullabilityNode = NullabilityNode.forInferredType();
+ if (type is InterfaceType) {
assert(() {
if (typeArguments != null) {
assert(typeArguments.length == type.typeArguments.length);
@@ -166,24 +164,17 @@
typeArguments ??= type.typeArguments
.map((t) => DecoratedType.forImplicitType(typeProvider, t, graph))
.toList();
- return DecoratedType(type, NullabilityNode.forInferredType(),
- typeArguments: typeArguments);
+ return DecoratedType(type, nullabilityNode, typeArguments: typeArguments);
} else if (type is FunctionType) {
if (typeArguments != null) {
throw "Not supported: implicit function type with explicit type arguments";
}
return DecoratedType.forImplicitFunction(
- typeProvider, type, NullabilityNode.forInferredType(), graph);
- } else if (type is TypeParameterType) {
+ typeProvider, type, nullabilityNode, graph);
+ } else {
assert(typeArguments == null);
- return DecoratedType(type, NullabilityNode.forInferredType());
- } else if (type is NeverTypeImpl) {
- assert(typeArguments == null);
- return DecoratedType(type, NullabilityNode.forInferredType());
+ return DecoratedType(type, nullabilityNode);
}
- // TODO(paulberry)
- throw UnimplementedError(
- 'DecoratedType.forImplicitType(${type.runtimeType})');
}
/// Creates a [DecoratedType] for a synthetic type parameter, to be used
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index ac9aecd..f44ba67 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -8,11 +8,12 @@
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
-import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
import 'package:analyzer/src/generated/source.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/instrumentation.dart';
@@ -119,18 +120,6 @@
/// information used in flow analysis. Otherwise `null`.
AssignedVariables<AstNode, PromotableElement> _assignedVariables;
- /// For convenience, a [DecoratedType] representing non-nullable `Object`.
- final DecoratedType _notNullType;
-
- /// For convenience, a [DecoratedType] representing non-nullable `bool`.
- final DecoratedType _nonNullableBoolType;
-
- /// For convenience, a [DecoratedType] representing non-nullable `Type`.
- final DecoratedType _nonNullableTypeType;
-
- /// For convenience, a [DecoratedType] representing `dynamic`.
- final DecoratedType _dynamicType;
-
/// The [DecoratedType] of the innermost function or method being visited, or
/// `null` if the visitor is not inside any function or method.
///
@@ -191,16 +180,19 @@
/// of the cascade. Otherwise `null`.
DecoratedType _currentCascadeTargetType;
+ /// While visiting a class declaration, set of class fields that lack
+ /// initializers at their declaration sites.
+ Set<FieldElement> _fieldsNotInitializedAtDeclaration;
+
+ /// While visiting a constructor, set of class fields that lack initializers
+ /// at their declaration sites *and* for which we haven't yet found an
+ /// initializer in the constructor declaration.
+ Set<FieldElement> _fieldsNotInitializedByConstructor;
+
EdgeBuilder(this.typeProvider, this._typeSystem, this._variables, this._graph,
this.source, this.listener, this._decoratedClassHierarchy,
{this.instrumentation})
- : _inheritanceManager = InheritanceManager3(_typeSystem),
- _notNullType = DecoratedType(typeProvider.objectType, _graph.never),
- _nonNullableBoolType =
- DecoratedType(typeProvider.boolType, _graph.never),
- _nonNullableTypeType =
- DecoratedType(typeProvider.typeType, _graph.never),
- _dynamicType = DecoratedType(typeProvider.dynamicType, _graph.always);
+ : _inheritanceManager = InheritanceManager3();
/// Gets the decorated type of [element] from [_variables], performing any
/// necessary substitutions.
@@ -223,13 +215,16 @@
var variable = baseElement.variable;
var decoratedElementType = _variables.decoratedElementType(variable);
if (baseElement.isGetter) {
- decoratedBaseType = DecoratedType(baseElement.type, _graph.never,
+ decoratedBaseType = DecoratedType(
+ baseElement.type, NullabilityNode.forInferredType(),
returnType: decoratedElementType);
} else {
assert(baseElement.isSetter);
- decoratedBaseType = DecoratedType(baseElement.type, _graph.never,
+ decoratedBaseType = DecoratedType(
+ baseElement.type, NullabilityNode.forInferredType(),
positionalParameters: [decoratedElementType],
- returnType: DecoratedType(VoidTypeImpl.instance, _graph.always));
+ returnType: DecoratedType(
+ VoidTypeImpl.instance, NullabilityNode.forInferredType()));
}
} else {
decoratedBaseType = _variables.decoratedElementType(baseElement);
@@ -266,9 +261,8 @@
if (identical(_conditionInfo?.condition, node.condition)) {
var intentNode = _conditionInfo.trueDemonstratesNonNullIntent;
if (intentNode != null && _conditionInfo.postDominatingIntent) {
- _graph.connect(_conditionInfo.trueDemonstratesNonNullIntent,
- _graph.never, NonNullAssertionOrigin(source, node),
- hard: true);
+ _graph.makeNonNullable(_conditionInfo.trueDemonstratesNonNullIntent,
+ NonNullAssertionOrigin(source, node));
}
}
_flowAnalysis.assert_afterCondition(node.condition);
@@ -284,9 +278,8 @@
if (identical(_conditionInfo?.condition, node.condition)) {
var intentNode = _conditionInfo.trueDemonstratesNonNullIntent;
if (intentNode != null && _conditionInfo.postDominatingIntent) {
- _graph.connect(_conditionInfo.trueDemonstratesNonNullIntent,
- _graph.never, NonNullAssertionOrigin(source, node),
- hard: true);
+ _graph.makeNonNullable(_conditionInfo.trueDemonstratesNonNullIntent,
+ NonNullAssertionOrigin(source, node));
}
}
_flowAnalysis.assert_afterCondition(node.condition);
@@ -353,7 +346,7 @@
falseDemonstratesNonNullIntent: leftType.node);
_conditionInfo = notEqual ? conditionInfo.not(node) : conditionInfo;
}
- return _nonNullableBoolType;
+ return _makeNonNullableBoolType(node);
} else if (operatorType == TokenType.AMPERSAND_AMPERSAND ||
operatorType == TokenType.BAR_BAR) {
bool isAnd = operatorType == TokenType.AMPERSAND_AMPERSAND;
@@ -362,7 +355,7 @@
_postDominatedLocals.doScoped(
action: () => _checkExpressionNotNull(rightOperand));
_flowAnalysis.logicalBinaryOp_end(node, rightOperand, isAnd: isAnd);
- return _nonNullableBoolType;
+ return _makeNonNullableBoolType(node);
} else if (operatorType == TokenType.QUESTION_QUESTION) {
DecoratedType expressionType;
var leftType = leftOperand.accept(this);
@@ -390,7 +383,7 @@
var callee = node.staticElement;
if (callee == null) {
rightOperand.accept(this);
- return _dynamicType;
+ return _makeNullableDynamicType(node);
} else {
var calleeType =
getOrComputeElementType(callee, targetType: targetType);
@@ -411,7 +404,7 @@
@override
DecoratedType visitBooleanLiteral(BooleanLiteral node) {
_flowAnalysis.booleanLiteral(node, node.value);
- return DecoratedType(node.staticType, _graph.never);
+ return _makeNonNullLiteralType(node);
}
@override
@@ -453,8 +446,18 @@
@override
DecoratedType visitClassDeclaration(ClassDeclaration node) {
+ _fieldsNotInitializedAtDeclaration = {
+ for (var member in node.members)
+ if (member is FieldDeclaration)
+ for (var field in member.fields.variables)
+ if (field.initializer == null) field.declaredElement as FieldElement
+ };
+ if (node.declaredElement.unnamedConstructor?.isSynthetic == true) {
+ _handleUninitializedFields(node, _fieldsNotInitializedAtDeclaration);
+ }
node.metadata.accept(this);
node.members.accept(this);
+ _fieldsNotInitializedAtDeclaration = null;
return null;
}
@@ -515,6 +518,8 @@
@override
DecoratedType visitConstructorDeclaration(ConstructorDeclaration node) {
+ _fieldsNotInitializedByConstructor =
+ _fieldsNotInitializedAtDeclaration.toSet();
_handleExecutableDeclaration(
node,
node.declaredElement,
@@ -524,12 +529,14 @@
node.initializers,
node.body,
node.redirectedConstructor);
+ _fieldsNotInitializedByConstructor = null;
return null;
}
@override
DecoratedType visitConstructorFieldInitializer(
ConstructorFieldInitializer node) {
+ _fieldsNotInitializedByConstructor.remove(node.fieldName.staticElement);
_handleAssignment(node.expression,
destinationType: getOrComputeElementType(node.fieldName.staticElement));
return null;
@@ -556,9 +563,7 @@
// Nothing to do; the implicit default value of `null` will never be
// reached.
} else {
- _connect(
- _graph.always,
- getOrComputeElementType(node.declaredElement).node,
+ _graph.makeNullable(getOrComputeElementType(node.declaredElement).node,
OptionalFormalParameterOrigin(source, node));
}
} else {
@@ -581,7 +586,7 @@
@override
DecoratedType visitDoubleLiteral(DoubleLiteral node) {
- return DecoratedType(node.staticType, _graph.never);
+ return _makeNonNullLiteralType(node);
}
@override
@@ -602,7 +607,9 @@
DecoratedType visitFieldFormalParameter(FieldFormalParameter node) {
var parameterElement = node.declaredElement as FieldFormalParameterElement;
var parameterType = _variables.decoratedElementType(parameterElement);
- var fieldType = _variables.decoratedElementType(parameterElement.field);
+ var field = parameterElement.field;
+ _fieldsNotInitializedByConstructor.remove(field);
+ var fieldType = _variables.decoratedElementType(field);
var origin = FieldFormalParameterOrigin(source, node);
if (node.type == null) {
_unionDecoratedTypes(parameterType, fieldType, origin);
@@ -637,8 +644,8 @@
// Initialize a new postDominator scope that contains only the parameters.
try {
node.functionExpression.accept(this);
- } finally {
_flowAnalysis.finish();
+ } finally {
_flowAnalysis = null;
_assignedVariables = null;
}
@@ -767,7 +774,7 @@
// Dynamic dispatch. The return type is `dynamic`.
// TODO(paulberry): would it be better to assume a return type of `Never`
// so that we don't unnecessarily propagate nullabilities everywhere?
- return _dynamicType;
+ return _makeNullableDynamicType(node);
}
var calleeType = getOrComputeElementType(callee, targetType: targetType);
// TODO(paulberry): substitute if necessary
@@ -808,7 +815,10 @@
decoratedTypeArguments = const [];
}
}
- var createdType = DecoratedType(node.staticType, _graph.never,
+ var nullabilityNode = NullabilityNode.forInferredType();
+ _graph.makeNonNullable(
+ nullabilityNode, InstanceCreationOrigin(source, node));
+ var createdType = DecoratedType(node.staticType, nullabilityNode,
typeArguments: decoratedTypeArguments);
var calleeType = getOrComputeElementType(callee, targetType: createdType);
_handleInvocationArguments(node, node.argumentList.arguments, typeArguments,
@@ -818,7 +828,7 @@
@override
DecoratedType visitIntegerLiteral(IntegerLiteral node) {
- return DecoratedType(node.staticType, _graph.never);
+ return _makeNonNullLiteralType(node);
}
@override
@@ -829,14 +839,13 @@
if (type is NamedType) {
// The main type of the is check historically could not be nullable.
// Making it nullable could change runtime behavior.
- _connect(decoratedType.node, _graph.never,
- IsCheckMainTypeOrigin(source, type));
+ _graph.makeNonNullable(
+ decoratedType.node, IsCheckMainTypeOrigin(source, type));
if (type.typeArguments != null) {
// TODO(mfairhurst): connect arguments to the expression type when they
// relate.
type.typeArguments.arguments.forEach((argument) {
- _connect(
- _graph.always,
+ _graph.makeNullable(
_variables.decoratedTypeAnnotation(source, argument).node,
IsCheckComponentTypeOrigin(source, argument));
});
@@ -849,7 +858,7 @@
expression.accept(this);
_flowAnalysis.isExpression_end(
node, expression, node.notOperator != null, decoratedType);
- return DecoratedType(node.staticType, _graph.never);
+ return _makeNonNullableBoolType(node);
}
@override
@@ -881,7 +890,7 @@
source, node.typeArguments.arguments[0]);
}
node.elements.forEach(_handleCollectionElement);
- return DecoratedType(listType, _graph.never,
+ return _makeNonNullLiteralType(node,
typeArguments: [_currentLiteralElementType]);
} finally {
_currentLiteralElementType = previousLiteralType;
@@ -930,7 +939,7 @@
// so that we don't unnecessarily propagate nullabilities everywhere?
node.typeArguments?.accept(this);
node.argumentList.accept(this);
- return _dynamicType;
+ return _makeNullableDynamicType(node);
} else if (callee is VariableElement) {
// Function expression invocation that looks like a method invocation.
return _handleFunctionExpressionInvocation(node, node.methodName,
@@ -968,8 +977,7 @@
_flowAnalysis.nullLiteral(node);
var decoratedType =
DecoratedType.forImplicitType(typeProvider, node.staticType, _graph);
- _graph.makeNullable(
- decoratedType.node, AlwaysNullableTypeOrigin(source, node));
+ _graph.makeNullable(decoratedType.node, LiteralOrigin(source, node));
return decoratedType;
}
@@ -998,7 +1006,7 @@
// Dynamic dispatch. The return type is `dynamic`.
// TODO(paulberry): would it be better to assume a return type of `Never`
// so that we don't unnecessarily propagate nullabilities everywhere?
- writeType = _dynamicType;
+ writeType = _makeNullableDynamicType(node);
} else {
var calleeType =
getOrComputeElementType(callee, targetType: targetType);
@@ -1034,7 +1042,7 @@
var operatorType = node.operator.type;
if (operatorType == TokenType.BANG) {
_flowAnalysis.logicalNot_end(node, operand);
- return _nonNullableBoolType;
+ return _makeNonNullableBoolType(node);
} else {
var callee = node.staticElement;
var isIncrementOrDecrement = operatorType.isIncrementOperator;
@@ -1043,7 +1051,7 @@
// Dynamic dispatch. The return type is `dynamic`.
// TODO(paulberry): would it be better to assume a return type of `Never`
// so that we don't unnecessarily propagate nullabilities everywhere?
- staticType = _dynamicType;
+ staticType = _makeNullableDynamicType(node);
} else {
var calleeType =
getOrComputeElementType(callee, targetType: targetType);
@@ -1085,7 +1093,9 @@
@override
DecoratedType visitRethrowExpression(RethrowExpression node) {
_flowAnalysis.handleExit();
- return DecoratedType(node.staticType, _graph.never);
+ var nullabilityNode = NullabilityNode.forInferredType();
+ _graph.makeNonNullable(nullabilityNode, ThrowOrigin(source, node));
+ return DecoratedType(node.staticType, nullabilityNode);
}
@override
@@ -1136,7 +1146,7 @@
_variables.decoratedTypeAnnotation(source, typeArguments[0]);
}
node.elements.forEach(_handleCollectionElement);
- return DecoratedType(setOrMapType, _graph.never,
+ return _makeNonNullLiteralType(node,
typeArguments: [_currentLiteralElementType]);
} finally {
_currentLiteralElementType = previousLiteralType;
@@ -1166,7 +1176,7 @@
}
node.elements.forEach(_handleCollectionElement);
- return DecoratedType(setOrMapType, _graph.never,
+ return _makeNonNullLiteralType(node,
typeArguments: [_currentMapKeyType, _currentMapValueType]);
} finally {
_currentMapKeyType = previousKeyType;
@@ -1183,7 +1193,13 @@
var promotedType = _flowAnalysis.variableRead(node, staticElement);
if (promotedType != null) return promotedType;
}
- return getOrComputeElementType(staticElement);
+ var type = getOrComputeElementType(staticElement);
+ if (!node.inDeclarationContext() &&
+ node.inGetterContext() &&
+ !_flowAnalysis.isAssigned(staticElement)) {
+ _graph.makeNullable(type.node, UninitializedReadOrigin(source, node));
+ }
+ return type;
} else if (staticElement is FunctionElement ||
staticElement is MethodElement) {
return getOrComputeElementType(staticElement);
@@ -1193,7 +1209,7 @@
? elementType.returnType
: elementType.positionalParameters[0];
} else if (staticElement is TypeDefiningElement) {
- return _nonNullableTypeType;
+ return _makeNonNullLiteralType(node);
} else {
// TODO(paulberry)
_unimplemented(node,
@@ -1239,7 +1255,7 @@
@override
DecoratedType visitStringLiteral(StringLiteral node) {
node.visitChildren(this);
- return DecoratedType(node.staticType, _graph.never);
+ return _makeNonNullLiteralType(node);
}
@override
@@ -1268,7 +1284,7 @@
@override
DecoratedType visitSymbolLiteral(SymbolLiteral node) {
- return DecoratedType(node.staticType, _graph.never);
+ return _makeNonNullLiteralType(node);
}
@override
@@ -1281,7 +1297,9 @@
node.expression.accept(this);
// TODO(paulberry): do we need to check the expression type? I think not.
_flowAnalysis.handleExit();
- return DecoratedType(node.staticType, _graph.never);
+ var nullabilityNode = NullabilityNode.forInferredType();
+ _graph.makeNonNullable(nullabilityNode, ThrowOrigin(source, node));
+ return DecoratedType(node.staticType, nullabilityNode);
}
@override
@@ -1346,7 +1364,7 @@
}
}
}
- return _nonNullableTypeType;
+ return null;
}
@override
@@ -1355,7 +1373,6 @@
bool isTopLevel =
parent is FieldDeclaration || parent is TopLevelVariableDeclaration;
node.metadata.accept(this);
- var typeAnnotation = node.type;
for (var variable in node.variables) {
variable.metadata.accept(this);
var initializer = variable.initializer;
@@ -1372,22 +1389,13 @@
_flowAnalysis.initialize(declaredElement);
}
var destinationType = getOrComputeElementType(declaredElement);
- if (typeAnnotation == null) {
- var initializerType = initializer.accept(this);
- if (initializerType == null) {
- throw StateError(
- 'No type computed for ${initializer.runtimeType} '
- '(${initializer.toSource()}) offset=${initializer.offset}');
- }
- _unionDecoratedTypes(initializerType, destinationType,
- InitializerInferenceOrigin(source, variable));
- } else {
- _handleAssignment(initializer, destinationType: destinationType);
- }
+ _handleAssignment(initializer, destinationType: destinationType);
+ }
+ if (isTopLevel) {
+ _flowAnalysis.finish();
}
} finally {
if (isTopLevel) {
- _flowAnalysis.finish();
_flowAnalysis = null;
_assignedVariables = null;
}
@@ -1433,14 +1441,22 @@
///
/// Returns the decorated type of [expression].
DecoratedType _checkExpressionNotNull(Expression expression) {
- // Note: it's not necessary for `destinationType` to precisely match the
- // type of the expression, since all we are doing is causing a single graph
- // edge to be built; it is sufficient to pass in any decorated type whose
- // node is `never`.
if (_isPrefix(expression)) {
throw ArgumentError('cannot check non-nullability of a prefix');
}
- return _handleAssignment(expression, destinationType: _notNullType);
+ DecoratedType sourceType = expression.accept(this);
+ if (sourceType == null) {
+ throw StateError('No type computed for ${expression.runtimeType} '
+ '(${expression.toSource()}) offset=${expression.offset}');
+ }
+ var origin = _makeEdgeOrigin(sourceType, expression);
+ var edge = _graph.makeNonNullable(sourceType.node, origin,
+ hard: _postDominatedLocals.isReferenceInScope(expression),
+ guards: _guards);
+ if (origin is ExpressionChecksOrigin) {
+ origin.checks.edges.add(edge);
+ }
+ return sourceType;
}
@override
@@ -1463,21 +1479,35 @@
PromotableElement, DecoratedType>(
DecoratedTypeOperations(_typeSystem, _variables, _graph),
_assignedVariables);
+ if (parameters != null) {
+ for (var parameter in parameters.parameters) {
+ _flowAnalysis.initialize(parameter.declaredElement);
+ }
+ }
+ }
+
+ /// Creates a type that can be used to check that an expression's value is
+ /// non-nullable.
+ DecoratedType _createNonNullableType(Expression expression) {
+ // Note: it's not necessary for the type to precisely match the type of the
+ // expression, since all we are going to do is cause a single graph edge to
+ // be built; it is sufficient to pass in any decorated type whose node is
+ // non-nullable. So we use `Object`.
+ var nullabilityNode = NullabilityNode.forInferredType();
+ _graph.makeNonNullable(
+ nullabilityNode, NonNullableUsageOrigin(source, expression));
+ return DecoratedType(typeProvider.objectType, nullabilityNode);
}
DecoratedType _decorateUpperOrLowerBound(AstNode astNode, DartType type,
DecoratedType left, DecoratedType right, bool isLUB,
{NullabilityNode node}) {
- if (type.isDynamic || type.isVoid) {
- if (type.isDynamic) {
- _unimplemented(astNode, 'LUB/GLB with dynamic');
- }
- return DecoratedType(type, _graph.always);
- }
node ??= isLUB
? NullabilityNode.forLUB(left.node, right.node)
: _nullabilityNodeForGLB(astNode, left.node, right.node);
- if (type is InterfaceType) {
+ if (type.isDynamic || type.isVoid) {
+ return DecoratedType(type, node);
+ } else if (type is InterfaceType) {
if (type.typeArguments.isEmpty) {
return DecoratedType(type, node);
} else {
@@ -1625,28 +1655,14 @@
throw StateError('No type computed for ${expression.runtimeType} '
'(${expression.toSource()}) offset=${expression.offset}');
}
- EdgeOrigin edgeOrigin;
- if (sourceType.type.isDynamic) {
- edgeOrigin = DynamicAssignmentOrigin(source, expression);
- } else {
- if (fromDefaultValue) {
- edgeOrigin = DefaultValueOrigin(source, expression);
- } else {
- ExpressionChecksOrigin expressionChecksOrigin =
- ExpressionChecksOrigin(
- source, expression, ExpressionChecks(expression.end));
- _variables.recordExpressionChecks(
- source, expression, expressionChecksOrigin);
- edgeOrigin = expressionChecksOrigin;
- }
- }
+ EdgeOrigin edgeOrigin = _makeEdgeOrigin(sourceType, expression);
if (compoundOperatorInfo != null) {
var compoundOperatorMethod = compoundOperatorInfo.staticElement;
if (compoundOperatorMethod != null) {
_checkAssignment(
CompoundAssignmentOrigin(source, compoundOperatorInfo),
source: destinationType,
- destination: _notNullType,
+ destination: _createNonNullableType(compoundOperatorInfo),
hard: _postDominatedLocals
.isReferenceInScope(destinationExpression));
DecoratedType compoundOperatorType = getOrComputeElementType(
@@ -1665,7 +1681,7 @@
destination: destinationType,
hard: false);
} else {
- sourceType = _dynamicType;
+ sourceType = _makeNullableDynamicType(compoundOperatorInfo);
}
} else {
_checkAssignment(edgeOrigin,
@@ -1743,13 +1759,17 @@
_postDominatedLocals.pushScope(elements: declaredElement.parameters);
try {
initializers?.accept(this);
+ if (declaredElement is ConstructorElement &&
+ !declaredElement.isFactory &&
+ declaredElement.redirectedConstructor == null) {
+ _handleUninitializedFields(node, _fieldsNotInitializedByConstructor);
+ }
body.accept(this);
if (redirectedConstructor != null) {
_handleConstructorRedirection(parameters, redirectedConstructor);
}
if (declaredElement is! ConstructorElement) {
var classElement = declaredElement.enclosingElement as ClassElement;
- var origin = InheritanceOrigin(source, node);
for (var overriddenElement in _inheritanceManager.getOverridden(
classElement.thisType,
Name(classElement.library.source.uri, declaredElement.name)) ??
@@ -1765,10 +1785,12 @@
var overriddenFunctionType =
decoratedOverriddenFunctionType.substitute(substitution);
if (returnType == null) {
- _unionDecoratedTypes(_currentFunctionType.returnType,
- overriddenFunctionType.returnType, origin);
+ _unionDecoratedTypes(
+ _currentFunctionType.returnType,
+ overriddenFunctionType.returnType,
+ ReturnTypeInheritanceOrigin(source, node));
} else {
- _checkAssignment(origin,
+ _checkAssignment(ReturnTypeInheritanceOrigin(source, node),
source: _currentFunctionType.returnType,
destination: overriddenFunctionType.returnType,
hard: true);
@@ -1805,6 +1827,7 @@
positionalParameterCount++;
}
if (overriddenParameterType != null) {
+ var origin = ParameterInheritanceOrigin(source, node);
if (_isUntypedParameter(normalParameter)) {
_unionDecoratedTypes(
overriddenParameterType, currentParameterType, origin);
@@ -1819,8 +1842,8 @@
}
}
}
- } finally {
_flowAnalysis.finish();
+ } finally {
_flowAnalysis = null;
_assignedVariables = null;
_currentFunctionType = null;
@@ -1871,7 +1894,7 @@
_flowAnalysis.forEach_bodyBegin(
node,
lhsElement is PromotableElement ? lhsElement : null,
- elementType ?? _dynamicType);
+ elementType ?? _makeNullableDynamicType(node));
}
// The condition may fail/iterable may be empty, so the body gets a new
@@ -1903,7 +1926,7 @@
// Invocation of type `dynamic` or `Function`.
typeArguments?.accept(this);
argumentList.accept(this);
- return _dynamicType;
+ return _makeNullableDynamicType(node);
}
}
@@ -2012,7 +2035,7 @@
}
if (callee == null) {
// Dynamic dispatch.
- return _dynamicType;
+ return _makeNullableDynamicType(node);
}
var calleeType = getOrComputeElementType(callee, targetType: targetType);
// TODO(paulberry): substitute if necessary
@@ -2044,17 +2067,30 @@
DecoratedType _handleThisOrSuper(Expression node) {
var type = node.staticType as InterfaceType;
- // Instantiate the type, and any type arguments, with `_graph.never`,
+ // Instantiate the type, and any type arguments, with non-nullable types,
// because the type of `this` is always `ClassName<Param, Param, ...>` with
// no `?`s. (Even if some of the type parameters are allowed to be
// instantiated with nullable types at runtime, a reference to `this` can't
// be migrated in such a way that forces them to be nullable).
- return DecoratedType(type, _graph.never,
+ NullabilityNode makeNonNullableNode() {
+ var nullabilityNode = NullabilityNode.forInferredType();
+ _graph.makeNonNullable(nullabilityNode, ThisOrSuperOrigin(source, node));
+ return nullabilityNode;
+ }
+
+ return DecoratedType(type, makeNonNullableNode(),
typeArguments: type.typeArguments
- .map((t) => DecoratedType(t, _graph.never))
+ .map((t) => DecoratedType(t, makeNonNullableNode()))
.toList());
}
+ void _handleUninitializedFields(AstNode node, Set<FieldElement> fields) {
+ for (var field in fields) {
+ _graph.makeNullable(_variables.decoratedElementType(field).node,
+ FieldNotInitializedOrigin(source, node));
+ }
+ }
+
bool _isPrefix(Expression e) =>
e is SimpleIdentifier && e.staticElement is PrefixElement;
@@ -2068,6 +2104,42 @@
}
}
+ EdgeOrigin _makeEdgeOrigin(DecoratedType sourceType, Expression expression) {
+ if (sourceType.type.isDynamic) {
+ return DynamicAssignmentOrigin(source, expression);
+ } else {
+ ExpressionChecksOrigin expressionChecksOrigin = ExpressionChecksOrigin(
+ source, expression, ExpressionChecks(expression.end));
+ _variables.recordExpressionChecks(
+ source, expression, expressionChecksOrigin);
+ return expressionChecksOrigin;
+ }
+ }
+
+ DecoratedType _makeNonNullableBoolType(Expression expression) {
+ assert(expression.staticType.isDartCoreBool);
+ var nullabilityNode = NullabilityNode.forInferredType();
+ _graph.makeNonNullable(
+ nullabilityNode, NonNullableBoolTypeOrigin(source, expression));
+ return DecoratedType(typeProvider.boolType, nullabilityNode);
+ }
+
+ DecoratedType _makeNonNullLiteralType(Expression expression,
+ {List<DecoratedType> typeArguments = const []}) {
+ var nullabilityNode = NullabilityNode.forInferredType();
+ _graph.makeNonNullable(nullabilityNode, LiteralOrigin(source, expression));
+ return DecoratedType(expression.staticType, nullabilityNode,
+ typeArguments: typeArguments);
+ }
+
+ DecoratedType _makeNullableDynamicType(AstNode astNode) {
+ var decoratedType = DecoratedType.forImplicitType(
+ typeProvider, typeProvider.dynamicType, _graph);
+ _graph.makeNullable(
+ decoratedType.node, AlwaysNullableTypeOrigin(source, astNode));
+ return decoratedType;
+ }
+
NullabilityNode _nullabilityNodeForGLB(
AstNode astNode, NullabilityNode leftNode, NullabilityNode rightNode) {
var node = NullabilityNode.forGLB();
@@ -2145,8 +2217,6 @@
DecoratedClassHierarchy get _decoratedClassHierarchy;
- NullabilityGraph get _graph;
-
TypeSystem get _typeSystem;
/// Creates the necessary constraint(s) for an assignment from [source] to
@@ -2336,18 +2406,12 @@
'downcast to type parameters with bounds not supported');
}
}
-
- for (final arg in destination.typeArguments) {
- // We cannot assume we're downcasting to C<T!>. Downcast to C<T?>.
- _checkDowncast(origin, source: source, destination: arg, hard: false);
- }
} else if (destinationType is TypeParameterType &&
source.type is! TypeParameterType) {
// Assume an assignment to the type parameter's bound.
_checkAssignment(origin,
source: source,
- destination:
- _getTypeParameterTypeBound(destination).withNode(_graph.always),
+ destination: _getTypeParameterTypeBound(destination),
hard: false);
} else if (destinationType is InterfaceType) {
assert(source.typeArguments.isEmpty,
@@ -2356,13 +2420,6 @@
assert(param.bound == null,
'downcast to type parameters with bounds not supported');
}
- for (final arg in destination.typeArguments) {
- // We cannot assume we're downcasting to C<T!>. Downcast to C<T?>.
- _checkDowncast(origin,
- source: DecoratedType(typeProvider.dynamicType, _graph.always),
- destination: arg,
- hard: false);
- }
} else {
assert(
false,
diff --git a/pkg/nnbd_migration/lib/src/edge_origin.dart b/pkg/nnbd_migration/lib/src/edge_origin.dart
index 2899ee8a..e593c40 100644
--- a/pkg/nnbd_migration/lib/src/edge_origin.dart
+++ b/pkg/nnbd_migration/lib/src/edge_origin.dart
@@ -109,6 +109,19 @@
EdgeOriginKind get kind => EdgeOriginKind.fieldFormalParameter;
}
+/// An edge origin used for edges that originated because a field was not
+/// initialized.
+///
+/// The AST node associated with the edge is the AST node for the constructor
+/// that failed to initialize the field (or the class, if the constructor is
+/// synthetic).
+class FieldNotInitializedOrigin extends EdgeOrigin {
+ FieldNotInitializedOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.fieldNotInitialized;
+}
+
/// Edge origin resulting from the use of an iterable type in a for-each loop.
///
/// For example, in the following code snippet:
@@ -170,14 +183,6 @@
EdgeOriginKind get kind => EdgeOriginKind.implicitMixinSuperCall;
}
-/// Edge origin resulting from an inheritance relationship between two methods.
-class InheritanceOrigin extends EdgeOrigin {
- InheritanceOrigin(Source source, AstNode node) : super(source, node);
-
- @override
- EdgeOriginKind get kind => EdgeOriginKind.inheritance;
-}
-
/// Edge origin resulting from a type that is inferred from its initializer.
class InitializerInferenceOrigin extends EdgeOrigin {
InitializerInferenceOrigin(Source source, VariableDeclaration node)
@@ -187,6 +192,15 @@
EdgeOriginKind get kind => EdgeOriginKind.initializerInference;
}
+/// An edge origin used for edges that originated because of an instance
+/// creation expression.
+class InstanceCreationOrigin extends EdgeOrigin {
+ InstanceCreationOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.instanceCreation;
+}
+
/// Edge origin resulting from a class that is instantiated to bounds.
///
/// For example, in the following code snippet:
@@ -229,6 +243,15 @@
EdgeOriginKind get kind => EdgeOriginKind.isCheckMainType;
}
+/// An edge origin used for edges that originated because a literal expression
+/// has a known nullability.
+class LiteralOrigin extends EdgeOrigin {
+ LiteralOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.literal;
+}
+
/// Edge origin resulting from a call site that does not supply a named
/// parameter.
///
@@ -249,6 +272,34 @@
EdgeOriginKind get kind => EdgeOriginKind.namedParameterNotSupplied;
}
+/// Edge origin for the nullability of an expression that whose type is fixed by
+/// the language definition to be non-nullable `bool`.
+class NonNullableBoolTypeOrigin extends EdgeOrigin {
+ NonNullableBoolTypeOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.nonNullableBoolType;
+}
+
+/// Edge origin resulting from the class/superclass relationship for a class
+/// whose superclass is implicitly `Object`.
+class NonNullableObjectSuperclass extends EdgeOrigin {
+ NonNullableObjectSuperclass(Source source, AstNode node)
+ : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.nonNullableObjectSuperclass;
+}
+
+/// Edge origin resulting from the usage of a value in a circumstance that
+/// requires it to be non-nullable
+class NonNullableUsageOrigin extends EdgeOrigin {
+ NonNullableUsageOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.nonNullableUsage;
+}
+
/// Edge origin resulting from the presence of a non-null assertion.
///
/// For example, in the following code snippet:
@@ -295,3 +346,58 @@
@override
EdgeOriginKind get kind => EdgeOriginKind.optionalFormalParameter;
}
+
+/// Edge origin resulting from an inheritance relationship between two method
+/// parameters.
+class ParameterInheritanceOrigin extends EdgeOrigin {
+ ParameterInheritanceOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.parameterInheritance;
+}
+
+/// Edge origin resulting from an inheritance relationship between two method
+/// return types.
+class ReturnTypeInheritanceOrigin extends EdgeOrigin {
+ ReturnTypeInheritanceOrigin(Source source, AstNode node)
+ : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.returnTypeInheritance;
+}
+
+/// Edge origin resulting from the use of a stacktrace parameter in a catch
+/// directive. The type of such parameters is fixed by the language as
+/// non-nullable `StackTrace`.
+class StackTraceTypeOrigin extends EdgeOrigin {
+ StackTraceTypeOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.stackTraceTypeOrigin;
+}
+
+/// Edge origin resulting from the use of `this` or `super`.
+class ThisOrSuperOrigin extends EdgeOrigin {
+ ThisOrSuperOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.thisOrSuper;
+}
+
+/// An edge origin used for edges that originated from the type of a `throw` or
+/// `rethrow`.
+class ThrowOrigin extends EdgeOrigin {
+ ThrowOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.throw_;
+}
+
+/// Edge origin resulting from the read of a variable that has not been
+/// definitely assigned a value.
+class UninitializedReadOrigin extends EdgeOrigin {
+ UninitializedReadOrigin(Source source, AstNode node) : super(source, node);
+
+ @override
+ EdgeOriginKind get kind => EdgeOriginKind.uninitializedRead;
+}
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index b812254..6793265 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -75,7 +75,7 @@
final TypeProvider typeProvider;
/// The type system.
- final Dart2TypeSystem _typeSystem;
+ final TypeSystemImpl _typeSystem;
/// Variables for this migration run.
final Variables _variables;
@@ -98,8 +98,8 @@
FixBuilder(this.source, this._decoratedClassHierarchy,
TypeProvider typeProvider, this._typeSystem, this._variables)
- : typeProvider = (typeProvider as TypeProviderImpl)
- .withNullability(NullabilitySuffix.none);
+ : typeProvider =
+ (typeProvider as TypeProviderImpl).asNonNullableByDefault;
/// Called whenever an AST node is found that needs to be changed.
void addChange(AstNode node, NodeChange change);
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index c0d1938..889e44f 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -63,23 +63,9 @@
final TypeProvider _typeProvider;
- /// For convenience, a [DecoratedType] representing `dynamic`.
- final DecoratedType _dynamicType;
-
- /// For convenience, a [DecoratedType] representing non-nullable `Object`.
- final DecoratedType _nonNullableObjectType;
-
- /// For convenience, a [DecoratedType] representing non-nullable `StackTrace`.
- final DecoratedType _nonNullableStackTraceType;
-
NodeBuilder(this._variables, this.source, this.listener, this._graph,
this._typeProvider,
- {this.instrumentation})
- : _dynamicType = DecoratedType(_typeProvider.dynamicType, _graph.always),
- _nonNullableObjectType =
- DecoratedType(_typeProvider.objectType, _graph.never),
- _nonNullableStackTraceType =
- DecoratedType(_typeProvider.stackTraceType, _graph.never);
+ {this.instrumentation});
@override
DecoratedType visitCatchClause(CatchClause node) {
@@ -87,7 +73,8 @@
if (node.exceptionParameter != null) {
// If there is no `on Type` part of the catch clause, the type is dynamic.
if (exceptionType == null) {
- exceptionType = _dynamicType;
+ exceptionType = DecoratedType.forImplicitType(
+ _typeProvider, _typeProvider.dynamicType, _graph);
instrumentation?.implicitType(
source, node.exceptionParameter, exceptionType);
}
@@ -96,7 +83,11 @@
}
if (node.stackTraceParameter != null) {
// The type of stack traces is always StackTrace (non-nullable).
- var stackTraceType = _nonNullableStackTraceType;
+ var nullabilityNode = NullabilityNode.forInferredType();
+ _graph.makeNonNullable(nullabilityNode,
+ StackTraceTypeOrigin(source, node.stackTraceParameter));
+ var stackTraceType =
+ DecoratedType(_typeProvider.stackTraceType, nullabilityNode);
_variables.recordDecoratedElementType(
node.stackTraceParameter.staticElement, stackTraceType);
instrumentation?.implicitType(
@@ -115,7 +106,7 @@
node.nativeClause?.accept(this);
node.members.accept(this);
var classElement = node.declaredElement;
- _handleSupertypeClauses(classElement, node.extendsClause?.superclass,
+ _handleSupertypeClauses(node, classElement, node.extendsClause?.superclass,
node.withClause, node.implementsClause, null);
var constructors = classElement.constructors;
if (constructors.length == 1) {
@@ -140,8 +131,8 @@
node.name.accept(this);
node.typeParameters?.accept(this);
var classElement = node.declaredElement;
- _handleSupertypeClauses(classElement, node.superclass, node.withClause,
- node.implementsClause, null);
+ _handleSupertypeClauses(node, classElement, node.superclass,
+ node.withClause, node.implementsClause, null);
for (var constructorElement in classElement.constructors) {
assert(constructorElement.isSynthetic);
var decoratedReturnType =
@@ -325,8 +316,8 @@
node.name?.accept(this);
node.typeParameters?.accept(this);
node.members.accept(this);
- _handleSupertypeClauses(
- node.declaredElement, null, null, node.implementsClause, node.onClause);
+ _handleSupertypeClauses(node, node.declaredElement, null, null,
+ node.implementsClause, node.onClause);
return null;
}
@@ -341,8 +332,6 @@
var type = node.type;
if (type.isVoid || type.isDynamic) {
var nullabilityNode = NullabilityNode.forTypeAnnotation(node.end);
- _graph.connect(_graph.always, nullabilityNode,
- AlwaysNullableTypeOrigin(source, node));
var decoratedType = DecoratedType(type, nullabilityNode);
_variables.recordDecoratedTypeAnnotation(
source, node, decoratedType, null);
@@ -431,13 +420,12 @@
var commentToken = node.endToken.next.precedingComments;
switch (_classifyComment(commentToken)) {
case _NullabilityComment.bang:
- _graph.connect(decoratedType.node, _graph.never,
- NullabilityCommentOrigin(source, node),
- hard: true);
+ _graph.makeNonNullable(
+ decoratedType.node, NullabilityCommentOrigin(source, node));
break;
case _NullabilityComment.question:
- _graph.union(_graph.always, decoratedType.node,
- NullabilityCommentOrigin(source, node));
+ _graph.makeNullableUnion(
+ decoratedType.node, NullabilityCommentOrigin(source, node));
break;
case _NullabilityComment.none:
break;
@@ -457,8 +445,6 @@
decoratedBound = bound.accept(this);
} else {
var nullabilityNode = NullabilityNode.forInferredType();
- _graph.union(_graph.always, nullabilityNode,
- AlwaysNullableTypeOrigin(source, node));
decoratedBound = DecoratedType(_typeProvider.objectType, nullabilityNode);
}
_typeFormalBounds?.add(decoratedBound);
@@ -623,6 +609,7 @@
}
void _handleSupertypeClauses(
+ NamedCompilationUnitMember astNode,
ClassElement declaredElement,
TypeName superclass,
WithClause withClause,
@@ -643,7 +630,11 @@
for (var supertype in supertypes) {
DecoratedType decoratedSupertype;
if (supertype == null) {
- decoratedSupertype = _nonNullableObjectType;
+ var nullabilityNode = NullabilityNode.forInferredType();
+ _graph.makeNonNullable(
+ nullabilityNode, NonNullableObjectSuperclass(source, astNode));
+ decoratedSupertype =
+ DecoratedType(_typeProvider.objectType, nullabilityNode);
} else {
decoratedSupertype = supertype.accept(this);
}
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index 0f778dd..40925c4 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -121,30 +121,30 @@
@override
final NullabilityFixDescription description;
- Location _location;
+ List<Location> _locations;
factory _SingleNullabilityFix(Source source,
PotentialModification potentialModification, LineInfo lineInfo) {
- Location location;
+ List<Location> locations = [];
- if (potentialModification.modifications.isNotEmpty) {
- final locationInfo = lineInfo
- .getLocation(potentialModification.modifications.first.offset);
- location = new Location(
+ for (var modification in potentialModification.modifications) {
+ final locationInfo = lineInfo.getLocation(modification.offset);
+ locations.add(new Location(
source.fullName,
- potentialModification.modifications.first.offset,
- potentialModification.modifications.first.length,
+ modification.offset,
+ modification.length,
locationInfo.lineNumber,
locationInfo.columnNumber,
- );
+ ));
}
return _SingleNullabilityFix._(source, potentialModification.description,
- location: location);
+ locations: locations);
}
- _SingleNullabilityFix._(this.source, this.description, {Location location})
- : this._location = location;
+ _SingleNullabilityFix._(this.source, this.description,
+ {List<Location> locations})
+ : this._locations = locations;
- Location get location => _location;
+ List<Location> get locations => _locations;
}
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index 8812789..04db7be 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -160,8 +160,9 @@
/// Creates a graph edge that will try to force the given [node] to be
/// non-nullable.
- void makeNonNullable(NullabilityNode node, EdgeOrigin origin) {
- connect(node, never, origin, hard: true);
+ NullabilityEdge makeNonNullable(NullabilityNode node, EdgeOrigin origin,
+ {bool hard: true, List<NullabilityNode> guards: const []}) {
+ return connect(node, never, origin, hard: hard, guards: guards);
}
/// Creates a graph edge that will try to force the given [node] to be
@@ -171,6 +172,13 @@
connect(always, node, origin, guards: guards);
}
+ /// Creates a `union` graph edge that will try to force the given [node] to be
+ /// nullable. This is a stronger signal than [makeNullable] (it overrides
+ /// [makeNonNullable]).
+ void makeNullableUnion(NullabilityNode node, EdgeOrigin origin) {
+ union(always, node, origin);
+ }
+
/// Record source as code that is being migrated.
void migrating(Source source) {
_sourcesBeingMigrated.add(source);
@@ -360,6 +368,8 @@
for (var edge in node._upstreamEdges) {
pendingEdges.add(edge);
}
+
+ // TODO(mfairhurst): should this propagate back up outerContainerNodes?
}
}
while (pendingEdges.isNotEmpty) {
@@ -460,6 +470,9 @@
/// List of edges that have this node as their destination.
final _upstreamEdges = <NullabilityEdge>[];
+ /// List of compound nodes wrapping this node.
+ final List<NullabilityNode> outerCompoundNodes = <NullabilityNode>[];
+
/// Creates a [NullabilityNode] representing the nullability of a variable
/// whose type comes from an already-migrated library.
factory NullabilityNode.forAlreadyMigrated() =>
@@ -583,7 +596,10 @@
final NullabilityNode right;
- NullabilityNodeForLUB._(this.left, this.right);
+ NullabilityNodeForLUB._(this.left, this.right) {
+ left.outerCompoundNodes.add(this);
+ right.outerCompoundNodes.add(this);
+ }
@override
Iterable<NullabilityNode> get _components => [left, right];
@@ -602,7 +618,10 @@
@override
final NullabilityNode outerNode;
- NullabilityNodeForSubstitution._(this.innerNode, this.outerNode);
+ NullabilityNodeForSubstitution._(this.innerNode, this.outerNode) {
+ innerNode.outerCompoundNodes.add(this);
+ outerNode.outerCompoundNodes.add(this);
+ }
@override
Iterable<NullabilityNode> get _components => [innerNode, outerNode];
@@ -672,14 +691,18 @@
String get debugSuffix => isNullable ? '?' : '';
@override
- bool get isExactNullable => isNullable;
+ // Note: the node "always" is not exact nullable, because exact nullability is
+ // a concept for contravariant generics which propagates upstream instead of
+ // downstream. "always" is not a contravariant generic, and does not have any
+ // upstream nodes, so it should not be considered *exact* nullable.
+ bool get isExactNullable => false;
@override
bool get isImmutable => true;
@override
NullabilityState get _state => isNullable
- ? NullabilityState.exactNullable
+ ? NullabilityState.ordinaryNullable
: NullabilityState.nonNullable;
}
diff --git a/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart b/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
index d8131a2..eaf987b 100644
--- a/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
+++ b/pkg/nnbd_migration/test/already_migrated_code_decorator_test.dart
@@ -39,8 +39,13 @@
Element element = _MockElement();
_AlreadyMigratedCodeDecoratorTestBase(NullabilitySuffix nullabilitySuffix)
- : this._(nullabilitySuffix, NullabilityGraphForTesting(),
- TestTypeProvider(nullabilitySuffix: nullabilitySuffix));
+ : this._(
+ nullabilitySuffix,
+ NullabilityGraphForTesting(),
+ TestTypeProvider(
+ isNonNullableByDefault:
+ nullabilitySuffix == NullabilitySuffix.none),
+ );
_AlreadyMigratedCodeDecoratorTestBase._(
this.suffix, this.graph, this.typeProvider)
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 91a9d171..a2efe64 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -100,7 +100,6 @@
await _checkSingleFileChanges(content, expected);
}
- @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38341')
test_back_propagation_stops_at_implicitly_typed_variables() async {
var content = '''
class C {
@@ -1030,13 +1029,17 @@
await _checkSingleFileChanges(content, expected);
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/39368')
test_downcast_widest_type_from_top_type_parameters() async {
var content = '''
List<int> f1(dynamic a) => a;
List<int> f2(Object b) => b;
''';
+ // Note: even though the type `dynamic` permits `null`, the migration engine
+ // sees that there is no code path that could cause `f1` to be passed a null
+ // value, so it leaves its return type as non-nullable.
var expected = '''
-List<int?>? f1(dynamic a) => a;
+List<int?> f1(dynamic a) => a;
List<int?> f2(Object b) => b;
''';
await _checkSingleFileChanges(content, expected);
@@ -1209,6 +1212,76 @@
await _checkSingleFileChanges(content, expected);
}
+ test_field_initialized_at_declaration_site() async {
+ var content = '''
+class C {
+ int i = 0;
+ C();
+}
+''';
+ var expected = '''
+class C {
+ int i = 0;
+ C();
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ test_field_initialized_at_declaration_site_no_constructor() async {
+ var content = '''
+class C {
+ int i = 0;
+}
+''';
+ var expected = '''
+class C {
+ int i = 0;
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ test_field_initialized_in_constructor() async {
+ var content = '''
+class C {
+ int i;
+ C() : i = 0;
+}
+''';
+ var expected = '''
+class C {
+ int i;
+ C() : i = 0;
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ test_field_initialized_in_constructor_with_factories_and_redirects() async {
+ var content = '''
+class C {
+ int i;
+ C() : i = 0;
+ factory C.factoryConstructor => C();
+ factory C.factoryRedirect = D;
+ C.redirect : this();
+}
+class D extends C {}
+''';
+ var expected = '''
+class C {
+ int i;
+ C() : i = 0;
+ factory C.factoryConstructor => C();
+ factory C.factoryRedirect = D;
+ C.redirect : this();
+}
+class D extends C {}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
test_field_initializer_simple() async {
var content = '''
class C {
@@ -1295,6 +1368,37 @@
await _checkSingleFileChanges(content, expected);
}
+ test_field_not_initialized() async {
+ var content = '''
+class C {
+ int i;
+ C();
+}
+''';
+ var expected = '''
+class C {
+ int? i;
+ C();
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ test_field_not_initialized_no_constructor() async {
+ var content = '''
+class C {
+ int i;
+}
+''';
+ var expected = '''
+class C {
+ int? i;
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/39404')
test_field_type_inferred() async {
var content = '''
int f() => null;
@@ -1305,15 +1409,14 @@
}
}
''';
- // The type of x is inferred from its initializer, so it is non-nullable,
- // even though we try to assign a nullable value to it. So a null check
- // must be added.
+ // The type of x is inferred as non-nullable from its initializer, but we
+ // try to assign a nullable value to it. So an explicit type must be added.
var expected = '''
int? f() => null;
class C {
- var x = 1;
+ int? x = 1;
void g() {
- x = f()!;
+ x = f();
}
}
''';
@@ -1583,11 +1686,15 @@
}
Object g(C c) => c.f()();
''';
+ // Note: even though the type `dynamic` permits `null`, the migration engine
+ // sees that there is no code path that could cause `g` to return a null
+ // value, so it leaves its return type as `Object`, and there is an implicit
+ // downcast.
var expected = '''
abstract class C {
Function() f();
}
-Object? g(C c) => c.f()();
+Object g(C c) => c.f()();
''';
await _checkSingleFileChanges(content, expected);
}
@@ -1657,6 +1764,31 @@
await _checkSingleFileChanges(content, expected);
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/39376')
+ test_infer_required() async {
+ var content = '''
+void _f(bool b, {int x}) {
+ if (b) {
+ print(x + 1);
+ }
+}
+main() {
+ _f(true, x: 1);
+}
+''';
+ var expected = '''
+void _f(bool b, {required int x}) {
+ if (b) {
+ print(x + 1);
+ }
+}
+main() {
+ _f(true, x: 1);
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
test_inferred_method_parameter_type_non_nullable() async {
var content = '''
class B {
@@ -1895,6 +2027,7 @@
await _checkSingleFileChanges(content, expected);
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/39404')
test_localVariable_type_inferred() async {
var content = '''
int f() => null;
@@ -1903,14 +2036,13 @@
x = f();
}
''';
- // The type of x is inferred from its initializer, so it is non-nullable,
- // even though we try to assign a nullable value to it. So a null check
- // must be added.
+ // The type of x is inferred as non-nullable from its initializer, but we
+ // try to assign a nullable value to it. So an explicit type must be added.
var expected = '''
int? f() => null;
void main() {
- var x = 1;
- x = f()!;
+ int? x = 1;
+ x = f();
}
''';
await _checkSingleFileChanges(content, expected);
@@ -2279,7 +2411,6 @@
await _checkSingleFileChanges(content, expected);
}
- @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38344')
test_not_definitely_assigned_value() async {
var content = '''
String f(bool b) {
@@ -2829,12 +2960,16 @@
var content = '''
Object f(x) => x;
''';
+ // Note: even though the type `dynamic` permits `null`, the migration engine
+ // sees that there is no code path that passes a null value to `f`, so it
+ // leaves its return type as `Object`, and there is an implicit downcast.
var expected = '''
-Object? f(x) => x;
+Object f(x) => x;
''';
await _checkSingleFileChanges(content, expected);
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/39369')
test_topLevelFunction_returnType_implicit_dynamic() async {
var content = '''
f() {}
@@ -2847,6 +2982,7 @@
await _checkSingleFileChanges(content, expected);
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/39404')
test_topLevelVariable_type_inferred() async {
var content = '''
int f() => null;
@@ -2855,14 +2991,13 @@
x = f();
}
''';
- // The type of x is inferred from its initializer, so it is non-nullable,
- // even though we try to assign a nullable value to it. So a null check
- // must be added.
+ // The type of x is inferred as non-nullable from its initializer, but we
+ // try to assign a nullable value to it. So an explicit type must be added.
var expected = '''
int? f() => null;
-var x = 1;
+int? x = 1;
void main() {
- x = f()!;
+ x = f();
}
''';
await _checkSingleFileChanges(content, expected);
diff --git a/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart b/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
index 06c8b3c..25a7d20 100644
--- a/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
@@ -219,9 +219,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: true);
+ assertEdge(jNode, inSet(pointsToNever), hard: true);
}
test_binaryExpression_ampersandAmpersand_right() async {
@@ -236,9 +236,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_binaryExpression_barBar_left() async {
@@ -249,9 +249,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: true);
+ assertEdge(jNode, inSet(pointsToNever), hard: true);
}
test_binaryExpression_barBar_right() async {
@@ -266,9 +266,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_booleanLiteral_false() async {
@@ -284,9 +284,9 @@
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never i is known to be non-nullable at the site of
// the call to i.isEven
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_booleanLiteral_true() async {
@@ -302,9 +302,9 @@
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never i is known to be non-nullable at the site of
// the call to i.isEven
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_break_labeled() async {
@@ -458,10 +458,10 @@
var jNode = decoratedTypeAnnotation('int j').node;
var kNode = decoratedTypeAnnotation('int k').node;
// No edge from i to never because i is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there are edges from j and k to never.
- assertEdge(jNode, never, hard: false);
- assertEdge(kNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
+ assertEdge(kNode, inSet(pointsToNever), hard: false);
}
test_constructorDeclaration_assert() async {
@@ -473,9 +473,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: true);
+ assertEdge(jNode, inSet(pointsToNever), hard: true);
}
test_constructorDeclaration_initializer() async {
@@ -489,9 +489,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: true);
+ assertEdge(jNode, inSet(pointsToNever), hard: true);
}
test_constructorDeclaration_redirection() async {
@@ -504,9 +504,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: true);
+ assertEdge(jNode, inSet(pointsToNever), hard: true);
}
test_continue_labeled() async {
@@ -595,9 +595,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never because its promotion was cancelled.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_do_cancels_promotions_for_assignments_in_condition() async {
@@ -612,9 +612,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never because its promotion was cancelled.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_do_continue_target() async {
@@ -740,9 +740,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never because its promotion was cancelled.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_for_cancels_promotions_for_assignments_in_updaters() async {
@@ -759,9 +759,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never because its promotion was cancelled.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_for_collection_cancels_promotions_for_assignments_in_body() async {
@@ -775,9 +775,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never because its promotion was cancelled.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_for_collection_cancels_promotions_for_assignments_in_updaters() async {
@@ -791,9 +791,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never because its promotion was cancelled.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_for_collection_preserves_promotions_for_assignments_in_initializer() async {
@@ -808,9 +808,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because it is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_for_continue_target() async {
@@ -881,9 +881,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never because its promotion was cancelled.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_for_each_collection_assigns_to_declared_var() async {
@@ -922,9 +922,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never because its promotion was cancelled.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_for_each_collection_preserves_promotions_for_assignments_in_iterable() async {
@@ -939,9 +939,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because it is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_for_each_preserves_promotions_for_assignments_in_iterable() async {
@@ -956,9 +956,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because it is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_for_preserves_promotions_for_assignments_in_initializer() async {
@@ -973,9 +973,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because it is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_functionDeclaration() async {
@@ -989,9 +989,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_functionDeclaration_expression_body() async {
@@ -1002,9 +1002,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: true);
+ assertEdge(jNode, inSet(pointsToNever), hard: true);
}
test_functionDeclaration_resets_unconditional_control_flow() async {
@@ -1036,9 +1036,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_if() async {
@@ -1159,9 +1159,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_not() async {
@@ -1302,9 +1302,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_return() async {
@@ -1318,9 +1318,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_switch_break_target() async {
@@ -1403,10 +1403,10 @@
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because the switch statement is guaranteed to
// complete by returning, so i is promoted to non-nullable.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never, because the switch statement is not
// guaranteed to complete by returning, so j is not promoted.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_throw() async {
@@ -1420,9 +1420,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to `never` because i's type is promoted to non-nullable
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to `never`.
- assertEdge(jNode, never, hard: true);
+ assertEdge(jNode, inSet(pointsToNever), hard: true);
}
test_topLevelVar_initializer() async {
@@ -1499,9 +1499,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never because its promotion was cancelled.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_while_cancels_promotions_for_assignments_in_condition() async {
@@ -1516,9 +1516,9 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never because its promotion was cancelled.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
test_while_promotes() async {
@@ -1533,8 +1533,8 @@
var iNode = decoratedTypeAnnotation('int i').node;
var jNode = decoratedTypeAnnotation('int j').node;
// No edge from i to never because is is promoted.
- assertNoEdge(iNode, never);
+ assertNoEdge(iNode, inSet(pointsToNever));
// But there is an edge from j to never.
- assertEdge(jNode, never, hard: false);
+ assertEdge(jNode, inSet(pointsToNever), hard: false);
}
}
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index 9bf66c5..3ccc983 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -48,8 +48,16 @@
var typeProvider = TestTypeProvider();
var graph = NullabilityGraphForTesting();
var decoratedClassHierarchy = _DecoratedClassHierarchyForTesting();
- var checker = AssignmentCheckerForTesting(Dart2TypeSystem(typeProvider),
- typeProvider, graph, decoratedClassHierarchy);
+ var checker = AssignmentCheckerForTesting(
+ TypeSystemImpl(
+ implicitCasts: true,
+ isNonNullableByDefault: false,
+ strictInference: false,
+ typeProvider: typeProvider,
+ ),
+ typeProvider,
+ graph,
+ decoratedClassHierarchy);
var assignmentCheckerTest =
AssignmentCheckerTest._(typeProvider, graph, checker);
decoratedClassHierarchy.assignmentCheckerTest = assignmentCheckerTest;
@@ -97,7 +105,7 @@
var t2 = typeParameterType(typeParameter('T', bound));
assign(t1, t2, hard: true);
assertEdge(t1.node, t2.node, hard: true);
- assertNoEdge(t1.node, bound.node);
+ assertEdge(t1.node, bound.node, hard: false);
assertEdge(t1.typeArguments[0].node, bound.typeArguments[0].node,
hard: false);
}
@@ -457,7 +465,7 @@
var parameterType = decoratedTypeAnnotation('List<int> x');
var tType = decoratedTypeAnnotation('T f');
assertEdge(parameterType.node, tType.node, hard: true);
- assertNoEdge(parameterType.node, boundType.node);
+ assertEdge(parameterType.node, boundType.node, hard: false);
// TODO(mfairhurst): Confirm we want this edge.
assertEdge(
parameterType.typeArguments[0].node, boundType.typeArguments[0].node,
@@ -522,7 +530,7 @@
assertEdge(
substitutionNode(
- decoratedTypeAnnotation('int> x').node, inSet(neverClosure)),
+ decoratedTypeAnnotation('int> x').node, inSet(pointsToNever)),
decoratedTypeAnnotation('int> f').node,
hard: false);
assertNoEdge(decoratedTypeAnnotation('int> x').node,
@@ -600,7 +608,7 @@
var listInt = decoratedTypeAnnotation('List<int>');
assertEdge(listInt.node, iterableInt.node, hard: true);
assertEdge(
- substitutionNode(listInt.typeArguments[0].node, inSet(neverClosure)),
+ substitutionNode(listInt.typeArguments[0].node, inSet(pointsToNever)),
iterableInt.typeArguments[0].node,
hard: false);
}
@@ -622,8 +630,9 @@
C f(C y, C z) => (y += z);
''';
await analyze(code);
- var targetEdge =
- assertEdge(decoratedTypeAnnotation('C y').node, never, hard: true);
+ var targetEdge = assertEdge(
+ decoratedTypeAnnotation('C y').node, inSet(pointsToNever),
+ hard: true);
expect(
(graph.getEdgeOrigin(targetEdge) as CompoundAssignmentOrigin)
.node
@@ -660,8 +669,9 @@
C<int> f(C<int> y, C<int> z) => (y += z);
''';
await analyze(code);
- var targetEdge =
- assertEdge(decoratedTypeAnnotation('C<int> y').node, never, hard: true);
+ var targetEdge = assertEdge(
+ decoratedTypeAnnotation('C<int> y').node, inSet(pointsToNever),
+ hard: true);
expect(
(graph.getEdgeOrigin(targetEdge) as CompoundAssignmentOrigin)
.node
@@ -1041,7 +1051,8 @@
decoratedTypeAnnotation('int z').node,
hard: true);
assertNoEdge(decoratedTypeAnnotation('int g').node, anyNode);
- assertEdge(always, decoratedTypeAnnotation('Object f').node, hard: false);
+ assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('Object f').node,
+ hard: false);
}
test_binaryExpression_lt_result_not_null() async {
@@ -1165,7 +1176,7 @@
assertNullCheck(
checkExpression('j;'),
- assertEdge(decoratedTypeAnnotation('int j').node, inSet(neverClosure),
+ assertEdge(decoratedTypeAnnotation('int j').node, inSet(pointsToNever),
hard: true));
}
@@ -1508,7 +1519,7 @@
var yType = decoratedGenericFunctionTypeAnnotation('void Function() y');
var resultType = decoratedExpressionType('(b ?');
assertLUB(resultType.node, xType.node, yType.node);
- expect(resultType.returnType.node, same(always));
+ expect(resultType.returnType.node.isImmutable, false);
}
test_conditionalExpression_general() async {
@@ -1772,7 +1783,7 @@
''');
var xType =
variables.decoratedElementType(findNode.simple('x').staticElement);
- assertUnion(xType.node, decoratedTypeAnnotation('int').node);
+ assertEdge(decoratedTypeAnnotation('int').node, xType.node, hard: false);
}
test_fieldFormalParameter_function_typed() async {
@@ -1831,7 +1842,7 @@
assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
assertEdge(
substitutionNode(
- decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
+ decoratedTypeAnnotation('int> l').node, inSet(pointsToNever)),
decoratedTypeAnnotation('int i').node,
hard: false);
}
@@ -1850,7 +1861,7 @@
assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
assertEdge(
substitutionNode(
- decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
+ decoratedTypeAnnotation('int> l').node, inSet(pointsToNever)),
iNode,
hard: false);
}
@@ -1865,7 +1876,7 @@
assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
assertEdge(
substitutionNode(
- decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
+ decoratedTypeAnnotation('int> l').node, inSet(pointsToNever)),
decoratedTypeAnnotation('int x').node,
hard: false);
}
@@ -1879,7 +1890,7 @@
assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
assertEdge(
substitutionNode(
- decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
+ decoratedTypeAnnotation('int> l').node, inSet(pointsToNever)),
decoratedTypeAnnotation('int i').node,
hard: false);
}
@@ -1900,7 +1911,7 @@
assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
assertEdge(
substitutionNode(
- decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
+ decoratedTypeAnnotation('int> l').node, inSet(pointsToNever)),
iNode,
hard: false);
}
@@ -1915,7 +1926,7 @@
assertEdge(decoratedTypeAnnotation('List<int>').node, never, hard: true);
assertEdge(
substitutionNode(
- decoratedTypeAnnotation('int> l').node, inSet(neverClosure)),
+ decoratedTypeAnnotation('int> l').node, inSet(pointsToNever)),
decoratedTypeAnnotation('int x').node,
hard: false);
}
@@ -2545,7 +2556,8 @@
''');
// We assume that the index expression might evaluate to anything, including
// `null`.
- assertEdge(always, decoratedTypeAnnotation('int f').node, hard: false);
+ assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int f').node,
+ hard: false);
}
test_indexExpression_index() async {
@@ -2787,21 +2799,24 @@
await analyze('''
int f(dynamic g) => g();
''');
- assertEdge(always, decoratedTypeAnnotation('int f').node, hard: false);
+ assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int f').node,
+ hard: false);
}
test_invocation_dynamic_parenthesized() async {
await analyze('''
int f(dynamic g) => (g)();
''');
- assertEdge(always, decoratedTypeAnnotation('int f').node, hard: false);
+ assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int f').node,
+ hard: false);
}
test_invocation_function() async {
await analyze('''
int f(Function g) => g();
''');
- assertEdge(always, decoratedTypeAnnotation('int f').node, hard: false);
+ assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int f').node,
+ hard: false);
assertNullCheck(
checkExpression('g('),
assertEdge(decoratedTypeAnnotation('Function g').node, never,
@@ -2812,7 +2827,8 @@
await analyze('''
int f(Function g) => (g)();
''');
- assertEdge(always, decoratedTypeAnnotation('int f').node, hard: false);
+ assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int f').node,
+ hard: false);
assertNullCheck(
checkExpression('g)('),
assertEdge(decoratedTypeAnnotation('Function g').node, never,
@@ -2878,7 +2894,7 @@
bool f(a) => a is String;
''');
assertNoUpstreamNullability(decoratedTypeAnnotation('bool').node);
- assertEdge(decoratedTypeAnnotation('String').node, never, hard: false);
+ assertEdge(decoratedTypeAnnotation('String').node, never, hard: true);
}
test_isExpression_typeName_typeArguments() async {
@@ -2886,7 +2902,7 @@
bool f(a) => a is List<int>;
''');
assertNoUpstreamNullability(decoratedTypeAnnotation('bool').node);
- assertEdge(decoratedTypeAnnotation('List').node, never, hard: false);
+ assertEdge(decoratedTypeAnnotation('List').node, never, hard: true);
assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
}
@@ -2973,7 +2989,7 @@
''');
var xType =
variables.decoratedElementType(findNode.simple('x').staticElement);
- assertUnion(xType.node, decoratedTypeAnnotation('int').node);
+ assertEdge(decoratedTypeAnnotation('int').node, xType.node, hard: false);
}
test_method_parameterType_inferred() async {
@@ -3070,7 +3086,8 @@
assertNoEdge(decoratedTypeAnnotation('int g').node,
decoratedTypeAnnotation('int f').node);
// We do, however, assume that it might return anything, including `null`.
- assertEdge(always, decoratedTypeAnnotation('int f').node, hard: false);
+ assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int f').node,
+ hard: false);
}
test_methodInvocation_dynamic_arguments() async {
@@ -3238,7 +3255,7 @@
''');
var nullable_j = decoratedTypeAnnotation('int j');
assertNullCheck(checkExpression('j/*check*/'),
- assertEdge(nullable_j.node, inSet(neverClosure), hard: true));
+ assertEdge(nullable_j.node, inSet(pointsToNever), hard: true));
}
test_methodInvocation_resolves_to_getter() async {
@@ -4415,7 +4432,7 @@
assertNullCheck(check_b, assertEdge(nullable_b, never, hard: true));
var return_f = decoratedTypeAnnotation('bool f').node;
- assertEdge(never, return_f, hard: false);
+ assertEdge(inSet(pointsToNever), return_f, hard: false);
}
test_prefixExpression_bang_dynamic() async {
@@ -4425,7 +4442,7 @@
}
''');
var return_f = decoratedTypeAnnotation('Object f').node;
- assertEdge(never, return_f, hard: false);
+ assertEdge(inSet(pointsToNever), return_f, hard: false);
}
test_prefixExpression_minus() async {
@@ -4446,7 +4463,7 @@
await analyze('''
Object test(dynamic d) => -d;
''');
- assertEdge(always, decoratedTypeAnnotation('Object test').node,
+ assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('Object test').node,
hard: false);
assertEdge(decoratedTypeAnnotation('dynamic d').node, never, hard: true);
}
@@ -4483,7 +4500,7 @@
assertNullCheck(use, assertEdge(declaration, never, hard: true));
var returnType = decoratedTypeAnnotation('int f').node;
- assertEdge(inSet(neverClosure), returnType, hard: false);
+ assertEdge(inSet(pointsToNever), returnType, hard: false);
}
test_prefixExpression_plusPlus() async {
@@ -4498,7 +4515,7 @@
assertNullCheck(use, assertEdge(declaration, never, hard: true));
var returnType = decoratedTypeAnnotation('int f').node;
- assertEdge(inSet(neverClosure), returnType, hard: false);
+ assertEdge(inSet(pointsToNever), returnType, hard: false);
}
test_prefixExpression_plusPlus_dynamic() async {
@@ -4508,7 +4525,7 @@
}
''');
var returnType = decoratedTypeAnnotation('Object f').node;
- assertEdge(always, returnType, hard: false);
+ assertEdge(inSet(alwaysPlus), returnType, hard: false);
}
test_prefixExpression_plusPlus_substituted() async {
@@ -4544,7 +4561,8 @@
assertNoEdge(decoratedTypeAnnotation('int get g').node,
decoratedTypeAnnotation('int f').node);
// We do, however, assume that it might return anything, including `null`.
- assertEdge(always, decoratedTypeAnnotation('int f').node, hard: false);
+ assertEdge(inSet(alwaysPlus), decoratedTypeAnnotation('int f').node,
+ hard: false);
}
test_propertyAccess_object_property() async {
@@ -5199,7 +5217,8 @@
''');
assertEdge(
substitutionNode(
- substitutionNode(never, decoratedTypeAnnotation('T> {').node),
+ substitutionNode(
+ inSet(pointsToNever), decoratedTypeAnnotation('T> {').node),
decoratedTypeAnnotation('U g').node),
decoratedTypeAnnotation('T f').node,
hard: false);
@@ -5248,7 +5267,7 @@
main() { x = 1; }
''');
var setXType = decoratedTypeAnnotation('int value');
- assertEdge(never, setXType.node, hard: false);
+ assertEdge(inSet(pointsToNever), setXType.node, hard: false);
}
test_topLevelSetter_nullable() async {
@@ -5291,7 +5310,7 @@
double get myPi => pi;
''');
var myPiType = decoratedTypeAnnotation('double get');
- assertEdge(inSet(neverClosure), myPiType.node, hard: false);
+ assertEdge(inSet(pointsToNever), myPiType.node, hard: false);
}
test_topLevelVariable_type_inferred() async {
@@ -5301,7 +5320,7 @@
''');
var xType =
variables.decoratedElementType(findNode.simple('x').staticElement);
- assertUnion(xType.node, decoratedTypeAnnotation('int').node);
+ assertEdge(decoratedTypeAnnotation('int').node, xType.node, hard: false);
}
test_type_argument_explicit_bound() async {
@@ -5362,7 +5381,8 @@
import 'dart:async' as a;
Type f() => a.Future;
''');
- assertEdge(never, decoratedTypeAnnotation('Type').node, hard: false);
+ assertEdge(inSet(neverClosure), decoratedTypeAnnotation('Type').node,
+ hard: false);
}
test_typeName_functionTypeAlias() async {
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index 6f1b668..76f7720 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
@@ -31,8 +30,7 @@
DartType get objectType => postMigrationTypeProvider.objectType;
TypeProvider get postMigrationTypeProvider =>
- (typeProvider as TypeProviderImpl)
- .withNullability(NullabilitySuffix.none);
+ (typeProvider as TypeProviderImpl).asNonNullableByDefault;
@override
Future<CompilationUnit> analyze(String code) async {
@@ -2152,12 +2150,8 @@
final Map<AstNode, Set<Problem>> problems = {};
- _FixBuilder(
- Source source,
- DecoratedClassHierarchy decoratedClassHierarchy,
- TypeProvider typeProvider,
- Dart2TypeSystem typeSystem,
- Variables variables)
+ _FixBuilder(Source source, DecoratedClassHierarchy decoratedClassHierarchy,
+ TypeProvider typeProvider, TypeSystemImpl typeSystem, Variables variables)
: super(source, decoratedClassHierarchy, typeProvider, typeSystem,
variables);
diff --git a/pkg/nnbd_migration/test/instrumentation_test.dart b/pkg/nnbd_migration/test/instrumentation_test.dart
index 38bdd97..5c97c1f 100644
--- a/pkg/nnbd_migration/test/instrumentation_test.dart
+++ b/pkg/nnbd_migration/test/instrumentation_test.dart
@@ -215,8 +215,9 @@
}
''');
var yUsage = findNode.simple('y);');
- var entry =
- fixes.entries.where((e) => e.key.location.offset == yUsage.end).single;
+ var entry = fixes.entries
+ .where((e) => e.key.locations.single.offset == yUsage.end)
+ .single;
var reasons = entry.value;
expect(reasons, hasLength(1));
var edge = reasons[0] as EdgeInfo;
@@ -235,7 +236,7 @@
var entries = fixes.entries.toList();
expect(entries, hasLength(1));
var intAnnotation = findNode.typeAnnotation('int');
- expect(entries.single.key.location.offset, intAnnotation.end);
+ expect(entries.single.key.locations.single.offset, intAnnotation.end);
var reasons = entries.single.value;
expect(reasons, hasLength(1));
expect(reasons.single, same(explicitTypeNullability[intAnnotation]));
@@ -562,6 +563,7 @@
hasLength(1));
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/39370')
test_implicitReturnType_functionTypeAlias() async {
await analyze('''
typedef F();
@@ -889,7 +891,7 @@
explicitTypeNullability[findNode.typeAnnotation('String')];
expect(
edges.where((e) =>
- e.sourceNode == never &&
+ _pointsToNeverHard(e.sourceNode) &&
e.destinationNode == implicitMapLiteralKeyNode),
hasLength(1));
expect(
@@ -992,4 +994,9 @@
return edges
.any((e) => e.sourceNode == always && e.destinationNode == node);
}
+
+ bool _pointsToNeverHard(NullabilityNodeInfo node) {
+ return edges.any(
+ (e) => e.sourceNode == node && e.destinationNode == never && e.isHard);
+ }
}
diff --git a/pkg/nnbd_migration/test/migration_visitor_test_base.dart b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
index c62a340..afee88d 100644
--- a/pkg/nnbd_migration/test/migration_visitor_test_base.dart
+++ b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
@@ -180,6 +180,11 @@
return result;
}
+ /// Gets the set of nodes with hard edges pointing to never.
+ Set<NullabilityNode> get pointsToNever {
+ return {for (var edge in getEdges(anyNode, graph.never)) edge.sourceNode};
+ }
+
/// Asserts that an edge exists with a node matching [source] and a node
/// matching [destination], and with the given [hard]ness and [guards].
///
@@ -344,8 +349,8 @@
TypeProvider get typeProvider => testAnalysisResult.typeProvider;
- Dart2TypeSystem get typeSystem =>
- testAnalysisResult.typeSystem as Dart2TypeSystem;
+ TypeSystemImpl get typeSystem =>
+ testAnalysisResult.typeSystem as TypeSystemImpl;
Future<CompilationUnit> analyze(String code) async {
await resolveTestUnit(code);
diff --git a/pkg/nnbd_migration/test/node_builder_test.dart b/pkg/nnbd_migration/test/node_builder_test.dart
index 963d3cf..708c1f6 100644
--- a/pkg/nnbd_migration/test/node_builder_test.dart
+++ b/pkg/nnbd_migration/test/node_builder_test.dart
@@ -39,7 +39,7 @@
expect(exceptionType.node, TypeMatcher<NullabilityNodeMutable>());
var stackTraceType =
variables.decoratedElementType(findNode.simple('st').staticElement);
- expect(stackTraceType.node, never);
+ assertEdge(stackTraceType.node, never, hard: true);
}
test_catch_clause_with_stacktrace_without_on() async {
@@ -50,10 +50,10 @@
''');
var exceptionType =
variables.decoratedElementType(findNode.simple('ex').staticElement);
- expect(exceptionType.node, always);
+ expect(exceptionType.node.isImmutable, false);
var stackTraceType =
variables.decoratedElementType(findNode.simple('st').staticElement);
- expect(stackTraceType.node, never);
+ assertEdge(stackTraceType.node, never, hard: true);
}
test_catch_clause_without_catch() async {
@@ -85,7 +85,7 @@
''');
var exceptionType =
variables.decoratedElementType(findNode.simple('ex').staticElement);
- expect(exceptionType.node, always);
+ expect(exceptionType.node.isImmutable, false);
}
test_class_alias_synthetic_constructors_no_parameters() async {
@@ -312,7 +312,7 @@
var types = decoratedDirectSupertypes('C');
var decorated = types[typeProvider.objectType.element];
expect(decorated.type.toString(), 'Object');
- expect(decorated.node, same(never));
+ assertEdge(decorated.node, never, hard: true);
expect(decorated.typeArguments, isEmpty);
}
@@ -418,7 +418,7 @@
var types = decoratedDirectSupertypes('C');
var decorated = types[typeProvider.objectType.element];
expect(decorated.type.toString(), 'Object');
- expect(decorated.node, same(never));
+ assertEdge(decorated.node, never, hard: true);
expect(decorated.typeArguments, isEmpty);
}
@@ -460,7 +460,7 @@
''');
var decoratedType = decoratedTypeAnnotation('dynamic');
expect(decoratedFunctionType('f').returnType, same(decoratedType));
- assertEdge(always, decoratedType.node, hard: false);
+ assertNoEdge(always, decoratedType.node);
}
test_field_type_implicit_dynamic() async {
@@ -471,7 +471,7 @@
''');
var decoratedType =
variables.decoratedElementType(findNode.simple('x').staticElement);
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_field_type_inferred() async {
@@ -494,7 +494,7 @@
''');
var decoratedType =
variables.decoratedElementType(findNode.simple('x').staticElement);
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_field_type_simple() async {
@@ -542,7 +542,7 @@
expect(ctorType.positionalParameters[0], same(ctorParamType));
expect(ctorParamType.node, TypeMatcher<NullabilityNodeMutable>());
expect(ctorParamType.namedParameters['i'].type.toString(), 'dynamic');
- expect(ctorParamType.namedParameters['i'].node, same(always));
+ expect(ctorParamType.namedParameters['i'].node.isImmutable, false);
}
test_fieldFormalParameter_function_positionalParameter_typed() async {
@@ -576,7 +576,7 @@
expect(ctorType.positionalParameters[0], same(ctorParamType));
expect(ctorParamType.node, TypeMatcher<NullabilityNodeMutable>());
expect(ctorParamType.positionalParameters[0].type.toString(), 'dynamic');
- expect(ctorParamType.positionalParameters[0].node, same(always));
+ expect(ctorParamType.positionalParameters[0].node.isImmutable, false);
}
test_fieldFormalParameter_function_return_typed() async {
@@ -609,7 +609,7 @@
expect(ctorType.positionalParameters[0], same(ctorParamType));
expect(ctorParamType.node, TypeMatcher<NullabilityNodeMutable>());
expect(ctorParamType.returnType.type.toString(), 'dynamic');
- expect(ctorParamType.returnType.node, same(always));
+ expect(ctorParamType.returnType.node.isImmutable, false);
}
test_fieldFormalParameter_typed() async {
@@ -665,7 +665,7 @@
var decoratedType = decoratedFunctionType('f');
var bound = decoratedTypeParameterBound('T>');
expect(decoratedType.typeFormalBounds[0], same(bound));
- assertUnion(always, bound.node);
+ assertNoEdge(always, bound.node);
expect(bound.type, same(typeProvider.objectType));
}
@@ -717,7 +717,7 @@
await analyze('''
typedef T F<T, U>(U u);
''');
- var element = findElement.genericTypeAlias('F');
+ var element = findElement.functionTypeAlias('F');
var decoratedType = variables.decoratedElementType(element);
var t = element.typeParameters[0];
var u = element.typeParameters[1];
@@ -743,9 +743,9 @@
typedef F();
''');
var decoratedType =
- variables.decoratedElementType(findElement.genericTypeAlias('F'));
+ variables.decoratedElementType(findElement.functionTypeAlias('F'));
expect(decoratedType.returnType.type.isDynamic, isTrue);
- expect(decoratedType.returnType.node, same(always));
+ expect(decoratedType.returnType.node.isImmutable, false);
expect(decoratedType.typeFormals, isEmpty);
}
@@ -754,7 +754,7 @@
typedef int F(String s);
''');
var decoratedType =
- variables.decoratedElementType(findElement.genericTypeAlias('F'));
+ variables.decoratedElementType(findElement.functionTypeAlias('F'));
expect(decoratedType.returnType, same(decoratedTypeAnnotation('int')));
expect(decoratedType.typeFormals, isEmpty);
expect(decoratedType.positionalParameters[0],
@@ -785,7 +785,7 @@
expect(fType.positionalParameters[0], same(gType));
expect(gType.node, TypeMatcher<NullabilityNodeMutable>());
expect(gType.namedParameters['i'].type.toString(), 'dynamic');
- expect(gType.namedParameters['i'].node, same(always));
+ expect(gType.namedParameters['i'].node.isImmutable, false);
}
test_functionTypedFormalParameter_positionalParameter_typed() async {
@@ -812,7 +812,7 @@
expect(fType.positionalParameters[0], same(gType));
expect(gType.node, TypeMatcher<NullabilityNodeMutable>());
expect(gType.positionalParameters[0].type.toString(), 'dynamic');
- expect(gType.positionalParameters[0].node, same(always));
+ expect(gType.positionalParameters[0].node.isImmutable, false);
}
test_functionTypedFormalParameter_return_typed() async {
@@ -839,7 +839,7 @@
expect(fType.positionalParameters[0], same(gType));
expect(gType.node, TypeMatcher<NullabilityNodeMutable>());
expect(gType.returnType.type.toString(), 'dynamic');
- expect(gType.returnType.node, same(always));
+ expect(gType.returnType.node.isImmutable, false);
}
test_generic_function_type_syntax_inferred_dynamic_return() async {
@@ -852,7 +852,7 @@
var decoratedFReturnType = decoratedFType.returnType;
var decoratedFReturnReturnType = decoratedFReturnType.returnType;
expect(decoratedFReturnReturnType.type.toString(), 'dynamic');
- expect(decoratedFReturnReturnType.node, same(always));
+ expect(decoratedFReturnReturnType.node.isImmutable, false);
}
test_genericFunctionType_formal_bounds() async {
@@ -932,7 +932,7 @@
await analyze('''
typedef F = T Function<T, U>(U u);
''');
- var element = findElement.genericTypeAlias('F');
+ var element = findElement.functionTypeAlias('F');
var decoratedType = variables.decoratedElementType(element);
expect(decoratedType,
same(decoratedGenericFunctionTypeAnnotation('T Function')));
@@ -956,7 +956,7 @@
await analyze('''
typedef F<T, U> = T Function(U u);
''');
- var element = findElement.genericTypeAlias('F');
+ var element = findElement.functionTypeAlias('F');
var decoratedType = variables.decoratedElementType(element);
expect(decoratedType,
same(decoratedGenericFunctionTypeAnnotation('T Function')));
@@ -984,11 +984,11 @@
typedef F = Function();
''');
var decoratedType =
- variables.decoratedElementType(findElement.genericTypeAlias('F'));
+ variables.decoratedElementType(findElement.functionTypeAlias('F'));
expect(decoratedType,
same(decoratedGenericFunctionTypeAnnotation('Function')));
expect(decoratedType.returnType.type.isDynamic, isTrue);
- expect(decoratedType.returnType.node, same(always));
+ expect(decoratedType.returnType.node.isImmutable, false);
expect(decoratedType.typeFormals, isEmpty);
}
@@ -997,7 +997,7 @@
typedef F = int Function(String s);
''');
var decoratedType =
- variables.decoratedElementType(findElement.genericTypeAlias('F'));
+ variables.decoratedElementType(findElement.functionTypeAlias('F'));
expect(decoratedType,
same(decoratedGenericFunctionTypeAnnotation('int Function')));
expect(decoratedType.returnType, same(decoratedTypeAnnotation('int')));
@@ -1016,7 +1016,7 @@
expect(decoratedListType.node, isNotNull);
expect(decoratedListType.node, isNot(never));
var decoratedArgType = decoratedListType.typeArguments[0];
- expect(decoratedArgType.node, same(always));
+ expect(decoratedArgType.node.isImmutable, false);
}
test_interfaceType_generic_instantiate_to_function_type() async {
@@ -1051,7 +1051,7 @@
expect(decoratedArgType.node, TypeMatcher<NullabilityNodeMutable>());
expect(decoratedArgType.typeArguments, isEmpty);
var decoratedArgReturnType = decoratedArgType.returnType;
- expect(decoratedArgReturnType.node, same(always));
+ expect(decoratedArgReturnType.node.isImmutable, false);
expect(decoratedArgReturnType.typeArguments, isEmpty);
}
@@ -1156,7 +1156,7 @@
''');
var decoratedType =
variables.decoratedElementType(findNode.simple('x').staticElement);
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_localVariable_type_inferred() async {
@@ -1179,7 +1179,7 @@
''');
var decoratedType =
variables.decoratedElementType(findNode.simple('x').staticElement);
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_method_generic_bounded() async {
@@ -1205,7 +1205,7 @@
var decoratedType = decoratedMethodType('f');
var bound = decoratedTypeParameterBound('T>');
expect(decoratedType.typeFormalBounds[0], same(bound));
- assertUnion(always, bound.node);
+ assertNoEdge(always, bound.node);
expect(bound.type, same(typeProvider.objectType));
}
@@ -1231,7 +1231,7 @@
}
''');
var decoratedType = decoratedMethodType('f').positionalParameters[0];
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_method_parameterType_implicit_dynamic_named() async {
@@ -1241,7 +1241,7 @@
}
''');
var decoratedType = decoratedMethodType('f').namedParameters['x'];
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_method_parameterType_inferred() async {
@@ -1267,7 +1267,7 @@
}
''');
var decoratedType = decoratedMethodType('f/*C*/').positionalParameters[0];
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_method_parameterType_inferred_dynamic_named() async {
@@ -1280,7 +1280,7 @@
}
''');
var decoratedType = decoratedMethodType('f/*C*/').namedParameters['x'];
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_method_parameterType_inferred_generic_function_typed_no_bound() async {
@@ -1339,7 +1339,7 @@
}
''');
var decoratedType = decoratedMethodType('f').returnType;
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_method_returnType_inferred() async {
@@ -1365,7 +1365,7 @@
}
''');
var decoratedType = decoratedMethodType('f/*C*/').returnType;
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_parameters() async {
@@ -1474,7 +1474,7 @@
''');
var decoratedType =
variables.decoratedElementType(findNode.simple('x').staticElement);
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_topLevelVariable_type_inferred() async {
@@ -1493,7 +1493,7 @@
''');
var decoratedType =
variables.decoratedElementType(findNode.simple('x').staticElement);
- expect(decoratedType.node, same(always));
+ expect(decoratedType.node.isImmutable, false);
}
test_type_comment_bang() async {
@@ -1528,7 +1528,7 @@
class C<T> {}
''');
var bound = decoratedTypeParameterBound('T');
- assertUnion(always, bound.node);
+ assertNoEdge(always, bound.node);
expect(bound.type, same(typeProvider.objectType));
}
@@ -1542,7 +1542,7 @@
// This is necessary because there is no guarantee of whether the typedef or
// its usage will be visited first.
var typedefDecoratedType =
- variables.decoratedElementType(findElement.genericTypeAlias('F'));
+ variables.decoratedElementType(findElement.functionTypeAlias('F'));
var decoratedType = decoratedTypeAnnotation('F<int>');
expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
expect(decoratedType.node, isNot(same(typedefDecoratedType.node)));
@@ -1564,7 +1564,7 @@
// This is necessary because there is no guarantee of whether the typedef or
// its usage will be visited first.
var typedefDecoratedType =
- variables.decoratedElementType(findElement.genericTypeAlias('F'));
+ variables.decoratedElementType(findElement.functionTypeAlias('F'));
var decoratedType = decoratedTypeAnnotation('F f');
expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
expect(decoratedType.node, isNot(same(typedefDecoratedType.node)));
@@ -1589,7 +1589,7 @@
// This is necessary because there is no guarantee of whether the typedef or
// its usage will be visited first.
var typedefDecoratedType =
- variables.decoratedElementType(findElement.genericTypeAlias('F'));
+ variables.decoratedElementType(findElement.functionTypeAlias('F'));
var decoratedType = decoratedTypeAnnotation('F f');
expect(decoratedType.node, TypeMatcher<NullabilityNodeMutable>());
expect(decoratedType.node, isNot(same(typedefDecoratedType.node)));
@@ -1633,6 +1633,6 @@
''');
var decoratedType = decoratedTypeAnnotation('void');
expect(decoratedFunctionType('f').returnType, same(decoratedType));
- assertEdge(always, decoratedType.node, hard: false);
+ assertNoEdge(always, decoratedType.node);
}
}
diff --git a/pkg/nnbd_migration/test/nullability_migration_impl_test.dart b/pkg/nnbd_migration/test/nullability_migration_impl_test.dart
index 1ba7901..078cad0 100644
--- a/pkg/nnbd_migration/test/nullability_migration_impl_test.dart
+++ b/pkg/nnbd_migration/test/nullability_migration_impl_test.dart
@@ -32,7 +32,8 @@
final text = 'void f() {}\nint g() => null;';
final offset = text.indexOf('int') + 3;
final potentialModification = _PotentialModificationMock(
- _NullabilityFixDescriptionMock('Add ?'),
+ _NullabilityFixDescriptionMock(
+ 'Add ?', NullabilityFixKind.makeTypeNullable),
false,
[SourceEdit(offset, 0, '?')]);
final listener = NullabilityMigrationListenerMock();
@@ -47,11 +48,12 @@
as SingleNullabilityFix;
expect(fix.description.appliedMessage, 'Add ?');
expect(fix.source, source);
- expect(fix.location.offset, offset);
- expect(fix.location.length, 0);
- expect(fix.location.file, '/test.dart');
- expect(fix.location.startLine, 2);
- expect(fix.location.startColumn, 4);
+ Location location = fix.locations.single;
+ expect(location.offset, offset);
+ expect(location.length, 0);
+ expect(location.file, '/test.dart');
+ expect(location.startLine, 2);
+ expect(location.startColumn, 4);
verifyNever(listener.reportException(any, any, any, any));
final edit =
verify(listener.addEdit(fix, captureAny)).captured.single as SourceEdit;
@@ -61,8 +63,9 @@
}
void test_noModifications_notReported() {
- final potentialModification =
- _PotentialModificationMock.empty(_NullabilityFixDescriptionMock('foo'));
+ final potentialModification = _PotentialModificationMock.empty(
+ _NullabilityFixDescriptionMock(
+ 'foo', NullabilityFixKind.noModification));
final listener = NullabilityMigrationListenerMock();
final source = SourceMock('');
when(variables.getPotentialModifications()).thenReturn({
@@ -105,8 +108,10 @@
class _NullabilityFixDescriptionMock implements NullabilityFixDescription {
@override
final String appliedMessage;
+ @override
+ final NullabilityFixKind kind;
- _NullabilityFixDescriptionMock(this.appliedMessage);
+ _NullabilityFixDescriptionMock(this.appliedMessage, this.kind);
}
class _PotentialModificationMock extends PotentialModification {
diff --git a/pkg/nnbd_migration/test/nullability_node_test.dart b/pkg/nnbd_migration/test/nullability_node_test.dart
index e256963e..9f45acc 100644
--- a/pkg/nnbd_migration/test/nullability_node_test.dart
+++ b/pkg/nnbd_migration/test/nullability_node_test.dart
@@ -106,6 +106,15 @@
assertUnsatisfied([]);
}
+ test_lubNode_relatesInBothDirections() {
+ final nodeA = newNode(1);
+ final nodeB = newNode(2);
+ final lubNode = lub(nodeA, nodeB);
+
+ expect(nodeA.outerCompoundNodes, [lubNode]);
+ expect(nodeB.outerCompoundNodes, [lubNode]);
+ }
+
test_never_source() {
// never -> 1
var n1 = newNode(1);
@@ -600,6 +609,15 @@
expect(subst(n1, null), same(n1));
}
+ test_substitutionNode_relatesInBothDirections() {
+ final nodeA = newNode(1);
+ final nodeB = newNode(2);
+ final substNode = subst(nodeA, nodeB);
+
+ expect(nodeA.outerCompoundNodes, [substNode]);
+ expect(nodeB.outerCompoundNodes, [substNode]);
+ }
+
test_unconstrainted_node_non_nullable() {
var n1 = newNode(1);
propagate();
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 0769ac3..29fa5d7 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -220,6 +220,9 @@
[ $arch != x64 || $compiler != none || $mode != release || $runtime != vm ]
front_end/test/whole_program_test: SkipByDesign
+[ $mode == debug || $runtime != vm || $system == android ]
+vm/test/modular_kernel_plus_aot_test: SkipByDesign # This test should only run if binary is run from build dir
+
[ $mode != release || $runtime != vm ]
front_end/test/fasta/*: Skip
front_end/tool/_fasta/*: Skip
diff --git a/pkg/telemetry/lib/crash_reporting.dart b/pkg/telemetry/lib/crash_reporting.dart
index 415950c..285e5ac 100644
--- a/pkg/telemetry/lib/crash_reporting.dart
+++ b/pkg/telemetry/lib/crash_reporting.dart
@@ -16,8 +16,9 @@
/// Crash backend host.
const String _crashServerHost = 'clients2.google.com';
+// This should be one of 'report' or 'staging_report'.
/// Path to the crash servlet.
-const String _crashEndpointPath = '/cr/report'; // or, 'staging_report'
+const String _crashEndpointPath = '/cr/staging_report';
/// The field corresponding to the multipart/form-data file attachment where
/// crash backend expects to find the Dart stack trace.
diff --git a/pkg/test_runner/lib/src/command.dart b/pkg/test_runner/lib/src/command.dart
index bcf4024..8127e35 100644
--- a/pkg/test_runner/lib/src/command.dart
+++ b/pkg/test_runner/lib/src/command.dart
@@ -388,28 +388,25 @@
Runtime get browser => configuration.runtime;
final String url;
final TestConfiguration configuration;
- final bool retry;
- BrowserTestCommand(this.url, this.configuration, {this.retry, int index = 0})
+ BrowserTestCommand(this.url, this.configuration, {int index = 0})
: super._(configuration.runtime.name, index: index);
BrowserTestCommand indexedCopy(int index) =>
- BrowserTestCommand(url, configuration, retry: retry, index: index);
+ BrowserTestCommand(url, configuration, index: index);
void _buildHashCode(HashCodeBuilder builder) {
super._buildHashCode(builder);
builder.addJson(browser.name);
builder.addJson(url);
builder.add(configuration);
- builder.add(retry);
}
bool _equal(BrowserTestCommand other) =>
super._equal(other) &&
browser == other.browser &&
url == other.url &&
- identical(configuration, other.configuration) &&
- retry == other.retry;
+ identical(configuration, other.configuration);
String get reproductionCommand {
var parts = [
diff --git a/pkg/test_runner/lib/src/command_output.dart b/pkg/test_runner/lib/src/command_output.dart
index 9898e75..5f98e9e 100644
--- a/pkg/test_runner/lib/src/command_output.dart
+++ b/pkg/test_runner/lib/src/command_output.dart
@@ -47,7 +47,7 @@
Expectation result(TestCase testCase) {
if (hasCrashed) return Expectation.crash;
if (hasTimedOut) return Expectation.timeout;
- if (hasFailed(testCase)) return Expectation.fail;
+ if (_didFail(testCase)) return Expectation.fail;
if (hasNonUtf8) return Expectation.nonUtf8Error;
return Expectation.pass;
@@ -111,23 +111,8 @@
return !hasTimedOut && exitCode == 0;
}
- // Reverse result of a negative test.
- bool hasFailed(TestCase testCase) {
- return testCase.isNegative ? !_didFail(testCase) : _didFail(testCase);
- }
-
bool get hasNonUtf8 => exitCode == nonUtfFakeExitCode;
- Expectation _negateOutcomeIfNegativeTest(
- Expectation outcome, bool isNegative) {
- if (!isNegative) return outcome;
- if (outcome == Expectation.ignore) return outcome;
- if (outcome.canBeOutcomeOf(Expectation.fail)) {
- return Expectation.pass;
- }
- return Expectation.fail;
- }
-
/// Called when producing output for a test failure to describe this output.
void describe(TestCase testCase, Progress progress, OutputWriter output) {
output.subsection("exit code");
@@ -282,7 +267,7 @@
with _UnittestSuiteMessagesMixin {
final BrowserTestJsonResult _jsonResult;
final BrowserTestOutput _result;
- final Expectation _rawOutcome;
+ final Expectation _outcome;
factory BrowserCommandOutput(Command command, BrowserTestOutput result) {
Expectation outcome;
@@ -317,7 +302,7 @@
}
BrowserCommandOutput._internal(Command command, BrowserTestOutput result,
- this._rawOutcome, this._jsonResult, List<int> stdout, List<int> stderr)
+ this._outcome, this._jsonResult, List<int> stdout, List<int> stderr)
: _result = result,
super(command, 0, result.didTimeout, stdout, stderr, result.duration,
false, 0);
@@ -332,11 +317,11 @@
// Multitests are handled specially.
if (testCase.hasRuntimeError) {
- if (_rawOutcome == Expectation.runtimeError) return Expectation.pass;
+ if (_outcome == Expectation.runtimeError) return Expectation.pass;
return Expectation.missingRuntimeError;
}
- return _negateOutcomeIfNegativeTest(_rawOutcome, testCase.isNegative);
+ return _outcome;
}
/// Cloned code from member result(), with changes.
@@ -348,7 +333,7 @@
}
if (hasNonUtf8) return Expectation.nonUtf8Error;
- return _rawOutcome;
+ return _outcome;
}
void describe(TestCase testCase, Progress progress, OutputWriter output) {
@@ -509,13 +494,6 @@
return _validateExpectedErrors(testCase);
}
- // Handle negative.
- if (testCase.isNegative) {
- return errors.isNotEmpty
- ? Expectation.pass
- : Expectation.missingCompileTimeError;
- }
-
// Handle errors / missing errors.
if (testCase.hasCompileError) {
if (errors.isNotEmpty) {
@@ -727,8 +705,7 @@
outcome = Expectation.fail;
}
- outcome = _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout));
- return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
+ return _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout));
}
/// Cloned code from member result(), with changes.
@@ -835,9 +812,7 @@
return Expectation.compileTimeError;
}
- var outcome =
- exitCode == 0 ? Expectation.pass : Expectation.compileTimeError;
- return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
+ return exitCode == 0 ? Expectation.pass : Expectation.compileTimeError;
}
}
@@ -866,9 +841,7 @@
: Expectation.pass;
}
- var outcome =
- exitCode == 0 ? Expectation.pass : Expectation.compileTimeError;
- return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
+ return exitCode == 0 ? Expectation.pass : Expectation.compileTimeError;
}
/// Cloned code from member result(), with changes.
@@ -930,16 +903,15 @@
}
// The actual outcome depends on the exitCode.
- var outcome = Expectation.pass;
if (exitCode == VMCommandOutput._compileErrorExitCode ||
exitCode == kBatchModeCompileTimeErrorExit) {
- outcome = Expectation.compileTimeError;
+ return Expectation.compileTimeError;
} else if (exitCode != 0) {
// This is a general fail, in case we get an unknown nonzero exitcode.
- outcome = Expectation.fail;
+ return Expectation.fail;
}
- return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
+ return Expectation.pass;
}
/// Cloned code from member result(), with changes.
@@ -1003,8 +975,7 @@
}
var outcome = exitCode == 0 ? Expectation.pass : Expectation.runtimeError;
- outcome = _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout));
- return _negateOutcomeIfNegativeTest(outcome, testCase.isNegative);
+ return _negateOutcomeIfIncompleteAsyncTest(outcome, decodeUtf8(stdout));
}
/// Cloned code from member result(), with changes.
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index 01389c4..b575952 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -51,8 +51,6 @@
bool get _isDebug => _configuration.mode.isDebug;
- bool get _isProduct => _configuration.mode == Mode.product;
-
bool get _isHostChecked => _configuration.isHostChecked;
bool get _useSdk => _configuration.useSdk;
@@ -1051,8 +1049,6 @@
bool get _useSdk;
- bool get _isProduct;
-
bool get _isAot;
bool get _enableAsserts;
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index ce68eba..1dfea78 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -330,7 +330,7 @@
'''
Skip the compilation step, using the compilation artifacts left in
the output folder from a previous run. This flag will often cause
-false positves and negatives, but can be useful for quick and
+false positives and negatives, but can be useful for quick and
dirty offline testing when not making changes that affect the
compiler.''',
hide: true),
diff --git a/pkg/test_runner/lib/src/runtime_configuration.dart b/pkg/test_runner/lib/src/runtime_configuration.dart
index 5a2b45b..f21d1d5 100644
--- a/pkg/test_runner/lib/src/runtime_configuration.dart
+++ b/pkg/test_runner/lib/src/runtime_configuration.dart
@@ -94,8 +94,6 @@
List<String> dart2jsPreambles(Uri preambleDir) => [];
- bool get shouldSkipNegativeTests => false;
-
/// Returns the path to the Dart VM executable.
///
/// Controlled by user with the option "--dart".
@@ -389,9 +387,6 @@
checked: _configuration.isChecked))
.toList();
}
-
- @override
- bool get shouldSkipNegativeTests => true;
}
/// Temporary runtime configuration for browser runtimes that haven't been
diff --git a/pkg/test_runner/lib/src/test_case.dart b/pkg/test_runner/lib/src/test_case.dart
index b317545..7ff1410 100644
--- a/pkg/test_runner/lib/src/test_case.dart
+++ b/pkg/test_runner/lib/src/test_case.dart
@@ -75,10 +75,6 @@
bool get hasSyntaxError => testFile?.hasSyntaxError ?? false;
bool get hasCompileError => testFile?.hasCompileError ?? false;
bool get hasCrash => testFile?.hasCrash ?? false;
- bool get isNegative =>
- hasCompileError ||
- hasRuntimeError && configuration.runtime != Runtime.none ||
- displayName.contains("negative_test");
bool get unexpectedOutput {
var outcome = result;
@@ -109,9 +105,6 @@
}
return Expectation.pass;
}
- if (displayName.contains("negative_test")) {
- return Expectation.fail;
- }
if (configuration.compiler == Compiler.dart2analyzer && hasStaticWarning) {
return Expectation.staticWarning;
}
diff --git a/pkg/test_runner/lib/src/test_configurations.dart b/pkg/test_runner/lib/src/test_configurations.dart
index be93c90..5b957cd 100644
--- a/pkg/test_runner/lib/src/test_configurations.dart
+++ b/pkg/test_runner/lib/src/test_configurations.dart
@@ -34,10 +34,14 @@
Path('tests/compiler/dart2js_extra'),
Path('tests/compiler/dart2js_native'),
Path('tests/compiler/dartdevc_native'),
+ Path('tests/corelib'),
Path('tests/corelib_2'),
Path('tests/kernel'),
+ Path('tests/language'),
Path('tests/language_2'),
+ Path('tests/lib'),
Path('tests/lib_2'),
+ Path('tests/standalone'),
Path('tests/standalone_2'),
Path('tests/ffi'),
Path('utils/tests/peg'),
@@ -125,7 +129,7 @@
}
for (var key in configuration.selectors.keys) {
- if (key == 'co19_2') {
+ if (key == 'co19_2' || key == 'co19') {
testSuites.add(Co19TestSuite(configuration, key));
} else if ((configuration.compiler == Compiler.none ||
configuration.compiler == Compiler.dartk ||
diff --git a/pkg/test_runner/lib/src/test_progress.dart b/pkg/test_runner/lib/src/test_progress.dart
index 6461397..c2b3d5e 100644
--- a/pkg/test_runner/lib/src/test_progress.dart
+++ b/pkg/test_runner/lib/src/test_progress.dart
@@ -255,7 +255,6 @@
class StatusFileUpdatePrinter extends EventListener {
final Map<String, List<String>> statusToConfigs = {};
- final List<String> _failureSummary = [];
void done(TestCase test) {
if (test.unexpectedOutput) {
@@ -391,7 +390,6 @@
class PassingStdoutPrinter extends EventListener {
final Formatter _formatter;
- final _failureSummary = <String>[];
PassingStdoutPrinter([this._formatter = Formatter.normal]);
diff --git a/pkg/test_runner/lib/src/test_suite.dart b/pkg/test_runner/lib/src/test_suite.dart
index 31b7f32..5f92c54 100644
--- a/pkg/test_runner/lib/src/test_suite.dart
+++ b/pkg/test_runner/lib/src/test_suite.dart
@@ -147,7 +147,8 @@
// So, for now, until we have figured out how to manage those tests, we
// implicitly skip any test that does not require NNBD if run in a
// configuration that enables the NNBD experiment.
- if (configuration.experiments.contains("non-nullable") &&
+ if (testFile.path.toString().contains("language_2") &&
+ configuration.experiments.contains("non-nullable") &&
!(testFile.requirements.contains(Feature.nnbd) ||
testFile.requirements.contains(Feature.nnbdWeak) ||
testFile.requirements.contains(Feature.nnbdStrong))) {
@@ -165,11 +166,6 @@
return false;
}
- if (isNegative(testFile) &&
- configuration.runtimeConfiguration.shouldSkipNegativeTests) {
- return false;
- }
-
// Handle sharding based on the original test path. All multitests of a
// given original test belong to the same shard.
if (configuration.shardCount > 1 &&
@@ -211,10 +207,6 @@
return false;
}
- bool isNegative(TestFile testFile) =>
- testFile.hasCompileError ||
- testFile.hasRuntimeError && configuration.runtime != Runtime.none;
-
String createGeneratedTestDirectoryHelper(
String name, String dirname, Path testPath) {
Path relative = testPath.relativeTo(Repository.dir);
@@ -879,8 +871,7 @@
var htmlPathSubtest = _createUrlPathFromFile(Path(htmlPath));
var fullHtmlPath = _uriForBrowserTest(htmlPathSubtest, subtestName);
- commands.add(BrowserTestCommand(fullHtmlPath, configuration,
- retry: !isNegative(testFile)));
+ commands.add(BrowserTestCommand(fullHtmlPath, configuration));
var fullName = testName;
if (subtestName != null) fullName += "/$subtestName";
@@ -970,8 +961,7 @@
super._enqueueBrowserTest(testFile, expectations, onTest);
} else {
var fullPath = _createUrlPathFromFile(customHtmlPath);
- var command = BrowserTestCommand(fullPath, configuration,
- retry: !isNegative(testFile));
+ var command = BrowserTestCommand(fullPath, configuration);
_addTestCase(testFile, testFile.name, [command],
expectations[testFile.name], onTest);
}
diff --git a/pkg/test_runner/tool/update_static_error_tests.dart b/pkg/test_runner/tool/update_static_error_tests.dart
index d763c9f..4547df3 100644
--- a/pkg/test_runner/tool/update_static_error_tests.dart
+++ b/pkg/test_runner/tool/update_static_error_tests.dart
@@ -142,7 +142,7 @@
bool insertCfe}) async {
stdout.write("${file.path}...");
var source = file.readAsStringSync();
- var testFile = TestFile.parse(Path("."), file.path, source);
+ var testFile = TestFile.parse(Path("."), file.absolute.path, source);
var options = testFile.sharedOptions.toList();
if (testFile.experiments.isNotEmpty) {
@@ -152,14 +152,14 @@
var errors = <StaticError>[];
if (insertAnalyzer) {
stdout.write("\r${file.path} (Running analyzer...)");
- errors.addAll(await _runAnalyzer(file.path, options));
+ errors.addAll(await _runAnalyzer(file.absolute.path, options));
}
if (insertCfe) {
// Clear the previous line.
stdout.write("\r${file.path} ");
stdout.write("\r${file.path} (Running CFE...)");
- errors.addAll(await _runCfe(file.path, options));
+ errors.addAll(await _runCfe(file.absolute.path, options));
}
errors = StaticError.simplify(errors);
@@ -182,11 +182,15 @@
// TODO(rnystrom): Running the analyzer command line each time is very slow.
// Either import the analyzer as a library, or at least invoke it in a batch
// mode.
- var result = await Process.run("sdk/bin/dartanalyzer$shellScriptExtension", [
- ...options,
- "--format=machine",
- path,
- ]);
+ var result = await Process.run(
+ Platform.isWindows
+ ? "sdk\\bin\\dartanalyzer.bat"
+ : "sdk/bin/dartanalyzer",
+ [
+ ...options,
+ "--format=machine",
+ path,
+ ]);
var errors = <StaticError>[];
AnalysisCommandOutput.parseErrors(result.stderr as String, errors);
return errors;
@@ -197,19 +201,17 @@
// TODO(rnystrom): Running the CFE command line each time is slow and wastes
// time generating code, which we don't care about. Import it as a library or
// at least run it in batch mode.
- var result = await Process.run("sdk/bin/dart", [
+ var result = await Process.run(
+ Platform.isWindows ? "sdk\\bin\\dart.bat" : "sdk/bin/dart", [
"pkg/front_end/tool/_fasta/compile.dart",
...options,
"--verify",
+ "-o",
+ "dev:null", // Output is only created for file URIs.
path,
]);
var errors = <StaticError>[];
FastaCommandOutput.parseErrors(result.stdout as String, errors);
-
- // Running the above command generates a dill file next to the test, which we
- // don't want, so delete it.
- await File("$path.dill").delete();
-
return errors;
}
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 00de5c9..99141fa 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -35,13 +35,14 @@
import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/kernel.dart' show Component, Procedure;
+import 'package:kernel/kernel.dart' show Component, Library, Procedure;
import 'package:kernel/target/targets.dart' show TargetFlags;
import 'package:vm/bytecode/gen_bytecode.dart'
show createFreshComponentWithBytecode, generateBytecode;
import 'package:vm/bytecode/options.dart' show BytecodeOptions;
import 'package:vm/incremental_compiler.dart';
-import 'package:vm/kernel_front_end.dart' show runWithFrontEndCompilerContext;
+import 'package:vm/kernel_front_end.dart'
+ show createLoadedLibrariesSet, runWithFrontEndCompilerContext;
import 'package:vm/http_filesystem.dart';
import 'package:vm/target/vm.dart' show VmTarget;
import 'package:front_end/src/api_prototype/compiler_options.dart'
@@ -157,7 +158,7 @@
};
}
- Future<Component> compile(Uri script) {
+ Future<CompilerResult> compile(Uri script) {
return runWithPrintToStderr(() async {
CompilerResult compilerResult = await compileInternal(script);
Component component = compilerResult.component;
@@ -169,11 +170,19 @@
}
if (options.bytecode && errors.isEmpty) {
+ final List<Library> libraries = new List<Library>();
+ final Set<Library> loadedLibraries = compilerResult.loadedLibraries;
+ for (Library library in component.libraries) {
+ if (loadedLibraries.contains(library)) continue;
+ libraries.add(library);
+ }
+
await runWithFrontEndCompilerContext(script, options, component, () {
// TODO(alexmarkov): disable local variables info,
// debugger stops and source files in VM PRODUCT mode.
// TODO(rmacnak): disable annotations if mirrors are not enabled.
generateBytecode(component,
+ libraries: libraries,
coreTypes: compilerResult.coreTypes,
hierarchy: compilerResult.classHierarchy,
options: new BytecodeOptions(
@@ -195,11 +204,17 @@
keepUnreachableCode: supportCodeCoverage,
avoidClosureCallInstructions: supportCodeCoverage,
));
- component = createFreshComponentWithBytecode(component);
+ Component freshComponent =
+ createFreshComponentWithBytecode(component);
+ compilerResult = new CompilerResult(
+ freshComponent,
+ compilerResult.loadedLibraries,
+ compilerResult.classHierarchy,
+ compilerResult.coreTypes);
});
}
- return component;
+ return compilerResult;
});
}
@@ -208,11 +223,17 @@
class CompilerResult {
final Component component;
+
+ /// Set of libraries loaded from .dill, with or without the SDK depending on
+ /// the compilation settings.
+ final Set<Library> loadedLibraries;
final ClassHierarchy classHierarchy;
final CoreTypes coreTypes;
- CompilerResult(this.component, this.classHierarchy, this.coreTypes)
+ CompilerResult(
+ this.component, this.loadedLibraries, this.classHierarchy, this.coreTypes)
: assert(component != null),
+ assert(loadedLibraries != null),
assert(classHierarchy != null),
assert(coreTypes != null);
}
@@ -279,8 +300,8 @@
}
errors.clear();
final component = await generator.compile(entryPoint: script);
- return new CompilerResult(
- component, generator.getClassHierarchy(), generator.getCoreTypes());
+ return new CompilerResult(component, const {},
+ generator.getClassHierarchy(), generator.getCoreTypes());
}
void accept() => generator.accept();
@@ -336,7 +357,12 @@
fe.CompilerResult compilerResult = requireMain
? await kernelForProgram(script, options)
: await kernelForModule([script], options);
- return new CompilerResult(compilerResult.component,
+
+ Set<Library> loadedLibraries = createLoadedLibrariesSet(
+ compilerResult?.loadedComponents, compilerResult?.sdkComponent,
+ includePlatform: !options.omitPlatform);
+
+ return new CompilerResult(compilerResult.component, loadedLibraries,
compilerResult.classHierarchy, compilerResult.coreTypes);
}
}
@@ -678,14 +704,15 @@
print("DFE: scriptUri: ${script}");
}
- Component component = await compiler.compile(script);
+ CompilerResult compilerResult = await compiler.compile(script);
+ Set<Library> loadedLibraries = compilerResult.loadedLibraries;
if (compiler.errors.isNotEmpty) {
- if (component != null) {
+ if (compilerResult.component != null) {
result = new CompilationResult.errors(
compiler.errors,
- // ignore: DEPRECATED_MEMBER_USE
- serializeComponent(component, filter: (lib) => !lib.isExternal));
+ serializeComponent(compilerResult.component,
+ filter: (lib) => !loadedLibraries.contains(lib)));
} else {
result = new CompilationResult.errors(compiler.errors, null);
}
@@ -694,9 +721,9 @@
// these sources built-in. Everything loaded as a summary in
// [kernelForProgram] is marked `external`, so we can use that bit to
// decide what to exclude.
- result = new CompilationResult.ok(
- // ignore: DEPRECATED_MEMBER_USE
- serializeComponent(component, filter: (lib) => !lib.isExternal));
+ result = new CompilationResult.ok(serializeComponent(
+ compilerResult.component,
+ filter: (lib) => !loadedLibraries.contains(lib)));
}
} catch (error, stack) {
result = new CompilationResult.crash(error, stack);
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index 10dd830..be95068 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -107,9 +107,9 @@
}
}
- void emitYieldPointSourcePosition() {
+ void emitYieldPointSourcePosition(int yieldSourcePosition) {
if (!isUnreachable) {
- sourcePositions.addYieldPoint(offset, currentSourcePosition);
+ sourcePositions.addYieldPoint(offset, yieldSourcePosition);
}
}
@@ -746,4 +746,14 @@
emitSourcePosition();
_emitInstructionD(Opcode.kInitLateField, rd);
}
+
+ @pragma('vm:prefer-inline')
+ void emitPushUninitializedSentinel() {
+ _emitInstruction0(Opcode.kPushUninitializedSentinel);
+ }
+
+ @pragma('vm:prefer-inline')
+ void emitJumpIfInitialized(Label label) {
+ _emitJumpInstruction(Opcode.kJumpIfInitialized, label);
+ }
}
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index a860cd6..bc1e22b 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -10,7 +10,7 @@
/// Before bumping current bytecode version format, make sure that
/// all users have switched to a VM which is able to consume new
/// version of bytecode.
-const int currentBytecodeFormatVersion = 26;
+const int currentBytecodeFormatVersion = 27;
enum Opcode {
kUnusedOpcode000,
@@ -95,9 +95,11 @@
kUnusedOpcode079,
kUnusedOpcode080,
kUnusedOpcode081,
- kUnusedOpcode082,
- kUnusedOpcode083,
- kUnusedOpcode084,
+
+ // Late variables.
+ kJumpIfInitialized,
+ kJumpIfInitialized_Wide,
+ kPushUninitializedSentinel,
kTrap,
@@ -181,7 +183,7 @@
kStoreIndexedTOS,
kUnused20,
- // Late fields and variables.
+ // Late fields.
kInitLateField,
kInitLateField_Wide,
@@ -416,6 +418,10 @@
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kInitLateField: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
+ Opcode.kPushUninitializedSentinel: const Format(
+ Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+ Opcode.kJumpIfInitialized: const Format(
+ Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kLoadStatic: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kStoreStaticTOS: const Format(
@@ -642,6 +648,7 @@
case Opcode.kPushTrue:
case Opcode.kPushFalse:
case Opcode.kPushInt:
+ case Opcode.kPushUninitializedSentinel:
return true;
default:
return false;
diff --git a/pkg/vm/lib/bytecode/declarations.dart b/pkg/vm/lib/bytecode/declarations.dart
index 704bef6..273e443 100644
--- a/pkg/vm/lib/bytecode/declarations.dart
+++ b/pkg/vm/lib/bytecode/declarations.dart
@@ -5,6 +5,7 @@
library vm.bytecode.declarations;
import 'package:kernel/ast.dart' show TreeNode, listHashCode, listEquals;
+import 'package:kernel/core_types.dart' show CoreTypes;
import 'bytecode_serialization.dart'
show
BufferedWriter,
@@ -1253,9 +1254,9 @@
Set<String> protectedNames;
ObjectHandle mainLibrary;
- Component(this.version)
+ Component(this.version, CoreTypes coreTypes)
: stringTable = new StringTable(),
- objectTable = new ObjectTable();
+ objectTable = new ObjectTable(coreTypes);
void write(BufferedWriter writer) {
objectTable.allocateIndexTable();
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 6e97d4a..dce21ec 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -24,7 +24,7 @@
import 'package:kernel/type_algebra.dart'
show Substitution, containsTypeVariable;
import 'package:kernel/type_environment.dart'
- show SubtypeCheckMode, TypeEnvironment;
+ show StatefulStaticTypeContext, SubtypeCheckMode, TypeEnvironment;
import 'assembler.dart';
import 'bytecode_serialization.dart' show StringTable;
import 'constant_pool.dart';
@@ -122,6 +122,7 @@
final CoreTypes coreTypes;
final ClassHierarchy hierarchy;
final TypeEnvironment typeEnvironment;
+ final StatefulStaticTypeContext staticTypeContext;
final BytecodeOptions options;
final BytecodeMetadataRepository metadata = new BytecodeMetadataRepository();
final RecognizedMethods recognizedMethods;
@@ -167,20 +168,33 @@
List<int> savedMaxSourcePositions;
int maxSourcePosition;
- BytecodeGenerator(ast.Component component, this.coreTypes, this.hierarchy,
- this.typeEnvironment, this.options)
- : recognizedMethods = new RecognizedMethods(typeEnvironment),
+ BytecodeGenerator(
+ ast.Component component,
+ CoreTypes coreTypes,
+ ClassHierarchy hierarchy,
+ TypeEnvironment typeEnvironment,
+ BytecodeOptions options)
+ : this._internal(component, coreTypes, hierarchy, typeEnvironment,
+ options, new StatefulStaticTypeContext.flat(typeEnvironment));
+
+ BytecodeGenerator._internal(
+ ast.Component component,
+ this.coreTypes,
+ this.hierarchy,
+ this.typeEnvironment,
+ this.options,
+ this.staticTypeContext)
+ : recognizedMethods = new RecognizedMethods(staticTypeContext),
formatVersion = currentBytecodeFormatVersion,
astUriToSource = component.uriToSource {
nullabilityDetector = new NullabilityDetector(recognizedMethods);
component.addMetadataRepository(metadata);
- bytecodeComponent = new Component(formatVersion);
+ bytecodeComponent = new Component(formatVersion, coreTypes);
metadata.mapping[component] = new BytecodeMetadata(bytecodeComponent);
stringTable = bytecodeComponent.stringTable;
objectTable = bytecodeComponent.objectTable;
- objectTable.coreTypes = coreTypes;
if (component.mainMethod != null) {
bytecodeComponent.mainLibrary =
@@ -207,10 +221,7 @@
@override
visitLibrary(Library node) {
- // ignore: DEPRECATED_MEMBER_USE
- if (node.isExternal) {
- return;
- }
+ staticTypeContext.enterLibrary(node);
startMembers();
visitList(node.procedures, this);
@@ -226,6 +237,7 @@
bytecodeComponent.libraries
.add(getLibraryDeclaration(node, classDeclarations));
classDeclarations = null;
+ staticTypeContext.leaveLibrary(node);
}
@override
@@ -570,12 +582,10 @@
FieldDeclaration getFieldDeclaration(Field field, Code initializer) {
int flags = 0;
Constant value;
- if (_hasTrivialInitializer(field)) {
- if (field.initializer != null) {
- value = _getConstant(field.initializer);
- }
- } else {
+ if (_hasNonTrivialInitializer(field)) {
flags |= FieldDeclaration.hasNontrivialInitializerFlag;
+ } else if (field.initializer != null) {
+ value = _getConstant(field.initializer);
}
if (initializer != null) {
flags |= FieldDeclaration.hasInitializerCodeFlag;
@@ -956,7 +966,7 @@
(field.isStatic ||
field.isLate ||
options.emitInstanceFieldInitializers) &&
- !_hasTrivialInitializer(field);
+ _hasNonTrivialInitializer(field);
bool _needsGetter(Field field) {
// All instance fields need a getter.
@@ -964,7 +974,7 @@
// Static fields also need a getter if they have a non-trivial initializer,
// because it needs to be initialized lazily.
- if (!_hasTrivialInitializer(field)) return true;
+ if (_hasNonTrivialInitializer(field)) return true;
// Static late fields with no initializer also need a getter, to check if
// it's been initialized.
@@ -972,11 +982,14 @@
}
bool _needsSetter(Field field) {
- // Static fields never need a setter.
- if (field.isStatic) return false;
+ // Late fields always need a setter, unless they're static and non-final.
+ if (field.isLate) {
+ if (field.isStatic && !field.isFinal) return false;
+ return true;
+ }
- // Late instance fields always need a setter.
- if (field.isLate) return true;
+ // Non-late static fields never need a setter.
+ if (field.isStatic) return false;
// Otherwise, the field only needs a setter if it isn't final.
return !field.isFinal;
@@ -1074,6 +1087,11 @@
Procedure get futureValue =>
_futureValue ??= libraryIndex.getMember('dart:async', 'Future', 'value');
+ Procedure _throwNewLateInitializationError;
+ Procedure get throwNewLateInitializationError =>
+ _throwNewLateInitializationError ??= libraryIndex.getMember(
+ 'dart:core', '_LateInitializationError', '_throwNew');
+
Procedure _throwNewAssertionError;
Procedure get throwNewAssertionError => _throwNewAssertionError ??=
libraryIndex.getMember('dart:core', '_AssertionError', '_throwNew');
@@ -1203,7 +1221,7 @@
void _genLateFieldInitializer(Field field) {
assert(!field.isStatic);
- if (field.initializer != null && _hasTrivialInitializer(field)) {
+ if (_isTrivialInitializer(field.initializer)) {
_genFieldInitializer(field, field.initializer);
return;
}
@@ -1277,7 +1295,7 @@
}
}
- void _genReturnTOS() {
+ void _genReturnTOS([int yieldSourcePosition = null]) {
if (options.causalAsyncStacks &&
parentFunction != null &&
(parentFunction.dartAsyncMarker == AsyncMarker.Async ||
@@ -1290,6 +1308,9 @@
asm.currentSourcePosition = savedSourcePosition;
}
+ if (yieldSourcePosition != null && options.emitSourcePositions) {
+ asm.emitYieldPointSourcePosition(yieldSourcePosition);
+ }
asm.emitReturnTOS();
}
@@ -1653,9 +1674,7 @@
parentFunction = null;
isClosure = false;
hasErrors = false;
- if ((node is Procedure && !node.isStatic) || node is Constructor) {
- typeEnvironment.thisType = enclosingClass.thisType;
- }
+ staticTypeContext.enterMember(node);
final isFactory = node is Procedure && node.isFactory;
if (node.isInstanceMember || node is Constructor || isFactory) {
if (enclosingClass.typeParameters.isNotEmpty) {
@@ -1726,8 +1745,8 @@
savedMaxSourcePositions = <int>[];
maxSourcePosition = node.fileOffset;
- locals =
- new LocalVariables(node, options, typeEnvironment, directCallMetadata);
+ locals = new LocalVariables(
+ node, options, staticTypeContext, directCallMetadata);
locals.enterScope(node);
assert(!locals.isSyncYieldingFrame);
@@ -1847,7 +1866,7 @@
}
}
- typeEnvironment.thisType = null;
+ staticTypeContext.leaveMember(node);
enclosingClass = null;
enclosingMember = null;
enclosingFunction = null;
@@ -3237,7 +3256,7 @@
bool _isUncheckedCall(
Node node, Member interfaceTarget, Expression receiver) =>
- isUncheckedCall(interfaceTarget, receiver, typeEnvironment) ||
+ isUncheckedCall(interfaceTarget, receiver, staticTypeContext) ||
(inferredTypeMetadata != null &&
inferredTypeMetadata[node]?.skipCheck == true);
@@ -3258,7 +3277,7 @@
}
if (invocationKind != InvocationKind.getter && !isDynamic && !isUnchecked) {
- final staticReceiverType = getStaticType(receiver, typeEnvironment);
+ final staticReceiverType = getStaticType(receiver, staticTypeContext);
if (isInstantiatedInterfaceCall(interfaceTarget, staticReceiverType)) {
final callCpIndex = cp.addInstantiatedInterfaceCall(
invocationKind, interfaceTarget, argDesc, staticReceiverType);
@@ -3349,7 +3368,7 @@
}
// Front-end guarantees that all calls with known function type
// do not need any argument type checks.
- if (isUncheckedClosureCall(node, typeEnvironment, options)) {
+ if (isUncheckedClosureCall(node, staticTypeContext, options)) {
final int receiverTemp = locals.tempIndexInFrame(node);
_genArguments(node.receiver, args, storeReceiverToLocal: receiverTemp);
// Duplicate receiver (closure) for UncheckedClosureCall.
@@ -3569,10 +3588,14 @@
_genRethrow(tryCatch);
}
- bool _hasTrivialInitializer(Field field) {
- final initializer = field.initializer;
- if (initializer == null ||
- initializer is StringLiteral ||
+ bool _hasNonTrivialInitializer(Field field) {
+ if (field.initializer == null) return false;
+ return !_isTrivialInitializer(field.initializer);
+ }
+
+ bool _isTrivialInitializer(Expression initializer) {
+ if (initializer == null) return false;
+ if (initializer is StringLiteral ||
initializer is BoolLiteral ||
initializer is IntLiteral ||
initializer is DoubleLiteral ||
@@ -3670,7 +3693,7 @@
}
final target = node.target;
- if (target is Field) {
+ if (target is Field && !_needsSetter(target)) {
if (options.emitDebuggerStops &&
_variableSetNeedsDebugCheck(node.value)) {
asm.emitDebugCheck();
@@ -3751,6 +3774,34 @@
final v = node.variable;
if (v.isConst) {
_genPushConstExpr(v.initializer);
+ } else if (v.isLate) {
+ _genLoadVar(v);
+
+ final Label done = new Label();
+ asm.emitJumpIfInitialized(done);
+
+ if (v.initializer != null) {
+ final init = v.initializer;
+ _genPushContextIfCaptured(v);
+ // Late local variable initializers are transformed to wrap the
+ // initializer in a closure (see late_var_init_transformer.dart). The
+ // closure call needs one temporary, so withTemp lets us use this
+ // VariableGet's temporary when visiting the initializer.
+ assert(init is MethodInvocation &&
+ init.name.name == "call" &&
+ init.arguments.positional.length == 0);
+ locals.withTemp(
+ init, locals.tempIndexInFrame(node), () => _generateNode(init));
+ _genStoreVar(v);
+ } else {
+ asm.emitPushConstant(cp.addName(v.name));
+ _genDirectCall(throwNewLateInitializationError,
+ objectTable.getArgDescHandle(1), 1);
+ asm.emitDrop1();
+ }
+
+ asm.bind(done);
+ _genLoadVar(v);
} else {
_genLoadVar(v);
}
@@ -3760,8 +3811,11 @@
visitVariableSet(VariableSet node) {
final v = node.variable;
final bool hasResult = !isExpressionWithoutResult(node);
+ final bool isLateFinal = v.isLate && v.isFinal;
- _genPushContextIfCaptured(v);
+ if (!isLateFinal) {
+ _genPushContextIfCaptured(v);
+ }
_generateNode(node.value);
@@ -3769,7 +3823,32 @@
asm.emitDebugCheck();
}
- if (locals.isCaptured(v)) {
+ if (isLateFinal) {
+ final int temp = locals.tempIndexInFrame(node);
+ asm.emitPopLocal(temp);
+
+ final Label error = new Label();
+ final Label done = new Label();
+ _genLoadVar(v);
+ asm.emitJumpIfInitialized(error);
+
+ _genPushContextIfCaptured(v);
+ asm.emitPush(temp);
+ _genStoreVar(v);
+ asm.emitJump(done);
+
+ asm.bind(error);
+ asm.emitPushConstant(cp.addName(v.name));
+ _genDirectCall(
+ throwNewLateInitializationError, objectTable.getArgDescHandle(1), 1);
+ asm.emitDrop1();
+
+ asm.bind(done);
+
+ if (hasResult) {
+ asm.emitPush(temp);
+ }
+ } else if (locals.isCaptured(v)) {
final int temp = locals.tempIndexInFrame(node);
if (hasResult) {
asm.emitStoreLocal(temp);
@@ -4415,19 +4494,37 @@
finallyBlocks.remove(node);
}
+ bool _skipVariableInitialization(VariableDeclaration v, bool isCaptured) {
+ // We can skip variable initialization if the variable is supposed to be
+ // initialized to null and it's captured. This is because all the slots in
+ // the capture context are implicitly initialized to null.
+
+ // Check if the variable is supposed to be initialized to null.
+ if (!(v.initializer == null || v.initializer is NullLiteral)) {
+ return false;
+ }
+
+ // Late variables need to be initialized to a sentinel, not null.
+ if (v.isLate) return false;
+
+ // Non-captured variables go in stack slots that aren't implicitly nulled.
+ return isCaptured;
+ }
+
@override
visitVariableDeclaration(VariableDeclaration node) {
if (!node.isConst) {
final bool isCaptured = locals.isCaptured(node);
final initializer = node.initializer;
- final bool emitStore =
- !(isCaptured && (initializer == null || initializer is NullLiteral));
+ final bool emitStore = !_skipVariableInitialization(node, isCaptured);
int maxInitializerPosition = node.fileOffset;
if (emitStore) {
if (isCaptured) {
_genPushContextForVariable(node);
}
- if (initializer != null) {
+ if (node.isLate && !_isTrivialInitializer(initializer)) {
+ asm.emitPushUninitializedSentinel();
+ } else if (initializer != null) {
_startRecordingMaxPosition(node.fileOffset);
_generateNode(initializer);
maxInitializerPosition = _endRecordingMaxPosition();
@@ -4490,10 +4587,6 @@
return;
}
- if (options.emitSourcePositions) {
- asm.emitYieldPointSourcePosition();
- }
-
// 0 is reserved for normal entry, yield points are counted from 1.
final int yieldIndex = yieldPoints.length + 1;
final Label continuationLabel = new Label(allowsBackwardJumps: true);
@@ -4514,7 +4607,7 @@
// return <expression>
// Note: finally blocks are *not* executed on the way out.
_generateNode(node.expression);
- _genReturnTOS();
+ _genReturnTOS(node.fileOffset);
asm.bind(continuationLabel);
diff --git a/pkg/vm/lib/bytecode/generics.dart b/pkg/vm/lib/bytecode/generics.dart
index 4fe55e8..88b551c 100644
--- a/pkg/vm/lib/bytecode/generics.dart
+++ b/pkg/vm/lib/bytecode/generics.dart
@@ -9,7 +9,7 @@
import 'package:kernel/ast.dart' hide MapEntry;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/type_algebra.dart' show Substitution;
-import 'package:kernel/type_environment.dart' show TypeEnvironment;
+import 'package:kernel/type_environment.dart' show StaticTypeContext;
import 'options.dart' show BytecodeOptions;
@@ -153,6 +153,9 @@
bool visitBottomType(BottomType node) => false;
@override
+ bool visitNeverType(NeverType node) => false;
+
+ @override
bool visitTypeParameterType(TypeParameterType node) =>
_declaredTypeParameters == null ||
!_declaredTypeParameters.contains(node.parameter);
@@ -185,15 +188,8 @@
}
/// Returns static type of [expr].
-DartType getStaticType(Expression expr, TypeEnvironment typeEnvironment) {
- // TODO(dartbug.com/34496): Remove this try/catch once
- // getStaticType() is reliable.
- try {
- return expr.getStaticType(typeEnvironment);
- } catch (e) {
- return const DynamicType();
- }
-}
+DartType getStaticType(Expression expr, StaticTypeContext staticTypeContext) =>
+ expr.getStaticType(staticTypeContext);
/// Returns `true` if [type] cannot be extended in user code.
bool isSealedType(DartType type, CoreTypes coreTypes) {
@@ -212,7 +208,7 @@
/// [receiver] can omit argument type checks needed due to generic-covariant
/// parameters.
bool isUncheckedCall(Member interfaceTarget, Expression receiver,
- TypeEnvironment typeEnvironment) {
+ StaticTypeContext staticTypeContext) {
if (interfaceTarget == null) {
// Dynamic call cannot be unchecked.
return false;
@@ -228,14 +224,14 @@
return true;
}
- DartType receiverStaticType = getStaticType(receiver, typeEnvironment);
+ DartType receiverStaticType = getStaticType(receiver, staticTypeContext);
if (receiverStaticType is InterfaceType) {
if (receiverStaticType.typeArguments.isEmpty) {
return true;
}
- if (receiverStaticType.typeArguments
- .every((t) => isSealedType(t, typeEnvironment.coreTypes))) {
+ if (receiverStaticType.typeArguments.every(
+ (t) => isSealedType(t, staticTypeContext.typeEnvironment.coreTypes))) {
return true;
}
}
@@ -282,9 +278,9 @@
/// Returns true if invocation [node] is a closure call with statically known
/// function type. Such invocations can omit argument type checks.
bool isUncheckedClosureCall(MethodInvocation node,
- TypeEnvironment typeEnvironment, BytecodeOptions options) =>
+ StaticTypeContext staticTypeContext, BytecodeOptions options) =>
node.name.name == 'call' &&
- getStaticType(node.receiver, typeEnvironment) is FunctionType &&
+ getStaticType(node.receiver, staticTypeContext) is FunctionType &&
!options.avoidClosureCallInstructions;
/// Returns true if [MethodInvocation] node with given [interfaceTarget] is
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 88812ec..304fd0e 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -25,7 +25,7 @@
Map<TreeNode, VariableDeclaration> _capturedStackTraceVars;
Map<ForInStatement, VariableDeclaration> _capturedIteratorVars;
final BytecodeOptions options;
- final TypeEnvironment typeEnvironment;
+ final StaticTypeContext staticTypeContext;
final Map<TreeNode, DirectCallMetadata> directCallMetadata;
Scope _currentScope;
@@ -190,7 +190,7 @@
List<VariableDeclaration> get sortedNamedParameters =>
_currentFrame.sortedNamedParameters;
- LocalVariables(Member node, this.options, this.typeEnvironment,
+ LocalVariables(Member node, this.options, this.staticTypeContext,
this.directCallMetadata) {
final scopeBuilder = new _ScopeBuilder(this);
node.accept(scopeBuilder);
@@ -208,6 +208,14 @@
_currentScope = _currentScope.parent;
_currentFrame = _currentScope?.frame;
}
+
+ void withTemp(TreeNode node, int temp, void action()) {
+ final old = _temps[node];
+ assert(old == null || old.length == 1);
+ _temps[node] = [temp];
+ action();
+ _temps[node] = old;
+ }
}
class VarDesc {
@@ -595,6 +603,9 @@
@override
visitVariableGet(VariableGet node) {
_useVariable(node.variable);
+ if (node.variable.isLate && node.variable.initializer != null) {
+ node.variable.initializer.accept(this);
+ }
}
@override
@@ -1225,7 +1236,8 @@
@override
visitMethodInvocation(MethodInvocation node) {
int numTemps = 0;
- if (isUncheckedClosureCall(node, locals.typeEnvironment, locals.options)) {
+ if (isUncheckedClosureCall(
+ node, locals.staticTypeContext, locals.options)) {
numTemps = 1;
} else if (isCallThroughGetter(node.interfaceTarget)) {
final args = node.arguments;
@@ -1282,8 +1294,15 @@
}
@override
+ visitVariableGet(VariableGet node) {
+ _visit(node, temps: node.variable.isLate ? 1 : 0);
+ }
+
+ @override
visitVariableSet(VariableSet node) {
- _visit(node, temps: locals.isCaptured(node.variable) ? 1 : 0);
+ final v = node.variable;
+ final bool needsTemp = locals.isCaptured(v) || v.isLate && v.isFinal;
+ _visit(node, temps: needsTemp ? 1 : 0);
}
@override
diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart
index 1d8e290..7ef26b2 100644
--- a/pkg/vm/lib/bytecode/object_table.dart
+++ b/pkg/vm/lib/bytecode/object_table.dart
@@ -1745,14 +1745,13 @@
_TypeHandle _dynamicType;
_TypeHandle _voidType;
_TypeHandle _neverType;
- CoreTypes coreTypes;
_NodeVisitor _nodeVisitor;
- ObjectTable() {
+ ObjectTable(CoreTypes coreTypes) {
_dynamicType = getOrAddObject(new _DynamicTypeHandle());
_voidType = getOrAddObject(new _VoidTypeHandle());
_neverType = getOrAddObject(new _NeverTypeHandle());
- _nodeVisitor = new _NodeVisitor(this);
+ _nodeVisitor = new _NodeVisitor(this, coreTypes);
}
ObjectHandle getHandle(Node node) {
@@ -2093,11 +2092,13 @@
class _NodeVisitor extends Visitor<ObjectHandle> {
final ObjectTable objectTable;
+ final CoreTypes coreTypes;
final _typeParameters = <TypeParameter, ObjectHandle>{};
final Map<DartType, int> _recursiveTypeIds = <DartType, int>{};
- final recursiveTypesValidator = new RecursiveTypesValidator();
+ final recursiveTypesValidator;
- _NodeVisitor(this.objectTable);
+ _NodeVisitor(this.objectTable, this.coreTypes)
+ : recursiveTypesValidator = new RecursiveTypesValidator(coreTypes);
@override
ObjectHandle defaultNode(Node node) =>
@@ -2132,7 +2133,7 @@
@override
ObjectHandle visitBottomType(BottomType node) =>
- objectTable.getHandle(objectTable.coreTypes.nullType);
+ objectTable.getHandle(coreTypes.nullType);
@override
ObjectHandle visitInterfaceType(InterfaceType node) {
diff --git a/pkg/vm/lib/bytecode/recognized_methods.dart b/pkg/vm/lib/bytecode/recognized_methods.dart
index 73033b6..a237c1f 100644
--- a/pkg/vm/lib/bytecode/recognized_methods.dart
+++ b/pkg/vm/lib/bytecode/recognized_methods.dart
@@ -5,7 +5,7 @@
library vm.bytecode.recognized_methods;
import 'package:kernel/ast.dart';
-import 'package:kernel/type_environment.dart' show TypeEnvironment;
+import 'package:kernel/type_environment.dart' show StaticTypeContext;
import 'dbc.dart';
import 'generics.dart' show getStaticType;
@@ -41,15 +41,18 @@
'<=': Opcode.kCompareDoubleLe,
};
- final TypeEnvironment typeEnv;
+ final StaticTypeContext staticTypeContext;
- RecognizedMethods(this.typeEnv);
+ RecognizedMethods(this.staticTypeContext);
- DartType staticType(Expression expr) => getStaticType(expr, typeEnv);
+ DartType staticType(Expression expr) =>
+ getStaticType(expr, staticTypeContext);
- bool isInt(DartType type) => type == typeEnv.coreTypes.intLegacyRawType;
+ bool isInt(DartType type) =>
+ type == staticTypeContext.typeEnvironment.coreTypes.intLegacyRawType;
- bool isDouble(DartType type) => type == typeEnv.coreTypes.doubleLegacyRawType;
+ bool isDouble(DartType type) =>
+ type == staticTypeContext.typeEnvironment.coreTypes.doubleLegacyRawType;
Opcode specializedBytecodeFor(MethodInvocation node) {
final args = node.arguments;
diff --git a/pkg/vm/lib/bytecode/recursive_types_validator.dart b/pkg/vm/lib/bytecode/recursive_types_validator.dart
index acaa020..d88d291 100644
--- a/pkg/vm/lib/bytecode/recursive_types_validator.dart
+++ b/pkg/vm/lib/bytecode/recursive_types_validator.dart
@@ -5,6 +5,7 @@
library vm.bytecode.recursive_types_validator;
import 'package:kernel/ast.dart' hide MapEntry;
+import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/type_algebra.dart' show Substitution;
import 'generics.dart'
@@ -13,10 +14,13 @@
/// Detect recursive types and validates that finalized (flattened)
/// representation of generic types is valid (finite).
class RecursiveTypesValidator {
+ final CoreTypes coreTypes;
final Set<DartType> _validatedTypes = <DartType>{};
final Set<DartType> _recursiveTypes = <DartType>{};
final Set<Class> _validatedClases = <Class>{};
+ RecursiveTypesValidator(this.coreTypes);
+
/// Validates [type].
void validateType(DartType type) {
if (!isValidated(type)) {
@@ -39,7 +43,8 @@
void validateClass(Class cls) {
if (_validatedClases.add(cls)) {
try {
- validateType(cls.thisType);
+ validateType(
+ cls.getThisType(coreTypes, cls.enclosingLibrary.nonNullable));
} on IllegalRecursiveTypeException catch (e) {
_validatedClases.remove(cls);
throw e;
@@ -103,6 +108,9 @@
void visitBottomType(BottomType node) {}
@override
+ void visitNeverType(NeverType node) {}
+
+ @override
void visitTypeParameterType(TypeParameterType node) {}
@override
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index e35422e..733b3b5 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -230,6 +230,7 @@
..embedSourceText = embedSources;
final results = await compileToKernel(mainUri, compilerOptions,
+ includePlatform: linkedDependencies.isNotEmpty,
aot: aot,
useGlobalTypeFlowAnalysis: tfa,
environmentDefines: environmentDefines,
@@ -267,9 +268,7 @@
await writeOutputSplitByPackages(
mainUri,
compilerOptions,
- results.component,
- results.coreTypes,
- results.classHierarchy,
+ results,
outputFileName,
genBytecode: genBytecode,
bytecodeOptions: bytecodeOptions,
@@ -284,12 +283,16 @@
/// collection of compiled sources.
class KernelCompilationResults {
final Component component;
+
+ /// Set of libraries loaded from .dill, with or without the SDK depending on
+ /// the compilation settings.
+ final Set<Library> loadedLibraries;
final ClassHierarchy classHierarchy;
final CoreTypes coreTypes;
final Iterable<Uri> compiledSources;
- KernelCompilationResults(this.component, this.classHierarchy, this.coreTypes,
- this.compiledSources);
+ KernelCompilationResults(this.component, this.loadedLibraries,
+ this.classHierarchy, this.coreTypes, this.compiledSources);
}
/// Generates a kernel representation of the program whose main library is in
@@ -299,7 +302,8 @@
///
Future<KernelCompilationResults> compileToKernel(
Uri source, CompilerOptions options,
- {bool aot: false,
+ {bool includePlatform: false,
+ bool aot: false,
bool useGlobalTypeFlowAnalysis: false,
Map<String, String> environmentDefines,
bool enableAsserts: true,
@@ -314,10 +318,13 @@
setVMEnvironmentDefines(environmentDefines, options);
CompilerResult compilerResult = await kernelForProgram(source, options);
-
Component component = compilerResult?.component;
final compiledSources = component?.uriToSource?.keys;
+ Set<Library> loadedLibraries = createLoadedLibrariesSet(
+ compilerResult?.loadedComponents, compilerResult?.sdkComponent,
+ includePlatform: includePlatform);
+
// Run global transformations only if component is correct.
if (aot && component != null) {
await runGlobalTransformations(
@@ -330,8 +337,15 @@
}
if (genBytecode && !errorDetector.hasCompilationErrors && component != null) {
+ List<Library> libraries = new List<Library>();
+ for (Library library in component.libraries) {
+ if (loadedLibraries.contains(library)) continue;
+ libraries.add(library);
+ }
+
await runWithFrontEndCompilerContext(source, options, component, () {
generateBytecode(component,
+ libraries: libraries,
hierarchy: compilerResult.classHierarchy,
coreTypes: compilerResult.coreTypes,
options: bytecodeOptions);
@@ -345,8 +359,37 @@
// Restore error handler (in case 'options' are reused).
options.onDiagnostic = errorDetector.previousErrorHandler;
- return new KernelCompilationResults(component, compilerResult?.classHierarchy,
- compilerResult?.coreTypes, compiledSources);
+ return new KernelCompilationResults(
+ component,
+ loadedLibraries,
+ compilerResult?.classHierarchy,
+ compilerResult?.coreTypes,
+ compiledSources);
+}
+
+Set<Library> createLoadedLibrariesSet(
+ List<Component> loadedComponents, Component sdkComponent,
+ {bool includePlatform: false}) {
+ final Set<Library> loadedLibraries = {};
+ if (loadedComponents != null) {
+ for (Component c in loadedComponents) {
+ for (Library lib in c.libraries) {
+ loadedLibraries.add(lib);
+ }
+ }
+ }
+ if (sdkComponent != null) {
+ if (includePlatform) {
+ for (Library lib in sdkComponent.libraries) {
+ loadedLibraries.remove(lib);
+ }
+ } else {
+ for (Library lib in sdkComponent.libraries) {
+ loadedLibraries.add(lib);
+ }
+ }
+ }
+ return loadedLibraries;
}
void setVMEnvironmentDefines(
@@ -618,9 +661,7 @@
Future writeOutputSplitByPackages(
Uri source,
CompilerOptions compilerOptions,
- Component component,
- CoreTypes coreTypes,
- ClassHierarchy hierarchy,
+ KernelCompilationResults compilationResults,
String outputFileName, {
bool genBytecode: false,
BytecodeOptions bytecodeOptions,
@@ -631,31 +672,34 @@
}
final packages = new List<String>();
- await runWithFrontEndCompilerContext(source, compilerOptions, component,
- () async {
+ await runWithFrontEndCompilerContext(
+ source, compilerOptions, compilationResults.component, () async {
// When loading a kernel file list, flutter_runner and dart_runner expect
// 'main' to be last.
- await forEachPackage(component,
+ await forEachPackage(compilationResults,
(String package, List<Library> libraries) async {
packages.add(package);
final String filename = '$outputFileName-$package.dilp';
final IOSink sink = new File(filename).openWrite();
- Component partComponent = component;
+ Component partComponent = compilationResults.component;
if (genBytecode) {
generateBytecode(partComponent,
options: bytecodeOptions,
libraries: libraries,
- hierarchy: hierarchy,
- coreTypes: coreTypes);
+ hierarchy: compilationResults.classHierarchy,
+ coreTypes: compilationResults.coreTypes);
if (dropAST) {
partComponent = createFreshComponentWithBytecode(partComponent);
}
}
- final BinaryPrinter printer = new LimitedBinaryPrinter(sink,
- (lib) => packageFor(lib) == package, false /* excludeUriToSource */);
+ final BinaryPrinter printer = new LimitedBinaryPrinter(
+ sink,
+ (lib) =>
+ packageFor(lib, compilationResults.loadedLibraries) == package,
+ false /* excludeUriToSource */);
printer.writeComponentFile(partComponent);
await sink.close();
@@ -673,10 +717,9 @@
await packagesList.close();
}
-String packageFor(Library lib) {
+String packageFor(Library lib, Set<Library> loadedLibraries) {
// Core libraries are not written into any package kernel binaries.
- // ignore: DEPRECATED_MEMBER_USE
- if (lib.isExternal) return null;
+ if (loadedLibraries.contains(lib)) return null;
// Packages are written into their own kernel binaries.
Uri uri = lib.importUri;
@@ -702,15 +745,20 @@
}
}
-Future<Null> forEachPackage<T>(
- Component component, T action(String package, List<Library> libraries),
+Future<Null> forEachPackage<T>(KernelCompilationResults results,
+ T action(String package, List<Library> libraries),
{bool mainFirst}) async {
+ final Component component = results.component;
+ final Set<Library> loadedLibraries = results.loadedLibraries;
sortComponent(component);
final packages = new Map<String, List<Library>>();
packages['main'] = new List<Library>(); // Always create 'main'.
for (Library lib in component.libraries) {
- packages.putIfAbsent(packageFor(lib), () => new List<Library>()).add(lib);
+ packages
+ .putIfAbsent(
+ packageFor(lib, loadedLibraries), () => new List<Library>())
+ .add(lib);
}
packages.remove(null); // Ignore external libraries.
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index a647eb8..bd70be0 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -14,11 +14,14 @@
as transformMixins show transformLibraries;
import 'package:kernel/transformations/continuation.dart' as transformAsync
show transformLibraries, transformProcedure;
+import 'package:kernel/type_environment.dart';
import 'package:kernel/vm/constants_native_effects.dart'
show VmConstantsBackend;
import '../metadata/binary_cache.dart' show BinaryCacheMetadataRepository;
import '../transformations/call_site_annotator.dart' as callSiteAnnotator;
+import '../transformations/late_var_init_transformer.dart'
+ as lateVarInitTransformer;
import '../transformations/list_factory_specializer.dart'
as listFactorySpecializer;
import '../transformations/ffi.dart' as transformFfi show ReplacedMembers;
@@ -48,6 +51,9 @@
bool get supportsSetLiterals => false;
@override
+ bool get supportsLateFields => !flags.forceLateLoweringForTesting;
+
+ @override
String get name => 'vm';
// This is the order that bootstrap libraries are loaded according to
@@ -145,13 +151,17 @@
// TODO(kmillikin): Make this run on a per-method basis.
bool productMode = environmentDefines["dart.vm.product"] == "true";
- transformAsync.transformLibraries(coreTypes, libraries,
+ transformAsync.transformLibraries(
+ new TypeEnvironment(coreTypes, hierarchy), libraries,
productMode: productMode);
logger?.call("Transformed async methods");
listFactorySpecializer.transformLibraries(libraries, coreTypes);
logger?.call("Specialized list factories");
+ lateVarInitTransformer.transformLibraries(libraries);
+ logger?.call("Transformed late variable initializers");
+
callSiteAnnotator.transformLibraries(
component, libraries, coreTypes, hierarchy);
logger?.call("Annotated call sites");
@@ -161,7 +171,8 @@
void performTransformationsOnProcedure(
CoreTypes coreTypes, ClassHierarchy hierarchy, Procedure procedure,
{void logger(String msg)}) {
- transformAsync.transformProcedure(coreTypes, procedure);
+ transformAsync.transformProcedure(
+ new TypeEnvironment(coreTypes, hierarchy), procedure);
logger?.call("Transformed async functions");
}
@@ -348,7 +359,7 @@
new ListLiteral(elements, typeArgument: typeArgument)
..fileOffset = offset
], types: [
- new DynamicType()
+ typeArgument,
]));
}
diff --git a/pkg/vm/lib/transformations/call_site_annotator.dart b/pkg/vm/lib/transformations/call_site_annotator.dart
index 7b6b620..b93b258 100644
--- a/pkg/vm/lib/transformations/call_site_annotator.dart
+++ b/pkg/vm/lib/transformations/call_site_annotator.dart
@@ -12,7 +12,8 @@
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/core_types.dart' show CoreTypes;
-import 'package:kernel/type_environment.dart' show TypeEnvironment;
+import 'package:kernel/type_environment.dart'
+ show StaticTypeContext, TypeEnvironment;
import '../metadata/call_site_attributes.dart';
@@ -32,6 +33,7 @@
class AnnotateWithStaticTypes extends RecursiveVisitor<Null> {
final CallSiteAttributesMetadataRepository _metadata;
final TypeEnvironment env;
+ StaticTypeContext _staticTypeContext;
AnnotateWithStaticTypes(
Component component, CoreTypes coreTypes, ClassHierarchy hierarchy)
@@ -39,30 +41,15 @@
env = new TypeEnvironment(coreTypes, hierarchy);
@override
- visitProcedure(Procedure proc) {
- if (!proc.isStatic) {
- env.thisType = proc.enclosingClass?.thisType;
- }
- super.visitProcedure(proc);
- env.thisType = null;
- }
-
- @override
- visitConstructor(Constructor proc) {
- env.thisType = proc.enclosingClass?.thisType;
- super.visitConstructor(proc);
- env.thisType = null;
+ defaultMember(Member node) {
+ _staticTypeContext = new StaticTypeContext(node, env);
+ super.defaultMember(node);
+ _staticTypeContext = null;
}
void annotateWithType(TreeNode node, Expression receiver) {
- try {
- _metadata.mapping[node] = new CallSiteAttributesMetadata(
- receiverType: receiver.getStaticType(env));
- } catch (e) {
- // TODO(dartbug.com/34496) Currently getStaticType is unreliable due to
- // various issues with AST welltypedness. As a workaround we just
- // swallow the exception.
- }
+ _metadata.mapping[node] = new CallSiteAttributesMetadata(
+ receiverType: receiver.getStaticType(_staticTypeContext));
}
@override
diff --git a/pkg/vm/lib/transformations/devirtualization.dart b/pkg/vm/lib/transformations/devirtualization.dart
index ff8e4ca..838fe66 100644
--- a/pkg/vm/lib/transformations/devirtualization.dart
+++ b/pkg/vm/lib/transformations/devirtualization.dart
@@ -91,9 +91,7 @@
@override
visitLibrary(Library node) {
if (_trace) {
- // ignore: DEPRECATED_MEMBER_USE
- String external = node.isExternal ? " (external)" : "";
- print("[devirt] Processing library ${node.name}${external}");
+ print("[devirt] Processing library ${node.name}");
}
super.visitLibrary(node);
}
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index 4837963..76e6f9c 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -181,6 +181,7 @@
final Class intClass;
final Class doubleClass;
+ final Class listClass;
final Class pragmaClass;
final Field pragmaName;
final Field pragmaOptions;
@@ -216,6 +217,7 @@
: env = new TypeEnvironment(coreTypes, hierarchy),
intClass = coreTypes.intClass,
doubleClass = coreTypes.doubleClass,
+ listClass = coreTypes.listClass,
pragmaClass = coreTypes.pragmaClass,
pragmaName = coreTypes.pragmaName,
pragmaOptions = coreTypes.pragmaOptions,
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index 249a45a..9861852 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -274,7 +274,8 @@
IntConstant(values[Abi.wordSize32Align32]),
IntConstant(values[Abi.wordSize32Align64])
]),
- InterfaceType(intClass, Nullability.legacy)),
+ InterfaceType(listClass, Nullability.legacy,
+ [InterfaceType(intClass, Nullability.legacy)])),
Name("[]"),
Arguments([StaticInvocation(abiMethod, Arguments([]))]),
listElementAt);
@@ -332,7 +333,8 @@
loadMethod,
Arguments([
PropertyGet(ThisExpression(), pointerName, pointerGetter),
- ConstantExpression(IntConstant(0))
+ ConstantExpression(IntConstant(0),
+ InterfaceType(intClass, Nullability.legacy))
], types: typeArguments))),
returnType: field.type),
fileUri: field.fileUri)
@@ -353,7 +355,8 @@
storeMethod,
Arguments([
PropertyGet(ThisExpression(), pointerName, pointerGetter),
- ConstantExpression(IntConstant(0)),
+ ConstantExpression(IntConstant(0),
+ InterfaceType(intClass, Nullability.legacy)),
VariableGet(argument)
], types: typeArguments))),
returnType: VoidType(),
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index e8562ab..9e3ba3ed 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -53,6 +53,7 @@
class _FfiUseSiteTransformer extends FfiTransformer {
final Map<Field, Procedure> replacedGetters;
final Map<Field, Procedure> replacedSetters;
+ StaticTypeContext _staticTypeContext;
Library currentLibrary;
bool get isFfiLibrary => currentLibrary == ffiLibrary;
@@ -79,7 +80,6 @@
@override
visitClass(Class node) {
- env.thisType = InterfaceType(node, Nullability.legacy);
try {
_ensureNotExtendsOrImplementsSealedClass(node);
return super.visitClass(node);
@@ -88,12 +88,34 @@
// cause compilation to fail. By continuing, we can report more
// diagnostics before compilation ends.
return super.visitClass(node);
- } finally {
- env.thisType = null;
}
}
@override
+ visitField(Field node) {
+ _staticTypeContext = new StaticTypeContext(node, env);
+ var result = super.visitField(node);
+ _staticTypeContext = null;
+ return result;
+ }
+
+ @override
+ visitConstructor(Constructor node) {
+ _staticTypeContext = new StaticTypeContext(node, env);
+ var result = super.visitConstructor(node);
+ _staticTypeContext = null;
+ return result;
+ }
+
+ @override
+ visitProcedure(Procedure node) {
+ _staticTypeContext = new StaticTypeContext(node, env);
+ var result = super.visitProcedure(node);
+ _staticTypeContext = null;
+ return result;
+ }
+
+ @override
visitPropertyGet(PropertyGet node) {
super.visitPropertyGet(node);
@@ -128,7 +150,7 @@
final DartType nativeType = InterfaceType(
nativeFunctionClass, Nullability.legacy, [node.arguments.types[0]]);
final Expression func = node.arguments.positional[0];
- final DartType dartType = func.getStaticType(env);
+ final DartType dartType = func.getStaticType(_staticTypeContext);
_ensureIsStaticFunction(func);
@@ -189,7 +211,8 @@
return node;
}
- final DartType returnType = exceptionalReturn.getStaticType(env);
+ final DartType returnType =
+ exceptionalReturn.getStaticType(_staticTypeContext);
if (!env.isSubtypeOf(returnType, funcType.returnType,
SubtypeCheckMode.ignoringNullabilities)) {
@@ -299,7 +322,8 @@
return _replaceLookupFunction(node);
} else if (target == asFunctionMethod) {
final DartType dartType = node.arguments.types[0];
- final DartType pointerType = node.receiver.getStaticType(env);
+ final DartType pointerType =
+ node.receiver.getStaticType(_staticTypeContext);
final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
_ensureNativeTypeValid(pointerType, node);
@@ -313,7 +337,8 @@
} else if (target == elementAtMethod) {
// TODO(37773): When moving to extension methods we can get rid of
// this rewiring.
- final DartType pointerType = node.receiver.getStaticType(env);
+ final DartType pointerType =
+ node.receiver.getStaticType(_staticTypeContext);
final DartType nativeType = _pointerTypeGetTypeArg(pointerType);
if (nativeType is TypeParameterType) {
// Do not rewire generic invocations.
diff --git a/pkg/vm/lib/transformations/late_var_init_transformer.dart b/pkg/vm/lib/transformations/late_var_init_transformer.dart
new file mode 100644
index 0000000..2e916d0
--- /dev/null
+++ b/pkg/vm/lib/transformations/late_var_init_transformer.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2019, 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.
+
+import 'package:kernel/ast.dart';
+
+/// Wraps the initializers of late local variables in closures.
+void transformLibraries(List<Library> libraries) {
+ const transformer = _LateVarInitTransformer();
+ libraries.forEach(transformer.visitLibrary);
+}
+
+class _LateVarInitTransformer extends Transformer {
+ const _LateVarInitTransformer();
+
+ bool _shouldApplyTransform(VariableDeclaration v) {
+ // This transform only applies to late variables.
+ if (!v.isLate) return false;
+
+ // Const variables are ignored.
+ if (v.isConst) return false;
+
+ // Variables with no initializer or a trivial initializer are ignored.
+ if (v.initializer == null) return false;
+ final Expression init = v.initializer;
+ if (init is StringLiteral) return false;
+ if (init is BoolLiteral) return false;
+ if (init is IntLiteral) return false;
+ if (init is DoubleLiteral) return false;
+ if (init is NullLiteral) return false;
+ if (init is ConstantExpression && init.constant is PrimitiveConstant) {
+ return false;
+ }
+
+ return true;
+ }
+
+ List<Statement> _transformVariableDeclaration(
+ TreeNode parent, VariableDeclaration node) {
+ super.visitVariableDeclaration(node);
+
+ final fnNode =
+ FunctionNode(ReturnStatement(node.initializer), returnType: node.type);
+ final fn = FunctionDeclaration(
+ VariableDeclaration("#${node.name}#initializer",
+ type: fnNode.thisFunctionType),
+ fnNode)
+ ..parent = parent;
+ node.initializer =
+ MethodInvocation(VariableGet(fn.variable), Name("call"), Arguments([]))
+ ..parent = node;
+
+ return [fn, node];
+ }
+
+ void _transformStatements(TreeNode parent, List<Statement> statements) {
+ List<Statement> oldStatements = statements;
+ for (var i = 0; i < oldStatements.length; ++i) {
+ Statement s = oldStatements[i];
+ if (s is VariableDeclaration && _shouldApplyTransform(s)) {
+ if (oldStatements == statements) {
+ oldStatements = List<Statement>.of(statements);
+ statements.clear();
+ }
+ statements.addAll(_transformVariableDeclaration(parent, s));
+ } else if (oldStatements != statements) {
+ statements.add(s.accept<TreeNode>(this)..parent = parent);
+ } else {
+ statements[i] = s.accept<TreeNode>(this)..parent = parent;
+ }
+ }
+ }
+
+ @override
+ visitBlock(Block node) {
+ _transformStatements(node, node.statements);
+ return node;
+ }
+
+ @override
+ visitAssertBlock(AssertBlock node) {
+ _transformStatements(node, node.statements);
+ return node;
+ }
+}
diff --git a/pkg/vm/lib/transformations/mixin_deduplication.dart b/pkg/vm/lib/transformations/mixin_deduplication.dart
index 610a20d..fcf8224 100644
--- a/pkg/vm/lib/transformations/mixin_deduplication.dart
+++ b/pkg/vm/lib/transformations/mixin_deduplication.dart
@@ -9,7 +9,28 @@
/// De-duplication of identical mixin applications.
void transformComponent(Component component) {
final deduplicateMixins = new DeduplicateMixinsTransformer();
+ final interfaceTargetResolver = InterfaceTargetResolver(deduplicateMixins);
+
+ // Deduplicate mixins and re-resolve super initializers.
+ // (this is a shallow transformation)
component.libraries.forEach(deduplicateMixins.visitLibrary);
+
+ // Do a deep transformation to re-resolve all interface targets that point to
+ // members of removed mixin application classes.
+
+ // This is necessary iff the component was assembled from individual modular
+ // kernel compilations:
+ //
+ // * if the CFE reads in the entire program as source, interface targets
+ // will point to the original mixin class
+ //
+ // * if the CFE reads in dependencies as kernel, interface targets will
+ // point to the already existing mixin application classes.
+ //
+ // TODO(dartbug.com/39375): Remove this extra O(N) pass over the AST if the
+ // CFE decides to consistently let the interface target point to the mixin
+ // class (instead of mixin application).
+ component.libraries.forEach(interfaceTargetResolver.visitLibrary);
}
class _DeduplicateMixinKey {
@@ -59,20 +80,12 @@
@override
TreeNode visitLibrary(Library node) {
- // ignore: DEPRECATED_MEMBER_USE
- if (!node.isExternal) {
- transformList(node.classes, this, node);
- }
+ transformList(node.classes, this, node);
return node;
}
@override
TreeNode visitClass(Class c) {
- // ignore: DEPRECATED_MEMBER_USE
- if (c.enclosingLibrary.isExternal) {
- return c;
- }
-
if (_duplicatedMixins.containsKey(c)) {
return null; // Class was de-duplicated already, just remove it.
}
@@ -96,7 +109,6 @@
if (canonical != c) {
c.canonicalName?.unbind();
_duplicatedMixins[c] = canonical;
- // print('Replacing $c with $canonical');
return null; // Remove class.
}
@@ -128,6 +140,73 @@
throw 'Unexpected node ${node.runtimeType}: $node';
}
+/// Rewrites interface targets to point to the deduplicated mixin application
+/// class.
+class InterfaceTargetResolver extends RecursiveVisitor<TreeNode> {
+ final DeduplicateMixinsTransformer transformer;
+
+ InterfaceTargetResolver(this.transformer);
+
+ defaultTreeNode(TreeNode node) {
+ node.visitChildren(this);
+ return node;
+ }
+
+ visitPropertyGet(PropertyGet node) {
+ node.interfaceTarget = _resolveNewInterfaceTarget(node.interfaceTarget);
+ return super.visitPropertyGet(node);
+ }
+
+ visitPropertySet(PropertySet node) {
+ node.interfaceTarget = _resolveNewInterfaceTarget(node.interfaceTarget);
+ return super.visitPropertySet(node);
+ }
+
+ visitMethodInvocation(MethodInvocation node) {
+ node.interfaceTarget = _resolveNewInterfaceTarget(node.interfaceTarget);
+ return super.visitMethodInvocation(node);
+ }
+
+ visitSuperPropertyGet(SuperPropertyGet node) {
+ node.interfaceTarget = _resolveNewInterfaceTarget(node.interfaceTarget);
+ return super.visitSuperPropertyGet(node);
+ }
+
+ visitSuperPropertySet(SuperPropertySet node) {
+ node.interfaceTarget = _resolveNewInterfaceTarget(node.interfaceTarget);
+ return super.visitSuperPropertySet(node);
+ }
+
+ visitSuperMethodInvocation(SuperMethodInvocation node) {
+ node.interfaceTarget = _resolveNewInterfaceTarget(node.interfaceTarget);
+ return super.visitSuperMethodInvocation(node);
+ }
+
+ Member _resolveNewInterfaceTarget(Member m) {
+ final Class c = m?.enclosingClass;
+ if (c != null && c.isAnonymousMixin) {
+ final Class replacement = transformer._duplicatedMixins[c];
+ if (replacement != null) {
+ // The class got removed, so we need to re-resolve the interface target.
+ return _findMember(replacement, m);
+ }
+ }
+ return m;
+ }
+
+ Member _findMember(Class klass, Member m) {
+ if (m is Field) {
+ return klass.members.where((other) => other.name == m.name).single;
+ } else if (m is Procedure) {
+ return klass.procedures
+ .where((other) => other.kind == m.kind && other.name == m.name)
+ .single;
+ } else {
+ throw 'Hit unexpected interface target which is not a Field/Procedure';
+ }
+ }
+}
+
/// Corrects forwarding constructors inserted by mixin resolution after
/// replacing superclass.
void _correctForwardingConstructors(Class c, Class oldSuper, Class newSuper) {
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 259d06e..b03f943 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -133,8 +133,8 @@
final nsmArgs = new Args<Type>([
receiver,
- new Type.cone(
- typeFlowAnalysis.environment.coreTypes.invocationLegacyRawType)
+ typeFlowAnalysis.hierarchyCache.fromStaticType(
+ typeFlowAnalysis.environment.coreTypes.invocationLegacyRawType, false)
]);
final nsmInvocation =
@@ -346,7 +346,7 @@
// Calculate result as a union of results of direct invocations
// corresponding to each target.
- Type result = new Type.empty();
+ Type result = const EmptyType();
if (targets.isEmpty) {
tracePrint("No targets...");
@@ -438,9 +438,8 @@
}
if (selector is InterfaceSelector) {
- final staticReceiverType = new Type.fromStatic(typeFlowAnalysis
- .environment.coreTypes
- .legacyRawType(selector.member.enclosingClass));
+ final staticReceiverType = new ConeType(typeFlowAnalysis.hierarchyCache
+ .getTFClass(selector.member.enclosingClass));
receiver = receiver.intersection(
staticReceiverType, typeFlowAnalysis.hierarchyCache);
assertx(receiver is! NullableType);
@@ -455,7 +454,7 @@
// invocation to the receiver class. A new allocated class discovered
// in the receiver cone will invalidate this invocation.
receiver = typeFlowAnalysis.hierarchyCache
- .specializeTypeCone((receiver as ConeType).dartType);
+ .specializeTypeCone((receiver as ConeType).cls);
}
assertx(targets.isEmpty);
@@ -497,10 +496,11 @@
ConcreteType receiver,
Map<Member, _ReceiverTypeBuilder> targets,
TypeFlowAnalysis typeFlowAnalysis) {
- Class class_ = receiver.classNode;
+ final TFClass cls = receiver.cls;
- Member target = typeFlowAnalysis.hierarchyCache.hierarchy
- .getDispatchTarget(class_, selector.name, setter: selector.isSetter);
+ Member target = typeFlowAnalysis.hierarchyCache.hierarchy.getDispatchTarget(
+ cls.classNode, selector.name,
+ setter: selector.isSetter);
if (target != null) {
if (kPrintTrace) {
@@ -508,7 +508,7 @@
}
_getReceiverTypeBuilder(targets, target).addConcreteType(receiver);
} else {
- if (typeFlowAnalysis.hierarchyCache.hasNonTrivialNoSuchMethod(class_)) {
+ if (typeFlowAnalysis.hierarchyCache.hasNonTrivialNoSuchMethod(cls)) {
if (kPrintTrace) {
tracePrint("Found non-trivial noSuchMethod for receiver $receiver");
}
@@ -652,7 +652,7 @@
_type = null;
}
- assertx(_list.last.classId.compareTo(type.classId) < 0);
+ assertx(_list.last.cls.id < type.cls.id);
_list.add(type);
}
@@ -762,8 +762,8 @@
/// Flag indicating if field initializer was executed.
bool isInitialized = false;
- _FieldValue(this.field, this.typeGuardSummary)
- : staticType = new Type.fromStatic(field.type) {
+ _FieldValue(this.field, this.typeGuardSummary, TypesBuilder typesBuilder)
+ : staticType = typesBuilder.fromStaticType(field.type, true) {
if (field.initializer == null && _isDefaultValueOfFieldObservable()) {
value = new Type.nullable(const EmptyType());
} else {
@@ -872,24 +872,24 @@
_DynamicTargetSet(this.selector, this.isObjectMember);
}
-class _ClassData extends _DependencyTracker implements ClassId<_ClassData> {
- final int _id;
- final Class class_;
- final Set<_ClassData> supertypes; // List of super-types including this.
- final Set<_ClassData> _allocatedSubtypes = new Set<_ClassData>();
+class _TFClassImpl extends TFClass {
+ final Set<_TFClassImpl> supertypes; // List of super-types including this.
+ final Set<_TFClassImpl> _allocatedSubtypes = new Set<_TFClassImpl>();
+ final _DependencyTracker dependencyTracker = new _DependencyTracker();
/// Flag indicating if this class has a noSuchMethod() method not inherited
/// from Object.
/// Lazy initialized by ClassHierarchyCache.hasNonTrivialNoSuchMethod().
bool hasNonTrivialNoSuchMethod;
- _ClassData(this._id, this.class_, this.supertypes) {
+ _TFClassImpl(int id, Class classNode, this.supertypes)
+ : super(id, classNode) {
supertypes.add(this);
}
ConcreteType _concreteType;
ConcreteType get concreteType =>
- _concreteType ??= new ConcreteType(this, class_, null);
+ _concreteType ??= new ConcreteType(this, null);
Type _specializedConeType;
Type get specializedConeType =>
@@ -898,7 +898,7 @@
Type _calculateConeTypeSpecialization() {
final int numSubTypes = _allocatedSubtypes.length;
if (numSubTypes == 0) {
- return new Type.empty();
+ return const EmptyType();
} else if (numSubTypes == 1) {
return _allocatedSubtypes.single.concreteType;
} else {
@@ -913,25 +913,11 @@
}
}
- void addAllocatedSubtype(_ClassData subType) {
+ void addAllocatedSubtype(_TFClassImpl subType) {
_allocatedSubtypes.add(subType);
_specializedConeType = null; // Reset cached specialization.
}
- @override
- int get hashCode => _id;
-
- @override
- bool operator ==(other) =>
- identical(this, other) ||
- (other is _ClassData) && (this._id == other._id);
-
- @override
- int compareTo(_ClassData other) => this._id.compareTo(other._id);
-
- @override
- String toString() => "_C $class_";
-
String dump() => "$this {supers: $supertypes}";
}
@@ -1000,12 +986,13 @@
}
}
-class _ClassHierarchyCache implements TypeHierarchy {
+// TODO(alexmarkov): Rename to _TypeHierarchyImpl.
+class _ClassHierarchyCache extends TypeHierarchy {
final TypeFlowAnalysis _typeFlowAnalysis;
final ClosedWorldClassHierarchy hierarchy;
final TypeEnvironment environment;
final Set<Class> allocatedClasses = new Set<Class>();
- final Map<Class, _ClassData> classes = <Class, _ClassData>{};
+ final Map<Class, _TFClassImpl> classes = <Class, _TFClassImpl>{};
final GenericInterfacesInfo genericInterfacesInfo;
/// Object.noSuchMethod().
@@ -1027,35 +1014,39 @@
_ClassHierarchyCache(this._typeFlowAnalysis, this.hierarchy,
this.genericInterfacesInfo, this.environment)
: objectNoSuchMethod = hierarchy.getDispatchTarget(
- environment.coreTypes.objectClass, noSuchMethodName) {
+ environment.coreTypes.objectClass, noSuchMethodName),
+ super(environment.coreTypes) {
assertx(objectNoSuchMethod != null);
}
- _ClassData getClassData(Class c) {
- return classes[c] ??= _createClassData(c);
+ @override
+ _TFClassImpl getTFClass(Class c) {
+ return classes[c] ??= _createTFClass(c);
}
- _ClassData _createClassData(Class c) {
- final supertypes = new Set<_ClassData>();
+ _TFClassImpl _createTFClass(Class c) {
+ final supertypes = new Set<_TFClassImpl>();
for (var sup in c.supers) {
- supertypes.addAll(getClassData(sup.classNode).supertypes);
+ supertypes.addAll(getTFClass(sup.classNode).supertypes);
}
- return new _ClassData(++_classIdCounter, c, supertypes);
+ return new _TFClassImpl(++_classIdCounter, c, supertypes);
}
ConcreteType addAllocatedClass(Class cl) {
assertx(!cl.isAbstract);
assertx(!_sealed);
- final _ClassData classData = getClassData(cl);
+ final _TFClassImpl classImpl = getTFClass(cl);
if (allocatedClasses.add(cl)) {
- classData.addAllocatedSubtype(classData);
- classData.invalidateDependentInvocations(_typeFlowAnalysis.workList);
+ classImpl.addAllocatedSubtype(classImpl);
+ classImpl.dependencyTracker
+ .invalidateDependentInvocations(_typeFlowAnalysis.workList);
- for (var supertype in classData.supertypes) {
- supertype.addAllocatedSubtype(classData);
- supertype.invalidateDependentInvocations(_typeFlowAnalysis.workList);
+ for (var supertype in classImpl.supertypes) {
+ supertype.addAllocatedSubtype(classImpl);
+ supertype.dependencyTracker
+ .invalidateDependentInvocations(_typeFlowAnalysis.workList);
}
for (var targetSet in _dynamicTargets.values) {
@@ -1063,7 +1054,7 @@
}
}
- return classData.concreteType;
+ return classImpl.concreteType;
}
void seal() {
@@ -1071,112 +1062,58 @@
}
@override
- bool isSubtype(DartType subType, DartType superType) {
+ bool isSubtype(Class sub, Class sup) {
if (kPrintTrace) {
- tracePrint("isSubtype for sub = $subType (${subType.runtimeType}),"
- " sup = $superType (${superType.runtimeType})");
+ tracePrint("isSubtype for sub = $sub, sup = $sup");
}
- if (subType == superType) {
+ if (identical(sub, sup)) {
return true;
}
- if (superType is DynamicType ||
- superType is VoidType ||
- subType is BottomType) {
- return true;
- }
- if (subType is DynamicType ||
- subType is VoidType ||
- superType is BottomType) {
- return false;
- }
-
- // TODO(alexmarkov): handle function types properly
- if (subType is FunctionType) {
- subType = _typeFlowAnalysis.environment.functionLegacyRawType;
- }
- if (superType is FunctionType) {
- superType = _typeFlowAnalysis.environment.functionLegacyRawType;
- }
- // TODO(alexmarkov): handle generic types properly.
- assertx(subType is! TypeParameterType);
- assertx(superType is! TypeParameterType);
-
- assertx(subType is InterfaceType, details: subType); // TODO(alexmarkov)
- assertx(superType is InterfaceType, details: superType); // TODO(alexmarkov)
-
- // InterfaceTypes should be raw, since we don't handle type arguments
- // (although frankly we can't distinguish between raw C and C<dynamic).
- assertx((subType as InterfaceType)
- .typeArguments
- .every((t) => t == const DynamicType()));
- assertx((superType as InterfaceType)
- .typeArguments
- .every((t) => t == const DynamicType()));
-
- Class subClass = (subType as InterfaceType).classNode;
- Class superClass = (superType as InterfaceType).classNode;
- if (subClass == superClass) {
+ // TODO(alexmarkov): handle FutureOr more precisely.
+ if (sup == coreTypes.futureOrClass) {
return true;
}
- // TODO(alexmarkov): handle FutureOr more precisely (requires generics).
- if (superClass == _typeFlowAnalysis.environment.futureOrClass) {
- return true;
- }
-
- _ClassData subClassData = getClassData(subClass);
- _ClassData superClassData = getClassData(superClass);
+ _TFClassImpl subClassData = getTFClass(sub);
+ _TFClassImpl superClassData = getTFClass(sup);
return subClassData.supertypes.contains(superClassData);
}
@override
- Type specializeTypeCone(DartType base) {
+ Type specializeTypeCone(TFClass baseClass) {
if (kPrintTrace) {
- tracePrint("specializeTypeCone for $base");
+ tracePrint("specializeTypeCone for $baseClass");
}
Statistics.typeConeSpecializations++;
- // TODO(alexmarkov): handle function types properly
- if (base is FunctionType) {
- base = _typeFlowAnalysis.environment.functionLegacyRawType;
- }
-
- if (base is TypeParameterType) {
- base = (base as TypeParameterType).bound;
- }
-
- assertx(base is InterfaceType); // TODO(alexmarkov)
- final baseClass = (base as InterfaceType).classNode;
-
- // TODO(alexmarkov): take type arguments into account.
-
// TODO(alexmarkov): consider approximating type if number of allocated
// subtypes is too large
- if (base == const DynamicType() ||
- base == _typeFlowAnalysis.environment.coreTypes.objectLegacyRawType ||
- // TODO(alexmarkov): handle FutureOr more precisely (requires generics).
- baseClass == _typeFlowAnalysis.environment.futureOrClass) {
+ // TODO(alexmarkov): handle FutureOr more precisely.
+
+ if (baseClass.classNode == coreTypes.objectClass ||
+ baseClass.classNode == coreTypes.futureOrClass) {
return const AnyType();
}
- _ClassData classData = getClassData(baseClass);
+ final _TFClassImpl cls = baseClass as _TFClassImpl;
if (!_sealed) {
- classData.addDependentInvocation(_typeFlowAnalysis.currentInvocation);
+ cls.dependencyTracker
+ .addDependentInvocation(_typeFlowAnalysis.currentInvocation);
}
- return classData.specializedConeType;
+ return cls.specializedConeType;
}
- bool hasNonTrivialNoSuchMethod(Class c) {
- final classData = getClassData(c);
- classData.hasNonTrivialNoSuchMethod ??=
- (hierarchy.getDispatchTarget(c, noSuchMethodName) !=
+ bool hasNonTrivialNoSuchMethod(TFClass c) {
+ final classImpl = c as _TFClassImpl;
+ classImpl.hasNonTrivialNoSuchMethod ??=
+ (hierarchy.getDispatchTarget(c.classNode, noSuchMethodName) !=
objectNoSuchMethod);
- return classData.hasNonTrivialNoSuchMethod;
+ return classImpl.hasNonTrivialNoSuchMethod;
}
_DynamicTargetSet getDynamicTargetSet(DynamicSelector selector) {
@@ -1236,11 +1173,6 @@
buf.write("}\n");
return buf.toString();
}
-
- Class get futureOrClass => environment.coreTypes.futureOrClass;
- Class get futureClass => environment.coreTypes.futureClass;
- Class get functionClass => environment.coreTypes.functionClass;
- CoreTypes get coreTypes => environment.coreTypes;
}
class _WorkList {
@@ -1353,8 +1285,8 @@
}
// Fall back to static type.
Statistics.recursiveInvocationsApproximated++;
- final staticType =
- new Type.fromStatic(invocation.selector.staticReturnType);
+ final staticType = _typeFlowAnalysis.hierarchyCache
+ .fromStaticType(invocation.selector.staticReturnType, true);
if (kPrintTrace) {
tracePrint(
"Approximated recursive invocation with static type $staticType");
@@ -1398,8 +1330,8 @@
nativeCodeOracle = new NativeCodeOracle(libraryIndex, annotationMatcher);
hierarchyCache = new _ClassHierarchyCache(
this, hierarchy, _genericInterfacesInfo, environment);
- summaryCollector = new SummaryCollector(
- target, environment, hierarchy, this, nativeCodeOracle, hierarchyCache);
+ summaryCollector = new SummaryCollector(target, environment, hierarchy,
+ this, hierarchyCache, nativeCodeOracle, hierarchyCache);
_invocationsCache = new _InvocationsCache(this);
workList = new _WorkList(this);
@@ -1419,7 +1351,8 @@
setterSummary = summaryCollector.createSummary(field,
fieldSummaryType: FieldSummaryType.kFieldGuard);
}
- return _fieldValues[field] ??= new _FieldValue(field, setterSummary);
+ return _fieldValues[field] ??=
+ new _FieldValue(field, setterSummary, hierarchyCache);
}
void process() {
@@ -1528,8 +1461,7 @@
if (field.isStatic) {
fieldValue.setValue(value, this, /*receiver_type=*/ null);
} else {
- final receiver =
- new Type.cone(new InterfaceType(field.parent, Nullability.legacy));
+ final receiver = new ConeType(hierarchyCache.getTFClass(field.parent));
fieldValue.setValue(value, this, receiver);
}
}
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index 3f06a5d..c9093dd 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -191,8 +191,8 @@
/// Simulate the execution of a native method by adding its entry points
/// using [entryPointsListener]. Returns result type of the native method.
- Type handleNativeProcedure(
- Member member, EntryPointsListener entryPointsListener) {
+ Type handleNativeProcedure(Member member,
+ EntryPointsListener entryPointsListener, TypesBuilder typesBuilder) {
Type returnType = null;
bool nullable = null;
@@ -243,8 +243,8 @@
if (returnType != null) {
return returnType;
} else {
- final coneType = new Type.cone(member.function.returnType);
- return nullable == false ? coneType : new Type.nullable(coneType);
+ return typesBuilder.fromStaticType(
+ member.function.returnType, nullable ?? true);
}
}
}
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index efcf37f..9589729 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -317,7 +317,7 @@
extractedType = const AnyType();
} else {
final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor(
- c.classNode, referenceClass);
+ c.cls.classNode, referenceClass);
final extract = c.typeArgs[interfaceOffset + paramIndex];
assertx(extract is AnyType || extract is RuntimeType);
if (extractedType == null || extract == extractedType) {
@@ -345,10 +345,10 @@
// The type arguments are factored against the generic interfaces; for more
// details see 'ClassHierarchyCache.factoredGenericInterfacesOf'.
class CreateConcreteType extends Statement {
- final ConcreteType type;
+ final TFClass cls;
final List<TypeExpr> flattenedTypeArgs;
- CreateConcreteType(this.type, this.flattenedTypeArgs);
+ CreateConcreteType(this.cls, this.flattenedTypeArgs);
@override
void accept(StatementVisitor visitor) =>
@@ -356,8 +356,8 @@
@override
String dump() {
- int numImmediateTypeArgs = type.classNode.typeParameters.length;
- return "$label = _CreateConcreteType (${type.classNode} @ "
+ int numImmediateTypeArgs = cls.classNode.typeParameters.length;
+ return "$label = _CreateConcreteType ($cls @ "
"${flattenedTypeArgs.take(numImmediateTypeArgs)})";
}
@@ -372,8 +372,7 @@
if (computed is RuntimeType) hasRuntimeType = true;
types[i] = computed;
}
- return new ConcreteType(
- type.classId, type.classNode, hasRuntimeType ? types : null);
+ return new ConcreteType(cls, hasRuntimeType ? types : null);
}
}
@@ -465,7 +464,8 @@
} else if (checkType is RuntimeType) {
canSkip = argType.isSubtypeOfRuntimeType(typeHierarchy, checkType);
argType = argType.intersection(
- Type.fromStatic(checkType.representedTypeRaw), typeHierarchy);
+ typeHierarchy.fromStaticType(checkType.representedTypeRaw, true),
+ typeHierarchy);
} else {
assertx(false, details: "Cannot see $checkType on RHS of TypeCheck.");
}
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 23902dc..3385c08 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -11,7 +11,8 @@
import 'package:kernel/ast.dart' hide Statement, StatementVisitor;
import 'package:kernel/ast.dart' as ast show Statement, StatementVisitor;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-import 'package:kernel/type_environment.dart' show TypeEnvironment;
+import 'package:kernel/type_environment.dart'
+ show StaticTypeContext, TypeEnvironment;
import 'package:kernel/type_algebra.dart' show Substitution;
import 'calls.dart';
@@ -32,11 +33,12 @@
/// * Eliminates joins with a single input.
class _SummaryNormalizer extends StatementVisitor {
final Summary _summary;
+ final TypesBuilder _typesBuilder;
Set<Statement> _processed = new Set<Statement>();
Set<Statement> _pending = new Set<Statement>();
bool _inLoop = false;
- _SummaryNormalizer(this._summary);
+ _SummaryNormalizer(this._summary, this._typesBuilder);
void normalize() {
final List<Statement> statements = _summary.statements;
@@ -132,7 +134,7 @@
_inLoop = false;
debugPrint("Approximated ${st} with ${st.staticType}");
Statistics.joinsApproximatedToBreakLoops++;
- return new Type.fromStatic(st.staticType);
+ return _typesBuilder.fromStaticType(st.staticType, true);
} else {
// Step back until Join is found.
_inLoop = true;
@@ -295,6 +297,7 @@
final TypeEnvironment _environment;
final ClassHierarchy _hierarchy;
final EntryPointsListener _entryPointsListener;
+ final TypesBuilder _typesBuilder;
final NativeCodeOracle _nativeCodeOracle;
final GenericInterfacesInfo _genericInterfacesInfo;
@@ -310,6 +313,7 @@
Parameter _receiver;
ConstantAllocationCollector constantAllocationCollector;
RuntimeTypeTranslator _translator;
+ StaticTypeContext _staticTypeContext;
// Currently only used for factory constructors.
Map<TypeParameter, TypeExpr> _fnTypeVariables;
@@ -319,6 +323,7 @@
this._environment,
this._hierarchy,
this._entryPointsListener,
+ this._typesBuilder,
this._nativeCodeOracle,
this._genericInterfacesInfo) {
assertx(_genericInterfacesInfo != null);
@@ -330,6 +335,7 @@
debugPrint("===== ${member} =====");
assertx(!member.isAbstract);
+ _staticTypeContext = new StaticTypeContext(member, _environment);
_variableJoins = <VariableDeclaration, Join>{};
_variables = <VariableDeclaration, TypeExpr>{};
_returnValue = null;
@@ -347,7 +353,6 @@
_receiver = _declareParameter("this",
_environment.coreTypes.legacyRawType(member.enclosingClass), null,
isReceiver: true);
- _environment.thisType = member.enclosingClass?.thisType;
} else {
_summary = new Summary();
}
@@ -361,8 +366,8 @@
} else {
Parameter valueParam = _declareParameter("value", member.type, null);
TypeExpr runtimeType = _translator.translate(member.type);
- final check = new TypeCheck(
- valueParam, runtimeType, member, Type.fromStatic(member.type));
+ final check = new TypeCheck(valueParam, runtimeType, member,
+ _typesBuilder.fromStaticType(member.type, true));
_summary.add(check);
_summary.result = check;
}
@@ -394,7 +399,6 @@
_receiver = _declareParameter("this",
_environment.coreTypes.legacyRawType(member.enclosingClass), null,
isReceiver: true);
- _environment.thisType = member.enclosingClass?.thisType;
}
_translator = new RuntimeTypeTranslator(
@@ -468,7 +472,7 @@
if (function.body == null) {
Type type = _nativeCodeOracle.handleNativeProcedure(
- member, _entryPointsListener);
+ member, _entryPointsListener, _typesBuilder);
if (type is! ConcreteType) {
// Runtime type could be more precise than static type, so
// calculate intersection.
@@ -488,14 +492,15 @@
}
_summary.result = _returnValue;
- _environment.thisType = null;
}
+ _staticTypeContext = null;
+
debugPrint("------------ SUMMARY ------------");
debugPrint(_summary);
debugPrint("---------------------------------");
- new _SummaryNormalizer(_summary).normalize();
+ new _SummaryNormalizer(_summary, _typesBuilder).normalize();
debugPrint("---------- NORM SUMMARY ---------");
debugPrint(_summary);
@@ -524,8 +529,8 @@
if (hasReceiverArg(member)) {
assertx(member.enclosingClass != null);
- Type receiver = new Type.cone(
- _environment.coreTypes.legacyRawType(member.enclosingClass));
+ final receiver =
+ new ConeType(_typesBuilder.getTFClass(member.enclosingClass));
args.add(receiver);
}
@@ -605,7 +610,7 @@
{bool isReceiver: false}) {
Type staticType;
if (type != null) {
- staticType = isReceiver ? new ConeType(type) : new Type.fromStatic(type);
+ staticType = _typesBuilder.fromStaticType(type, !isReceiver);
}
final param = new Parameter(name, staticType);
_summary.add(param);
@@ -639,8 +644,8 @@
TypeExpr variable = join;
if (useTypeCheck) {
TypeExpr runtimeType = _translator.translate(type);
- variable = new TypeCheck(
- variable, runtimeType, decl, Type.fromStatic(decl.type));
+ variable = new TypeCheck(variable, runtimeType, decl,
+ _typesBuilder.fromStaticType(decl.type, true));
_summary.add(variable);
}
@@ -659,7 +664,7 @@
// TODO(alexmarkov): Avoid declaring variables with static types.
void _declareVariableWithStaticType(VariableDeclaration decl) {
Join v = _declareVariable(decl);
- v.values.add(new Type.fromStatic(v.staticType));
+ v.values.add(_typesBuilder.fromStaticType(v.staticType, true));
}
Call _makeCall(TreeNode node, Selector selector, Args<TypeExpr> args) {
@@ -696,43 +701,41 @@
}
}
- DartType _staticDartType(Expression node) {
- // TODO(dartbug.com/34496): Remove this try/catch once
- // getStaticType() is reliable.
- try {
- return node.getStaticType(_environment);
- } catch (e) {
- return const DynamicType();
- }
- }
+ DartType _staticDartType(Expression node) =>
+ node.getStaticType(_staticTypeContext);
Type _staticType(Expression node) =>
- new Type.fromStatic(_staticDartType(node));
+ _typesBuilder.fromStaticType(_staticDartType(node), true);
Type _cachedBoolType;
Type get _boolType => _cachedBoolType ??=
- new Type.cone(_environment.coreTypes.boolLegacyRawType);
+ new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.boolClass));
Type _cachedDoubleType;
- Type get _doubleType => _cachedDoubleType ??=
- new Type.cone(_environment.coreTypes.doubleLegacyRawType);
+ Type get _doubleType => _cachedDoubleType ??= new ConeType(
+ _typesBuilder.getTFClass(_environment.coreTypes.doubleClass));
Type _cachedIntType;
- Type get _intType =>
- _cachedIntType ??= new Type.cone(_environment.coreTypes.intLegacyRawType);
+ Type get _intType => _cachedIntType ??=
+ new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.intClass));
Type _cachedStringType;
- Type get _stringType => _cachedStringType ??=
- new Type.cone(_environment.coreTypes.stringLegacyRawType);
+ Type get _stringType => _cachedStringType ??= new ConeType(
+ _typesBuilder.getTFClass(_environment.coreTypes.stringClass));
Type _cachedSymbolType;
- Type get _symbolType => _cachedSymbolType ??=
- new Type.cone(_environment.coreTypes.symbolLegacyRawType);
+ Type get _symbolType => _cachedSymbolType ??= new ConeType(
+ _typesBuilder.getTFClass(_environment.coreTypes.symbolClass));
+
+ Type _cachedTypeType;
+ Type get _typeType => _cachedTypeType ??=
+ new ConeType(_typesBuilder.getTFClass(_environment.coreTypes.typeClass));
Type _cachedNullType;
- Type get _nullType => _cachedNullType ??= new Type.nullable(new Type.empty());
+ Type get _nullType =>
+ _cachedNullType ??= new Type.nullable(const EmptyType());
- Class get _superclass => _environment.thisType.classNode.superclass;
+ Class get _superclass => _staticTypeContext.thisType.classNode.superclass;
Type _intLiteralType(int value) {
Class concreteClass =
@@ -779,7 +782,7 @@
@override
TypeExpr visitAsExpression(AsExpression node) {
TypeExpr operand = _visit(node.operand);
- Type type = new Type.fromStatic(node.type);
+ Type type = _typesBuilder.fromStaticType(node.type, true);
TypeExpr runtimeType = _translator.translate(node.type);
TypeExpr result = new TypeCheck(operand, runtimeType, node, type);
explicitCasts[node] = result;
@@ -888,7 +891,7 @@
@override
TypeExpr visitInvalidExpression(InvalidExpression node) {
- return new Type.empty();
+ return const EmptyType();
}
@override
@@ -1009,7 +1012,7 @@
}
switch (elementTypes.length) {
case 0:
- return new Type.empty();
+ return const EmptyType();
case 1:
return elementTypes.single;
default:
@@ -1066,7 +1069,7 @@
// Re-resolve target due to partial mixin resolution.
final target = _hierarchy.getDispatchTarget(_superclass, node.name);
if (target == null) {
- return new Type.empty();
+ return const EmptyType();
} else {
if ((target is Field) || ((target is Procedure) && target.isGetter)) {
// Call via field/getter.
@@ -1094,7 +1097,7 @@
// Re-resolve target due to partial mixin resolution.
final target = _hierarchy.getDispatchTarget(_superclass, node.name);
if (target == null) {
- return new Type.empty();
+ return const EmptyType();
} else {
return _makeCall(node,
new DirectSelector(target, callKind: CallKind.PropertyGet), args);
@@ -1132,7 +1135,7 @@
@override
TypeExpr visitRethrow(Rethrow node) {
- return new Type.empty();
+ return const EmptyType();
}
@override
@@ -1188,12 +1191,12 @@
@override
TypeExpr visitThrow(Throw node) {
_visit(node.expression);
- return new Type.empty();
+ return const EmptyType();
}
@override
TypeExpr visitTypeLiteral(TypeLiteral node) {
- return new Type.cone(_environment.coreTypes.typeLegacyRawType);
+ return _typeType;
}
@override
@@ -1205,7 +1208,8 @@
if ((node.promotedType != null) &&
(node.promotedType != const DynamicType())) {
- return _makeNarrow(v, new Type.cone(node.promotedType));
+ return _makeNarrow(
+ v, _typesBuilder.fromStaticType(node.promotedType, false));
}
return v;
@@ -1303,7 +1307,7 @@
Join v = _declareVariable(node.variable);
// TODO(alexmarkov): support function types.
// v.values.add(_concreteType(node.function.functionType));
- v.values.add(new Type.fromStatic(v.staticType));
+ v.values.add(_typesBuilder.fromStaticType(v.staticType, true));
_handleNestedFunctionNode(node.function);
return null;
}
@@ -1472,7 +1476,7 @@
// This function is very similar to 'visitInterfaceType', but with
// many small differences.
- final klass = type.classNode;
+ final klass = type.cls.classNode;
final substitution = Substitution.fromPairs(klass.typeParameters, typeArgs);
final flattenedTypeArgs =
genericInterfacesInfo.flattenedTypeArgumentsFor(klass);
@@ -1491,10 +1495,10 @@
if (allAnyType) return type;
if (createConcreteType) {
- return new ConcreteType(type.classId, type.classNode,
- new List<Type>.from(flattenedTypeExprs));
+ return new ConcreteType(
+ type.cls, new List<Type>.from(flattenedTypeExprs));
} else {
- final instantiate = new CreateConcreteType(type, flattenedTypeExprs);
+ final instantiate = new CreateConcreteType(type.cls, flattenedTypeExprs);
summary.add(instantiate);
return instantiate;
}
@@ -1532,6 +1536,8 @@
TypeExpr visitVoidType(VoidType type) => new RuntimeType(type, null);
@override
TypeExpr visitBottomType(BottomType type) => new RuntimeType(type, null);
+ @override
+ TypeExpr visitNeverType(NeverType type) => new RuntimeType(type, null);
@override
visitTypedefType(TypedefType node) => translate(node.unalias);
@@ -1583,50 +1589,6 @@
}
}
-class EmptyEntryPointsListener implements EntryPointsListener {
- final Map<Class, IntClassId> _classIds = <Class, IntClassId>{};
- int _classIdCounter = 0;
-
- @override
- void addRawCall(Selector selector) {}
-
- @override
- void addDirectFieldAccess(Field field, Type value) {}
-
- @override
- ConcreteType addAllocatedClass(Class c) {
- final classId = (_classIds[c] ??= new IntClassId(++_classIdCounter));
- return new ConcreteType(classId, c, null);
- }
-
- @override
- void recordMemberCalledViaInterfaceSelector(Member target) {}
-
- @override
- void recordMemberCalledViaThis(Member target) {}
-}
-
-class CreateAllSummariesVisitor extends RecursiveVisitor<Null> {
- final SummaryCollector _summaryCollector;
-
- CreateAllSummariesVisitor(Target target, TypeEnvironment environment,
- ClassHierarchy hierarchy, GenericInterfacesInfo genericInterfacesInfo)
- : _summaryCollector = new SummaryCollector(
- target,
- environment,
- hierarchy,
- new EmptyEntryPointsListener(),
- new NativeCodeOracle(null, null),
- genericInterfacesInfo);
-
- @override
- defaultMember(Member m) {
- if (!m.isAbstract && !(m is Field && m.initializer == null)) {
- _summaryCollector.createSummary(m);
- }
- }
-}
-
class ConstantAllocationCollector extends ConstantVisitor<Type> {
final SummaryCollector summaryCollector;
@@ -1640,6 +1602,10 @@
return constants.putIfAbsent(constant, () => constant.accept(this));
}
+ Type _getStaticType(Constant constant) =>
+ summaryCollector._typesBuilder.fromStaticType(
+ constant.getType(summaryCollector._staticTypeContext), false);
+
@override
defaultConstant(Constant constant) {
throw 'There is no support for constant "$constant" in TFA yet!';
@@ -1689,7 +1655,7 @@
.concreteConstListLiteralClass(summaryCollector._environment.coreTypes);
return concreteClass != null
? summaryCollector._entryPointsListener.addAllocatedClass(concreteClass)
- : new Type.cone(constant.getType(summaryCollector._environment));
+ : _getStaticType(constant);
}
@override
@@ -1708,18 +1674,18 @@
final Procedure procedure = constant.procedure;
summaryCollector._entryPointsListener
.addRawCall(new DirectSelector(procedure));
- return new Type.cone(constant.getType(summaryCollector._environment));
+ return _getStaticType(constant);
}
@override
Type visitPartialInstantiationConstant(
PartialInstantiationConstant constant) {
constant.tearOffConstant.accept(this);
- return new Type.cone(constant.getType(summaryCollector._environment));
+ return _getStaticType(constant);
}
@override
Type visitTypeLiteralConstant(TypeLiteralConstant constant) {
- return new Type.cone(constant.getType(summaryCollector._environment));
+ return summaryCollector._typeType;
}
}
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index bde9684..a6289ea 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -17,7 +17,6 @@
import 'analysis.dart';
import 'calls.dart';
import 'summary.dart';
-import 'summary_collector.dart';
import 'types.dart';
import 'utils.dart';
import '../pragma.dart';
@@ -27,8 +26,6 @@
import '../../metadata/procedure_attributes.dart';
import '../../metadata/unreachable.dart';
-const bool kDumpAllSummaries =
- const bool.fromEnvironment('global.type.flow.dump.all.summaries');
const bool kDumpClassHierarchy =
const bool.fromEnvironment('global.type.flow.dump.class.hierarchy');
@@ -44,14 +41,6 @@
final libraryIndex = new LibraryIndex.all(component);
final genericInterfacesInfo = new GenericInterfacesInfoImpl(hierarchy);
- if (kDumpAllSummaries) {
- Statistics.reset();
- new CreateAllSummariesVisitor(
- target, types, hierarchy, genericInterfacesInfo)
- .visitComponent(component);
- Statistics.print("All summaries statistics");
- }
-
Statistics.reset();
final analysisStopWatch = new Stopwatch()..start();
@@ -123,14 +112,14 @@
final InferredTypeMetadataRepository _inferredTypeMetadata;
final UnreachableNodeMetadataRepository _unreachableNodeMetadata;
final ProcedureAttributesMetadataRepository _procedureAttributesMetadata;
- final DartType _intType;
+ final Class _intClass;
AnnotateKernel(Component component, this._typeFlowAnalysis)
: _inferredTypeMetadata = new InferredTypeMetadataRepository(),
_unreachableNodeMetadata = new UnreachableNodeMetadataRepository(),
_procedureAttributesMetadata =
new ProcedureAttributesMetadataRepository(),
- _intType = _typeFlowAnalysis.environment.coreTypes.intLegacyRawType {
+ _intClass = _typeFlowAnalysis.environment.coreTypes.intClass {
component.addMetadataRepository(_inferredTypeMetadata);
component.addMetadataRepository(_unreachableNodeMetadata);
component.addMetadataRepository(_procedureAttributesMetadata);
@@ -153,7 +142,7 @@
concreteClass = type.getConcreteClass(_typeFlowAnalysis.hierarchyCache);
if (concreteClass == null) {
- isInt = type.isSubtypeOf(_typeFlowAnalysis.hierarchyCache, _intType);
+ isInt = type.isSubtypeOf(_typeFlowAnalysis.hierarchyCache, _intClass);
}
}
@@ -653,7 +642,7 @@
if (shaker.isFieldInitializerReachable(node)) {
node.transformChildren(this);
} else {
- node.initializer = _makeUnreachableCall([]);
+ node.initializer = _makeUnreachableCall([])..parent = node;
}
}
} else if (shaker.isMemberReferencedFromNativeCode(node)) {
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 4f5bf7b..35ec3c5 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -13,6 +13,28 @@
import 'utils.dart';
+/// Dart class representation used in type flow analysis.
+/// For each Dart class there is a unique instance of [TFClass].
+/// Each [TFClass] has unique id which could be used to sort classes.
+class TFClass {
+ final int id;
+ final Class classNode;
+
+ /// TFClass should not be instantiated directly.
+ /// Instead, [TypeHierarchy.getTFClass] should be used to obtain [TFClass]
+ /// instances specific to given [TypeHierarchy].
+ TFClass(this.id, this.classNode);
+
+ @override
+ int get hashCode => id;
+
+ @override
+ bool operator ==(other) => identical(this, other);
+
+ @override
+ String toString() => classNode.toString();
+}
+
abstract class GenericInterfacesInfo {
// Return a type arguments vector which contains the immediate type parameters
// to 'klass' as well as the type arguments to all generic supertypes of
@@ -36,47 +58,61 @@
List<Type> flattenedTypeArgumentsForNonGeneric(Class klass);
}
+abstract class TypesBuilder {
+ final CoreTypes coreTypes;
+
+ TypesBuilder(this.coreTypes);
+
+ /// Return [TFClass] corresponding to the given [classNode].
+ TFClass getTFClass(Class classNode);
+
+ /// Create a Type which corresponds to a set of instances constrained by
+ /// Dart type annotation [dartType].
+ Type fromStaticType(DartType type, bool isNullable) {
+ Type result;
+ if (type is InterfaceType) {
+ final cls = type.classNode;
+ result = (cls == coreTypes.nullClass)
+ ? const EmptyType()
+ : new ConeType(getTFClass(cls));
+ } else if (type == const DynamicType() || type == const VoidType()) {
+ result = const AnyType();
+ } else if (type == const BottomType() || type is NeverType) {
+ result = const EmptyType();
+ } else if (type is FunctionType) {
+ // TODO(alexmarkov): support function types
+ result = const AnyType();
+ } else if (type is TypeParameterType) {
+ final bound = type.bound;
+ // Protect against infinite recursion in case of cyclic type parameters
+ // like 'T extends T'. As of today, front-end doesn't report errors in such
+ // cases yet.
+ if (bound is TypeParameterType) {
+ result = const AnyType();
+ } else {
+ return fromStaticType(bound, isNullable);
+ }
+ } else {
+ throw 'Unexpected type ${type.runtimeType} $type';
+ }
+ if (isNullable) {
+ result = new Type.nullable(result);
+ }
+ return result;
+ }
+}
+
/// Abstract interface to type hierarchy information used by types.
-abstract class TypeHierarchy implements GenericInterfacesInfo {
- /// Test if [subType] is a subtype of [superType].
- bool isSubtype(DartType subType, DartType superType);
+abstract class TypeHierarchy extends TypesBuilder
+ implements GenericInterfacesInfo {
+ TypeHierarchy(CoreTypes coreTypes) : super(coreTypes);
+
+ /// Test if [sub] is a subtype of [sup].
+ bool isSubtype(Class sub, Class sup);
/// Return a more specific type for the type cone with [base] root.
/// May return EmptyType, AnyType, ConcreteType or a SetType.
- Type specializeTypeCone(DartType base);
-
- Class get futureOrClass;
- Class get futureClass;
- Class get functionClass;
- CoreTypes get coreTypes;
-}
-
-/// Basic normalization of Dart types.
-/// Currently used to approximate generic and function types.
-DartType _normalizeDartType(DartType type) {
- if (type is InterfaceType) {
- // TODO(alexmarkov): take generic type arguments into account
- // TODO(alexmarkov): cache the created raw type or use a CoreTypes object
- return new InterfaceType(
- type.classNode,
- Nullability.legacy,
- new List<DartType>.filled(
- type.classNode.typeParameters.length, const DynamicType()));
- } else if (type is FunctionType) {
- // TODO(alexmarkov): support function types
- return const DynamicType();
- } else if (type is TypeParameterType) {
- // TODO(alexmarkov): instantiate type parameters if possible
- final bound = type.bound;
- // Protect against infinite recursion in case of cyclic type parameters
- // like 'T extends T'. As of today, front-end doesn't report errors in such
- // cases yet.
- if (bound is TypeParameterType) {
- return const DynamicType();
- }
- return _normalizeDartType(bound);
- }
- return type;
+ Type specializeTypeCone(TFClass base);
}
/// Base class for type expressions.
@@ -96,54 +132,15 @@
abstract class Type extends TypeExpr {
const Type();
- /// Create an empty type.
- factory Type.empty() => const EmptyType();
-
- /// Create a non-nullable type representing a subtype cone. It contains
- /// instances of all Dart types which extend, mix-in or implement [dartType].
- factory Type.cone(DartType dartType) {
- dartType = _normalizeDartType(dartType);
- if ((dartType == const DynamicType()) || (dartType == const VoidType())) {
- return const AnyType();
- } else if (dartType == const BottomType()) {
- return new Type.empty();
- } else {
- return new ConeType(dartType);
- }
- }
-
/// Create a nullable type - union of [t] and the `null` object.
factory Type.nullable(Type t) => new NullableType(t);
/// Create a type representing arbitrary nullable object (`dynamic`).
factory Type.nullableAny() => new NullableType(const AnyType());
- /// Create a Type which corresponds to a set of instances constrained by
- /// Dart type annotation [dartType].
- factory Type.fromStatic(DartType dartType) {
- dartType = _normalizeDartType(dartType);
- if ((dartType == const DynamicType()) || (dartType == const VoidType())) {
- return new Type.nullableAny();
- } else if (dartType == const BottomType()) {
- return new Type.nullable(new Type.empty());
- } else if (
- // Recognize Null type and use a more precise representation which
- // doesn't need type specialization.
- // TODO(alexmarkov): figure out where exactly approximation happens if
- // Null is represented as Nullable(Cone(Null)) instead of
- // Nullable(Empty).
- dartType is InterfaceType &&
- dartType.classNode.name == 'Null' &&
- dartType.classNode.enclosingLibrary.importUri.scheme == 'dart' &&
- dartType.classNode.enclosingLibrary.importUri.path == 'core') {
- return new Type.nullable(new Type.empty());
- }
- return new Type.nullable(new ConeType(dartType));
- }
-
Class getConcreteClass(TypeHierarchy typeHierarchy) => null;
- bool isSubtypeOf(TypeHierarchy typeHierarchy, DartType dartType) => false;
+ bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) => false;
// 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
@@ -230,8 +227,8 @@
String toString() => "${baseType}?";
@override
- bool isSubtypeOf(TypeHierarchy typeHierarchy, DartType dartType) =>
- baseType.isSubtypeOf(typeHierarchy, dartType);
+ bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
+ baseType.isSubtypeOf(typeHierarchy, cls);
bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) =>
baseType.isSubtypeOfRuntimeType(typeHierarchy, other);
@@ -308,7 +305,11 @@
}
bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
- return typeHierarchy.isSubtype(const DynamicType(), other._type);
+ final rhs = other._type;
+ return (rhs is DynamicType) ||
+ (rhs is VoidType) ||
+ (rhs is InterfaceType &&
+ rhs.classNode == typeHierarchy.coreTypes.objectClass);
}
}
@@ -354,8 +355,8 @@
String toString() => "_T ${types}";
@override
- bool isSubtypeOf(TypeHierarchy typeHierarchy, DartType dartType) =>
- types.every((ConcreteType t) => t.isSubtypeOf(typeHierarchy, dartType));
+ 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));
@@ -371,11 +372,12 @@
while ((i1 < types1.length) && (i2 < types2.length)) {
final t1 = types1[i1];
final t2 = types2[i2];
- final relation = t1.classId.compareTo(t2.classId);
- if (relation < 0) {
+ final id1 = t1.cls.id;
+ final id2 = t2.cls.id;
+ if (id1 < id2) {
types.add(t1);
++i1;
- } else if (relation > 0) {
+ } else if (id1 > id2) {
types.add(t2);
++i2;
} else {
@@ -406,10 +408,11 @@
while ((i1 < types1.length) && (i2 < types2.length)) {
final t1 = types1[i1];
final t2 = types2[i2];
- final relation = t1.classId.compareTo(t2.classId);
- if (relation < 0) {
+ final id1 = t1.cls.id;
+ final id2 = t2.cls.id;
+ if (id1 < id2) {
++i1;
- } else if (relation > 0) {
+ } else if (id1 > id2) {
++i2;
} else {
if (t1.typeArgs == null && t2.typeArgs == null) {
@@ -440,7 +443,7 @@
: new SetType(_unionLists(types, <ConcreteType>[other]));
} else if (other is ConeType) {
return typeHierarchy
- .specializeTypeCone(other.dartType)
+ .specializeTypeCone(other.cls)
.union(this, typeHierarchy);
} else {
throw 'Unexpected type $other';
@@ -465,14 +468,14 @@
} else if (other is ConcreteType) {
for (var type in types) {
if (type == other) return other;
- if (type.classId == other.classId) {
+ if (identical(type.cls, other.cls)) {
return type.intersection(other, typeHierarchy);
}
}
return EmptyType();
} else if (other is ConeType) {
return typeHierarchy
- .specializeTypeCone(other.dartType)
+ .specializeTypeCone(other.cls)
.intersection(this, typeHierarchy);
} else {
throw 'Unexpected type $other';
@@ -481,42 +484,41 @@
}
/// Type representing a subtype cone. It contains instances of all
-/// Dart types which extend, mix-in or implement [dartType].
+/// Dart types which extend, mix-in or implement certain class.
/// TODO(alexmarkov): Introduce cones of types which extend but not implement.
class ConeType extends Type {
- final DartType dartType;
+ final TFClass cls;
- ConeType(this.dartType) {
- assertx(dartType != null);
- }
+ ConeType(this.cls);
@override
- Class getConcreteClass(TypeHierarchy typeHierarchy) => typeHierarchy
- .specializeTypeCone(dartType)
- .getConcreteClass(typeHierarchy);
+ Class getConcreteClass(TypeHierarchy typeHierarchy) =>
+ typeHierarchy.specializeTypeCone(cls).getConcreteClass(typeHierarchy);
@override
- bool isSubtypeOf(TypeHierarchy typeHierarchy, DartType dartType) =>
- typeHierarchy.isSubtype(this.dartType, dartType);
+ bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
+ typeHierarchy.isSubtype(this.cls.classNode, cls);
bool isSubtypeOfRuntimeType(TypeHierarchy typeHierarchy, RuntimeType other) {
- if (!typeHierarchy.isSubtype(dartType, other._type)) return false;
- if (dartType is InterfaceType) {
- return (dartType as InterfaceType).classNode.typeParameters.isEmpty;
+ final rhs = other._type;
+ if (rhs is DynamicType || rhs is VoidType) return true;
+ if (rhs is InterfaceType) {
+ return cls.classNode.typeParameters.isEmpty &&
+ typeHierarchy.isSubtype(cls.classNode, rhs.classNode);
}
- return true;
+ return false;
}
@override
- int get hashCode => (dartType.hashCode + 37) & kHashMask;
+ int get hashCode => (cls.id + 37) & kHashMask;
@override
bool operator ==(other) =>
identical(this, other) ||
- (other is ConeType) && (this.dartType == other.dartType);
+ (other is ConeType) && identical(this.cls, other.cls);
@override
- String toString() => "_T (${dartType})+";
+ String toString() => "_T ($cls)+";
@override
int get order => TypeOrder.Cone.index;
@@ -526,7 +528,7 @@
@override
Type specialize(TypeHierarchy typeHierarchy) =>
- typeHierarchy.specializeTypeCone(dartType);
+ typeHierarchy.specializeTypeCone(cls);
@override
Type union(Type other, TypeHierarchy typeHierarchy) {
@@ -537,22 +539,18 @@
if (this == other) {
return this;
}
- if (typeHierarchy.isSubtype(other.dartType, this.dartType)) {
+ if (typeHierarchy.isSubtype(other.cls.classNode, this.cls.classNode)) {
return this;
}
- if (typeHierarchy.isSubtype(this.dartType, other.dartType)) {
+ if (typeHierarchy.isSubtype(this.cls.classNode, other.cls.classNode)) {
return other;
}
} else if (other is ConcreteType) {
- if (typeHierarchy.isSubtype(
- typeHierarchy.coreTypes.legacyRawType(other.classNode),
- this.dartType)) {
+ if (typeHierarchy.isSubtype(other.cls.classNode, this.cls.classNode)) {
return this;
}
}
- return typeHierarchy
- .specializeTypeCone(dartType)
- .union(other, typeHierarchy);
+ return typeHierarchy.specializeTypeCone(cls).union(other, typeHierarchy);
}
@override
@@ -564,48 +562,29 @@
if (this == other) {
return this;
}
- if (typeHierarchy.isSubtype(other.dartType, this.dartType)) {
+ if (typeHierarchy.isSubtype(other.cls.classNode, this.cls.classNode)) {
return other;
}
- if (typeHierarchy.isSubtype(this.dartType, other.dartType)) {
+ if (typeHierarchy.isSubtype(this.cls.classNode, other.cls.classNode)) {
return this;
}
} else if (other is ConcreteType) {
- if (typeHierarchy.isSubtype(
- typeHierarchy.coreTypes.legacyRawType(other.classNode),
- this.dartType)) {
+ if (typeHierarchy.isSubtype(other.cls.classNode, this.cls.classNode)) {
return other;
} else {
return const EmptyType();
}
}
return typeHierarchy
- .specializeTypeCone(dartType)
+ .specializeTypeCone(cls)
.intersection(other, typeHierarchy);
}
}
-/// Abstract unique identifier of a Dart class.
-/// Identifiers are comparable and used to provide ordering on classes.
-abstract class ClassId<E extends ClassId<E>> implements Comparable<E> {
- const ClassId();
-}
-
-/// Simple implementation of [ClassId] based on int.
-class IntClassId extends ClassId<IntClassId> {
- final int id;
-
- const IntClassId(this.id);
-
- @override
- int compareTo(IntClassId other) => id.compareTo(other.id);
-}
-
/// Type representing a set of instances of a specific Dart class (no subtypes
/// or `null` object).
class ConcreteType extends Type implements Comparable<ConcreteType> {
- final ClassId classId;
- final Class classNode;
+ final TFClass cls;
int _hashCode;
// May be null if there are no type arguments constraints. The type arguments
@@ -621,52 +600,46 @@
final int numImmediateTypeArgs;
final List<Type> typeArgs;
- ConcreteType(this.classId, this.classNode, [List<Type> typeArgs_])
+ ConcreteType(this.cls, [List<Type> typeArgs_])
: typeArgs = typeArgs_,
numImmediateTypeArgs =
- typeArgs_ != null ? classNode.typeParameters.length : 0 {
+ typeArgs_ != null ? cls.classNode.typeParameters.length : 0 {
// TODO(alexmarkov): support closures
- assertx(!classNode.isAbstract);
- assertx(typeArgs == null || classNode.typeParameters.isNotEmpty);
+ assertx(!cls.classNode.isAbstract);
+ assertx(typeArgs == null || cls.classNode.typeParameters.isNotEmpty);
assertx(typeArgs == null || typeArgs.any((t) => t is RuntimeType));
}
- ConcreteType get raw => new ConcreteType(classId, classNode, null);
+ ConcreteType get raw => new ConcreteType(cls, null);
@override
- Class getConcreteClass(TypeHierarchy typeHierarchy) => classNode;
+ Class getConcreteClass(TypeHierarchy typeHierarchy) => cls.classNode;
@override
- bool isSubtypeOf(TypeHierarchy typeHierarchy, DartType dartType) =>
- typeHierarchy.isSubtype(
- typeHierarchy.coreTypes.legacyRawType(classNode), dartType);
+ bool isSubtypeOf(TypeHierarchy typeHierarchy, Class other) =>
+ typeHierarchy.isSubtype(cls.classNode, other);
bool isSubtypeOfRuntimeType(
TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
- if (runtimeType._type is InterfaceType &&
- (runtimeType._type as InterfaceType).classNode ==
- typeHierarchy.functionClass) {
- // TODO(35573): "implements/extends Function" is not handled correctly by
- // the CFE. By returning "false" we force an approximation -- that a type
- // check against "Function" might fail, whatever the LHS is.
- return false;
- }
+ final rhs = runtimeType._type;
+ if (rhs is DynamicType || rhs is VoidType) return true;
+ if (rhs is InterfaceType) {
+ if (rhs.classNode == typeHierarchy.coreTypes.functionClass) {
+ // TODO(35573): "implements/extends Function" is not handled correctly by
+ // the CFE. By returning "false" we force an approximation -- that a type
+ // check against "Function" might fail, whatever the LHS is.
+ return false;
+ }
- if (!typeHierarchy.isSubtype(
- typeHierarchy.coreTypes.legacyRawType(this.classNode),
- runtimeType._type)) {
- return false;
- }
+ if (!typeHierarchy.isSubtype(this.cls.classNode, rhs.classNode)) {
+ return false;
+ }
- InterfaceType runtimeDartType;
- if (runtimeType._type is InterfaceType) {
- runtimeDartType = runtimeType._type;
- if (runtimeDartType.typeArguments.isEmpty) return true;
- if (runtimeDartType.classNode == typeHierarchy.futureOrClass) {
+ if (rhs.typeArguments.isEmpty) return true;
+ if (rhs.classNode == typeHierarchy.coreTypes.futureOrClass) {
if (typeHierarchy.isSubtype(
- typeHierarchy.coreTypes.legacyRawType(classNode),
- typeHierarchy.coreTypes.futureLegacyRawType) ||
- classNode == typeHierarchy.futureOrClass) {
+ cls.classNode, typeHierarchy.coreTypes.futureClass) ||
+ cls.classNode == typeHierarchy.coreTypes.futureOrClass) {
final RuntimeType lhs =
typeArgs == null ? RuntimeType(DynamicType(), null) : typeArgs[0];
return lhs.isSubtypeOfRuntimeType(
@@ -675,44 +648,42 @@
return isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
}
}
- } else {
- // The TypeHierarchy result may be inaccurate only if there are type
- // arguments which it doesn't examine.
+
+ List<Type> usableTypeArgs = typeArgs;
+ if (usableTypeArgs == null) {
+ if (cls.classNode.typeParameters.isEmpty) {
+ usableTypeArgs =
+ typeHierarchy.flattenedTypeArgumentsForNonGeneric(cls.classNode);
+ } else {
+ return false;
+ }
+ }
+
+ final interfaceOffset =
+ typeHierarchy.genericInterfaceOffsetFor(cls.classNode, rhs.classNode);
+
+ assertx(usableTypeArgs.length - interfaceOffset >=
+ runtimeType.numImmediateTypeArgs);
+
+ for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) {
+ if (usableTypeArgs[i + interfaceOffset] == const AnyType())
+ return false;
+ assertx(usableTypeArgs[i + interfaceOffset] is RuntimeType);
+ if (!usableTypeArgs[i + interfaceOffset]
+ .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[i])) {
+ return false;
+ }
+ }
return true;
}
-
- List<Type> usableTypeArgs = typeArgs;
- if (usableTypeArgs == null) {
- if (classNode.typeParameters.isEmpty) {
- usableTypeArgs =
- typeHierarchy.flattenedTypeArgumentsForNonGeneric(classNode);
- } else {
- return false;
- }
- }
-
- final interfaceOffset = typeHierarchy.genericInterfaceOffsetFor(
- classNode, runtimeDartType.classNode);
-
- assertx(usableTypeArgs.length - interfaceOffset >=
- runtimeType.numImmediateTypeArgs);
-
- for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) {
- if (usableTypeArgs[i + interfaceOffset] == const AnyType()) return false;
- assertx(usableTypeArgs[i + interfaceOffset] is RuntimeType);
- if (!usableTypeArgs[i + interfaceOffset]
- .isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[i])) {
- return false;
- }
- }
- return true;
+ return false;
}
@override
int get hashCode => _hashCode ??= _computeHashCode();
int _computeHashCode() {
- int hash = classId.hashCode ^ 0x1234 & kHashMask;
+ int hash = cls.hashCode ^ 0x1234 & kHashMask;
// We only need to hash the first type arguments vector, since the type
// arguments of the implemented interfaces are implied by it.
for (int i = 0; i < numImmediateTypeArgs; ++i) {
@@ -725,7 +696,7 @@
bool operator ==(other) {
if (identical(this, other)) return true;
if (other is ConcreteType) {
- if (this.classId != other.classId ||
+ if (!identical(this.cls, other.cls) ||
this.numImmediateTypeArgs != other.numImmediateTypeArgs) {
return false;
}
@@ -745,12 +716,12 @@
// Note that this may return 0 for concrete types which are not equal if the
// difference is only in type arguments.
@override
- int compareTo(ConcreteType other) => classId.compareTo(other.classId);
+ int compareTo(ConcreteType other) => cls.id.compareTo(other.cls.id);
@override
String toString() => typeArgs == null
- ? "_T (${classNode})"
- : "_T (${classNode}<${typeArgs.take(numImmediateTypeArgs).join(', ')}>)";
+ ? "_T (${cls})"
+ : "_T (${cls}<${typeArgs.take(numImmediateTypeArgs).join(', ')}>)";
@override
int get order => TypeOrder.Concrete.index;
@@ -763,8 +734,8 @@
if (other is ConcreteType) {
if (this == other) {
return this;
- } else if (this.classId != other.classId) {
- final types = (this.classId.compareTo(other.classId) < 0)
+ } else if (!identical(this.cls, other.cls)) {
+ final types = (this.cls.id < other.cls.id)
? <ConcreteType>[this, other]
: <ConcreteType>[other, this];
return new SetType(types);
@@ -786,7 +757,7 @@
if (this == other) {
return this;
}
- if (this.classId != other.classId) {
+ if (!identical(this.cls, other.cls)) {
return EmptyType();
}
assertx(typeArgs != null || other.typeArgs != null);
@@ -809,7 +780,7 @@
mergedTypeArgs[i] = merged;
}
if (!hasRuntimeType) return raw;
- return new ConcreteType(classId, classNode, mergedTypeArgs);
+ return new ConcreteType(cls, mergedTypeArgs);
} else {
throw 'Unexpected type $other';
}
@@ -915,7 +886,7 @@
throw "ERROR: RuntimeType does not support isSpecialized.";
@override
- bool isSubtypeOf(TypeHierarchy typeHierarchy, DartType dartType) =>
+ bool isSubtypeOf(TypeHierarchy typeHierarchy, Class cls) =>
throw "ERROR: RuntimeType does not support isSubtypeOf.";
@override
@@ -944,20 +915,33 @@
bool isSubtypeOfRuntimeType(
TypeHierarchy typeHierarchy, RuntimeType runtimeType) {
- if (!typeHierarchy.isSubtype(this._type, runtimeType._type)) return false;
-
- // The typeHierarchy result maybe be inaccurate only if there are type
- // arguments which need to be examined.
- if (_type is! InterfaceType || runtimeType.numImmediateTypeArgs == 0) {
+ final rhs = runtimeType._type;
+ if (rhs is DynamicType ||
+ rhs is VoidType ||
+ _type is BottomType ||
+ _type is NeverType) {
return true;
}
+ if (rhs is BottomType || rhs is NeverType) return false;
+ if (_type is DynamicType || _type is VoidType) {
+ return (rhs is InterfaceType &&
+ rhs.classNode == typeHierarchy.coreTypes.objectClass);
+ }
final thisClass = (_type as InterfaceType).classNode;
- final otherClass = (runtimeType._type as InterfaceType).classNode;
+ final otherClass = (rhs as InterfaceType).classNode;
- if (otherClass == typeHierarchy.futureOrClass) {
- if (thisClass == typeHierarchy.futureClass ||
- thisClass == typeHierarchy.futureOrClass) {
+ if (!typeHierarchy.isSubtype(thisClass, otherClass)) return false;
+
+ // The typeHierarchy result maybe be inaccurate only if there are type
+ // arguments which need to be examined.
+ if (runtimeType.numImmediateTypeArgs == 0) {
+ return true;
+ }
+
+ if (otherClass == typeHierarchy.coreTypes.futureOrClass) {
+ if (thisClass == typeHierarchy.coreTypes.futureClass ||
+ thisClass == typeHierarchy.coreTypes.futureOrClass) {
return typeArgs[0]
.isSubtypeOfRuntimeType(typeHierarchy, runtimeType.typeArgs[0]);
} else {
diff --git a/pkg/vm/test/bytecode/object_table_test.dart b/pkg/vm/test/bytecode/object_table_test.dart
index 98923e8..84f1001 100644
--- a/pkg/vm/test/bytecode/object_table_test.dart
+++ b/pkg/vm/test/bytecode/object_table_test.dart
@@ -40,7 +40,7 @@
lib2.parent = component;
component.libraries.add(lib2);
- objectTable = new ObjectTable();
+ objectTable = new ObjectTable(coreTypes);
});
tearDown(() {});
diff --git a/pkg/vm/test/bytecode/recursive_types_validator_test.dart b/pkg/vm/test/bytecode/recursive_types_validator_test.dart
index 6e27e46..6927492 100644
--- a/pkg/vm/test/bytecode/recursive_types_validator_test.dart
+++ b/pkg/vm/test/bytecode/recursive_types_validator_test.dart
@@ -10,6 +10,7 @@
import 'package:vm/bytecode/recursive_types_validator.dart';
main() {
+ CoreTypes coreTypes;
Library lib;
Supertype objectSuper;
DartType intType;
@@ -27,7 +28,7 @@
setUp(() {
// Start with mock SDK libraries.
Component component = createMockSdkComponent();
- CoreTypes coreTypes = new CoreTypes(component);
+ coreTypes = new CoreTypes(component);
objectSuper = coreTypes.objectClass.asThisSupertype;
intType = new InterfaceType(coreTypes.intClass, Nullability.legacy);
doubleType = new InterfaceType(coreTypes.doubleClass, Nullability.legacy);
@@ -40,7 +41,7 @@
// class Base<T>
base = addClass('Base', [new TypeParameter('T')]);
- validator = new RecursiveTypesValidator();
+ validator = new RecursiveTypesValidator(coreTypes);
});
tearDown(() {});
@@ -165,9 +166,10 @@
new InterfaceType(e, Nullability.legacy, [intType, doubleType]);
validator.validateType(eOfIntDouble);
- validator.validateType(e.thisType);
+ validator.validateType(e.getThisType(coreTypes, lib.nonNullable));
Expect.isFalse(validator.isRecursive(eOfIntDouble));
- Expect.isFalse(validator.isRecursive(e.thisType));
+ Expect.isFalse(
+ validator.isRecursive(e.getThisType(coreTypes, lib.nonNullable)));
});
}
diff --git a/pkg/vm/test/modular_kernel_plus_aot_test.dart b/pkg/vm/test/modular_kernel_plus_aot_test.dart
new file mode 100644
index 0000000..d382501
--- /dev/null
+++ b/pkg/vm/test/modular_kernel_plus_aot_test.dart
@@ -0,0 +1,163 @@
+// Copyright (c) 2019, 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.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:front_end/src/api_unstable/bazel_worker.dart' as fe;
+import 'package:front_end/src/api_prototype/standard_file_system.dart';
+import 'package:kernel/target/targets.dart';
+import 'package:kernel/kernel.dart';
+import 'package:kernel/verifier.dart';
+import 'package:vm/target/vm.dart';
+import 'package:vm/kernel_front_end.dart';
+
+main() async {
+ Uri sdkSummary =
+ sdkRootFile(Platform.executable).resolve('vm_platform_strong.dill');
+ if (!await File.fromUri(sdkSummary).exists()) {
+ // If we run from the <build-dir>/dart-sdk/bin folder, we need to navigate two
+ // levels up.
+ sdkSummary = sdkRootFile(Platform.executable)
+ .resolve('../../vm_platform_strong.dill');
+ }
+
+ // Tests are run in the root directory of the sdk checkout.
+ final Uri packagesFile = sdkRootFile('.packages');
+ final Uri librariesFile = sdkRootFile('sdk/lib/libraries.json');
+
+ final vmTarget = VmTarget(TargetFlags());
+
+ await withTempDirectory((Uri uri) async {
+ final mixinFilename = uri.resolve('mixin.dart');
+ final mixinDillFilename = uri.resolve('mixin.dart.dill');
+ await File.fromUri(mixinFilename).writeAsStringSync(mixinFile);
+
+ await compileToKernel(vmTarget, librariesFile, sdkSummary, packagesFile,
+ mixinDillFilename, <Uri>[mixinFilename], <Uri>[], <Uri>[]);
+
+ final mainFilename = uri.resolve('main.dart');
+ final mainDillFilename = uri.resolve('main.dart.dill');
+ await File.fromUri(mainFilename).writeAsStringSync(mainFile);
+
+ await compileToKernel(
+ vmTarget,
+ librariesFile,
+ sdkSummary,
+ packagesFile,
+ mainDillFilename,
+ <Uri>[mainFilename],
+ <Uri>[mixinDillFilename],
+ <Uri>[]);
+
+ final bytes = concat(
+ await File.fromUri(sdkSummary).readAsBytes(),
+ concat(await File.fromUri(mixinDillFilename).readAsBytes(),
+ await File.fromUri(mainDillFilename).readAsBytes()));
+ final component = loadComponentFromBytes(bytes);
+
+ // Verify before running global transformations.
+ verifyComponent(component, isOutline: false, afterConst: true);
+
+ const useGlobalTypeFlowAnalysis = true;
+ const enableAsserts = false;
+ const useProtobufTreeShaker = false;
+ await runGlobalTransformations(
+ vmTarget,
+ component,
+ useGlobalTypeFlowAnalysis,
+ enableAsserts,
+ useProtobufTreeShaker,
+ ErrorDetector());
+
+ // Verify after running global transformations.
+ verifyComponent(component, isOutline: false, afterConst: true);
+ });
+}
+
+Future compileToKernel(
+ Target target,
+ Uri librariesFile,
+ Uri sdkSummary,
+ Uri packagesFile,
+ Uri outputFile,
+ List<Uri> sources,
+ List<Uri> linkedInputs,
+ List<Uri> summaryInputs) async {
+ final state = await fe.initializeCompiler(
+ null,
+ sdkSummary,
+ librariesFile,
+ packagesFile,
+ summaryInputs,
+ linkedInputs,
+ target,
+ StandardFileSystem.instance, const <String>[], const <String, String>{});
+
+ void onDiagnostic(fe.DiagnosticMessage message) {
+ print(message);
+ }
+
+ final Component component =
+ await fe.compileComponent(state, sources, onDiagnostic);
+ final Uint8List kernel = fe.serializeComponent(component,
+ filter: (library) => sources.contains(library.importUri));
+ await File(outputFile.toFilePath()).writeAsBytes(kernel);
+}
+
+Future withTempDirectory(Future func(Uri dirUri)) async {
+ final dir = await Directory.systemTemp.createTemp('modular-compile-test');
+ try {
+ await func(dir.uri);
+ } finally {
+ await dir.delete(recursive: true);
+ }
+}
+
+Uint8List concat(List<int> a, List<int> b) {
+ final bytes = Uint8List(a.length + b.length);
+ bytes.setRange(0, a.length, a);
+ bytes.setRange(a.length, bytes.length, b);
+ return bytes;
+}
+
+Uri sdkRootFile(name) => Directory.current.uri.resolveUri(Uri.file(name));
+
+const String mainFile = r'''
+import 'mixin.dart';
+class R extends A2 {
+ void bar() {
+ mixinProperty = '';
+ mixinProperty .foo();
+ mixinMethod('').foo();
+ super.mixinProperty= '';
+ super.mixinProperty.foo();
+ super.mixinMethod('').foo();
+ }
+}
+
+main() {
+ A1();
+ final a2 = A2();
+ // The mixin deduplication will remove the anonymous mixin application class
+ // from `A2 & Mixin` and instead use the one from `A1 & Mixin`.
+ a2.mixinProperty= '';
+ a2.mixinProperty.foo();
+ a2.mixinMethod('').foo();
+}
+''';
+
+const String mixinFile = r'''
+class Foo {
+ foo() {}
+}
+class Mixin {
+ void set mixinProperty(v) {}
+ Foo get mixinProperty{}
+ Foo mixinMethod(v) {}
+}
+class A1 extends Object with Mixin { }
+class A2 extends Object with Mixin { }
+''';
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index 4ab863b..2bb4e8b 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -7,33 +7,72 @@
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
+import 'package:kernel/target/targets.dart';
import 'package:kernel/type_environment.dart';
import 'package:test/test.dart';
import 'package:vm/transformations/pragma.dart'
show ConstantPragmaAnnotationParser;
+import 'package:vm/transformations/type_flow/analysis.dart';
+import 'package:vm/transformations/type_flow/calls.dart';
import 'package:vm/transformations/type_flow/native_code.dart';
import 'package:vm/transformations/type_flow/summary_collector.dart';
-import 'package:vm/transformations/type_flow/analysis.dart';
-import 'package:kernel/target/targets.dart';
+import 'package:vm/transformations/type_flow/types.dart';
import '../../common_test_utils.dart';
final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
+class FakeTypesBuilder extends TypesBuilder {
+ final Map<Class, TFClass> _classes = <Class, TFClass>{};
+ int _classIdCounter = 0;
+
+ FakeTypesBuilder(CoreTypes coreTypes) : super(coreTypes);
+
+ @override
+ TFClass getTFClass(Class c) =>
+ _classes[c] ??= new TFClass(++_classIdCounter, c);
+}
+
+class FakeEntryPointsListener implements EntryPointsListener {
+ final FakeTypesBuilder _typesBuilder;
+
+ FakeEntryPointsListener(this._typesBuilder);
+
+ @override
+ void addRawCall(Selector selector) {}
+
+ @override
+ void addDirectFieldAccess(Field field, Type value) {}
+
+ @override
+ ConcreteType addAllocatedClass(Class c) {
+ return new ConcreteType(_typesBuilder.getTFClass(c), null);
+ }
+
+ @override
+ void recordMemberCalledViaInterfaceSelector(Member target) {}
+
+ @override
+ void recordMemberCalledViaThis(Member target) {}
+}
+
class PrintSummaries extends RecursiveVisitor<Null> {
- final SummaryCollector _summaryCollector;
+ SummaryCollector _summaryCollector;
final StringBuffer _buf = new StringBuffer();
PrintSummaries(Target target, TypeEnvironment environment,
- CoreTypes coreTypes, ClassHierarchy hierarchy)
- : _summaryCollector = new SummaryCollector(
- target,
- environment,
- hierarchy,
- new EmptyEntryPointsListener(),
- new NativeCodeOracle(
- null, new ConstantPragmaAnnotationParser(coreTypes)),
- new GenericInterfacesInfoImpl(hierarchy));
+ CoreTypes coreTypes, ClassHierarchy hierarchy) {
+ final typesBuilder = new FakeTypesBuilder(coreTypes);
+ _summaryCollector = new SummaryCollector(
+ target,
+ environment,
+ hierarchy,
+ new FakeEntryPointsListener(typesBuilder),
+ typesBuilder,
+ new NativeCodeOracle(
+ null, new ConstantPragmaAnnotationParser(coreTypes)),
+ new GenericInterfacesInfoImpl(hierarchy));
+ }
String print(TreeNode node) {
visitLibrary(node);
diff --git a/pkg/vm/test/transformations/type_flow/types_test.dart b/pkg/vm/test/transformations/type_flow/types_test.dart
index 1689617..ec6e530 100644
--- a/pkg/vm/test/transformations/type_flow/types_test.dart
+++ b/pkg/vm/test/transformations/type_flow/types_test.dart
@@ -6,105 +6,123 @@
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';
+import 'package:kernel/testing/mock_sdk_component.dart';
import 'package:test/test.dart';
import 'package:vm/transformations/type_flow/types.dart';
-class TestTypeHierarchy implements TypeHierarchy {
- final Map<DartType, List<DartType>> subtypes;
- final Map<DartType, Type> specializations;
- final CoreTypes coreTypes = new CoreTypes(new Component());
+class TestTypeHierarchy extends TypeHierarchy {
+ final Map<Class, TFClass> classes = <Class, TFClass>{};
+ final Map<Class, List<Class>> subtypes;
+ final Map<Class, Type> specializations;
+ int classIdCounter = 0;
- TestTypeHierarchy(this.subtypes, this.specializations);
+ TestTypeHierarchy(CoreTypes coreTypes, this.subtypes, this.specializations)
+ : super(coreTypes);
@override
- bool isSubtype(DartType subType, DartType superType) {
- return subtypes[superType].contains(subType);
+ bool isSubtype(Class sub, Class sup) {
+ return subtypes[sup].contains(sub);
}
@override
- Type specializeTypeCone(DartType base) {
- Type result = specializations[base];
+ Type specializeTypeCone(TFClass base) {
+ Type result = specializations[base.classNode];
expect(result, isNotNull,
reason: "specializeTypeCone($base) is not defined");
return result;
}
+ @override
+ TFClass getTFClass(Class c) =>
+ classes[c] ??= new TFClass(++classIdCounter, c);
+
+ @override
List<DartType> flattenedTypeArgumentsFor(Class klass) =>
throw "flattenedTypeArgumentsFor is not supported in the types test.";
+ @override
int genericInterfaceOffsetFor(Class klass, Class iface) =>
throw "genericInterfaceOffsetFor is not supported in the types test.";
+ @override
List<Type> flattenedTypeArgumentsForNonGeneric(Class klass) =>
throw "flattenedTypeArgumentsFor is not supported in the types test.";
-
- Class get futureOrClass =>
- throw "futureOrClass not supported in the types test.";
- Class get futureClass => throw "futureClass not supported in the types test.";
- Class get functionClass =>
- throw "functionClass not supported in the types test.";
}
main() {
- test('factory-constructors', () {
- Class c1 = new Class(name: 'C1');
- Class c2 = new Class(name: 'C2', typeParameters: [new TypeParameter('E')]);
- InterfaceType t1 = new InterfaceType(c1, Nullability.legacy);
- InterfaceType t2Raw = new InterfaceType(c2, Nullability.legacy);
- InterfaceType t2Generic = new InterfaceType(c2, Nullability.legacy, [t1]);
- FunctionType f1 =
+ final Component component = createMockSdkComponent();
+ final CoreTypes coreTypes = new CoreTypes(component);
+
+ test('types-builder', () {
+ final Class c1 = new Class(name: 'C1');
+ final Class c2 =
+ new Class(name: 'C2', typeParameters: [new TypeParameter('E')]);
+
+ final TypesBuilder tb = new TestTypeHierarchy(coreTypes, {}, {});
+ final tfc1 = tb.getTFClass(c1);
+ final tfc2 = tb.getTFClass(c2);
+
+ final InterfaceType t1 = new InterfaceType(c1, Nullability.legacy);
+ final InterfaceType t2Raw = new InterfaceType(c2, Nullability.legacy);
+ final InterfaceType t2Generic =
+ new InterfaceType(c2, Nullability.legacy, [t1]);
+ final InterfaceType t3 =
+ new InterfaceType(coreTypes.nullClass, Nullability.nullable);
+ final FunctionType f1 =
new FunctionType([t1], const VoidType(), Nullability.legacy);
- expect(new Type.empty(), equals(const EmptyType()));
+ expect(tb.fromStaticType(const NeverType(Nullability.nonNullable), false),
+ equals(const EmptyType()));
+ expect(tb.fromStaticType(const BottomType(), true),
+ equals(new NullableType(const EmptyType())));
+ expect(tb.fromStaticType(const DynamicType(), true),
+ equals(new NullableType(const AnyType())));
+ expect(tb.fromStaticType(const VoidType(), true),
+ equals(new NullableType(const AnyType())));
- expect(new Type.cone(const DynamicType()), equals(const AnyType()));
- expect(new Type.cone(t1), equals(new ConeType(t1)));
- expect(new Type.cone(t2Raw), equals(new ConeType(t2Raw)));
- expect(new Type.cone(t2Generic), equals(new ConeType(t2Raw)));
- expect(new Type.cone(f1), equals(const AnyType()));
+ expect(tb.fromStaticType(t1, false), equals(new ConeType(tfc1)));
+ expect(tb.fromStaticType(t2Raw, false), equals(new ConeType(tfc2)));
+ expect(tb.fromStaticType(t2Generic, false), equals(new ConeType(tfc2)));
+ expect(tb.fromStaticType(t3, false), equals(new EmptyType()));
+ expect(tb.fromStaticType(f1, false), equals(const AnyType()));
- expect(new Type.nullable(new Type.empty()),
- equals(new NullableType(new EmptyType())));
- expect(new Type.nullable(new Type.cone(t1)),
- equals(new NullableType(new ConeType(t1))));
+ expect(tb.fromStaticType(t1, true),
+ equals(new NullableType(new ConeType(tfc1))));
+ expect(tb.fromStaticType(t2Raw, true),
+ equals(new NullableType(new ConeType(tfc2))));
+ expect(tb.fromStaticType(t2Generic, true),
+ equals(new NullableType(new ConeType(tfc2))));
+ expect(
+ tb.fromStaticType(t3, true), equals(new NullableType(new EmptyType())));
+ expect(
+ tb.fromStaticType(f1, true), equals(new NullableType(const AnyType())));
expect(new Type.nullableAny(), equals(new NullableType(new AnyType())));
-
- expect(new Type.fromStatic(const DynamicType()),
- equals(new NullableType(new AnyType())));
- expect(new Type.fromStatic(const DynamicType()),
- equals(new Type.nullableAny()));
- expect(new Type.fromStatic(const BottomType()),
- equals(new NullableType(new EmptyType())));
- expect(new Type.fromStatic(t1), equals(new NullableType(new ConeType(t1))));
- expect(new Type.fromStatic(t2Raw),
- equals(new NullableType(new ConeType(t2Raw))));
- expect(new Type.fromStatic(t2Generic),
- equals(new NullableType(new ConeType(t2Raw))));
});
test('union-intersection', () {
// T1 <: T3, T2 <: T3
- InterfaceType t1 =
- new InterfaceType(new Class(name: 'T1'), Nullability.legacy);
- InterfaceType t2 =
- new InterfaceType(new Class(name: 'T2'), Nullability.legacy);
- InterfaceType t3 =
- new InterfaceType(new Class(name: 'T3'), Nullability.legacy);
- InterfaceType t4 =
- new InterfaceType(new Class(name: 'T4'), Nullability.legacy);
+ final c1 = new Class(name: 'T1');
+ final c2 = new Class(name: 'T2');
+ final c3 = new Class(name: 'T3');
+ final c4 = new Class(name: 'T4');
+
+ final tfc1 = new TFClass(1, c1);
+ final tfc2 = new TFClass(2, c2);
+ final tfc3 = new TFClass(3, c3);
+ final tfc4 = new TFClass(4, c4);
final empty = new EmptyType();
final any = new AnyType();
- final concreteT1 = new ConcreteType(const IntClassId(1), t1.classNode);
- final concreteT2 = new ConcreteType(const IntClassId(2), t2.classNode);
- final concreteT3 = new ConcreteType(const IntClassId(3), t3.classNode);
- final concreteT4 = new ConcreteType(const IntClassId(4), t4.classNode);
- final coneT1 = new ConeType(t1);
- final coneT2 = new ConeType(t2);
- final coneT3 = new ConeType(t3);
- final coneT4 = new ConeType(t4);
+ final concreteT1 = new ConcreteType(tfc1);
+ final concreteT2 = new ConcreteType(tfc2);
+ final concreteT3 = new ConcreteType(tfc3);
+ final concreteT4 = new ConcreteType(tfc4);
+ final coneT1 = new ConeType(tfc1);
+ final coneT2 = new ConeType(tfc2);
+ final coneT3 = new ConeType(tfc3);
+ final coneT4 = new ConeType(tfc4);
final setT12 = new SetType([concreteT1, concreteT2]);
final setT14 = new SetType([concreteT1, concreteT4]);
final setT23 = new SetType([concreteT2, concreteT3]);
@@ -242,20 +260,20 @@
[nullableSetT12, nullableSetT34, nullableSetT1234, nullableEmpty],
];
- final hierarchy = new TestTypeHierarchy(
+ final hierarchy = new TestTypeHierarchy(coreTypes,
// subtypes
{
- t1: [t1],
- t2: [t2],
- t3: [t1, t2, t3],
- t4: [t4],
+ c1: [c1],
+ c2: [c2],
+ c3: [c1, c2, c3],
+ c4: [c4],
},
// specializations
{
- t1: concreteT1,
- t2: concreteT2,
- t3: setT123,
- t4: concreteT4
+ c1: concreteT1,
+ c2: concreteT2,
+ c3: setT123,
+ c4: concreteT4
});
for (List testCase in testCases) {
@@ -280,17 +298,13 @@
final c2 = new Class(name: 'C2');
final c3 = new Class(name: 'C3');
+ final tfc1 = new TFClass(1, c1);
+ final tfc2 = new TFClass(2, c2);
+ final tfc3 = new TFClass(3, c3);
+
final t1a = new InterfaceType(c1, Nullability.legacy);
final t1b = new InterfaceType(c1, Nullability.legacy);
final t2 = new InterfaceType(c2, Nullability.legacy);
- final f1a = new FunctionType([t1a], const VoidType(), Nullability.legacy);
- final f1b = new FunctionType([t1b], const VoidType(), Nullability.legacy);
- final f2 =
- new FunctionType([t1a, t1a], const VoidType(), Nullability.legacy);
-
- final cid1 = const IntClassId(1);
- final cid2 = const IntClassId(2);
- final cid3 = const IntClassId(3);
void eq(dynamic a, dynamic b) {
expect(a == b, isTrue, reason: "Test case: $a == $b");
@@ -308,68 +322,61 @@
eq(t1a, t1b);
ne(t1a, t2);
- eq(f1a, f1b);
- ne(f1a, f2);
- ne(t1a, f1a);
eq(new EmptyType(), new EmptyType());
ne(new EmptyType(), new AnyType());
- ne(new EmptyType(), new ConcreteType(cid1, c1));
- ne(new EmptyType(), new ConeType(t1a));
+ ne(new EmptyType(), new ConcreteType(tfc1));
+ ne(new EmptyType(), new ConeType(tfc1));
ne(new EmptyType(),
- new SetType([new ConcreteType(cid1, c1), new ConcreteType(cid2, c2)]));
+ new SetType([new ConcreteType(tfc1), new ConcreteType(tfc2)]));
ne(new EmptyType(), new NullableType(new EmptyType()));
eq(new AnyType(), new AnyType());
- ne(new AnyType(), new ConcreteType(cid1, c1));
- ne(new AnyType(), new ConeType(t1a));
+ ne(new AnyType(), new ConcreteType(tfc1));
+ ne(new AnyType(), new ConeType(tfc1));
ne(new AnyType(),
- new SetType([new ConcreteType(cid1, c1), new ConcreteType(cid2, c2)]));
+ new SetType([new ConcreteType(tfc1), new ConcreteType(tfc2)]));
ne(new AnyType(), new NullableType(new EmptyType()));
- eq(new ConcreteType(cid1, c1), new ConcreteType(cid1, c1));
- ne(new ConcreteType(cid1, c1), new ConcreteType(cid2, c2));
- ne(new ConcreteType(cid1, c1), new ConeType(t1a));
- ne(new ConcreteType(cid1, c1), new ConeType(t2));
- ne(new ConcreteType(cid1, c1),
- new SetType([new ConcreteType(cid1, c1), new ConcreteType(cid2, c2)]));
- ne(new ConcreteType(cid1, c1),
- new NullableType(new ConcreteType(cid1, c1)));
+ eq(new ConcreteType(tfc1), new ConcreteType(tfc1));
+ ne(new ConcreteType(tfc1), new ConcreteType(tfc2));
+ ne(new ConcreteType(tfc1), new ConeType(tfc1));
+ ne(new ConcreteType(tfc1), new ConeType(tfc2));
+ ne(new ConcreteType(tfc1),
+ new SetType([new ConcreteType(tfc1), new ConcreteType(tfc2)]));
+ ne(new ConcreteType(tfc1), new NullableType(new ConcreteType(tfc1)));
- eq(new ConeType(t1a), new ConeType(t1b));
- eq(new ConeType(f1a), new ConeType(f1b));
- ne(new ConeType(t1a), new ConeType(t2));
- ne(new ConeType(f1a), new ConeType(f2));
- ne(new ConeType(t1a), new ConeType(f1a));
- ne(new ConeType(t1a),
- new SetType([new ConcreteType(cid1, c1), new ConcreteType(cid2, c2)]));
- ne(new ConeType(t1a), new NullableType(new ConeType(t1a)));
+ eq(new ConeType(tfc1), new ConeType(tfc1));
+ ne(new ConeType(tfc1), new ConeType(tfc2));
+ ne(new ConeType(tfc1),
+ new SetType([new ConcreteType(tfc1), new ConcreteType(tfc2)]));
+ ne(new ConeType(tfc1), new NullableType(new ConeType(tfc1)));
- eq(new SetType([new ConcreteType(cid1, c1), new ConcreteType(cid2, c2)]),
- new SetType([new ConcreteType(cid1, c1), new ConcreteType(cid2, c2)]));
+ eq(new SetType([new ConcreteType(tfc1), new ConcreteType(tfc2)]),
+ new SetType([new ConcreteType(tfc1), new ConcreteType(tfc2)]));
eq(
new SetType([
- new ConcreteType(cid1, c1),
- new ConcreteType(cid2, c2),
- new ConcreteType(cid3, c3)
+ new ConcreteType(tfc1),
+ new ConcreteType(tfc2),
+ new ConcreteType(tfc3)
]),
new SetType([
- new ConcreteType(cid1, c1),
- new ConcreteType(cid2, c2),
- new ConcreteType(cid3, c3)
+ new ConcreteType(tfc1),
+ new ConcreteType(tfc2),
+ new ConcreteType(tfc3)
]));
ne(
- new SetType([new ConcreteType(cid1, c1), new ConcreteType(cid2, c2)]),
+ new SetType([new ConcreteType(tfc1), new ConcreteType(tfc2)]),
new SetType([
- new ConcreteType(cid1, c1),
- new ConcreteType(cid2, c2),
- new ConcreteType(cid3, c3)
+ new ConcreteType(tfc1),
+ new ConcreteType(tfc2),
+ new ConcreteType(tfc3)
]));
- ne(new SetType([new ConcreteType(cid1, c1), new ConcreteType(cid2, c2)]),
- new SetType([new ConcreteType(cid1, c1), new ConcreteType(cid3, c3)]));
+ ne(new SetType([new ConcreteType(tfc1), new ConcreteType(tfc2)]),
+ new SetType([new ConcreteType(tfc1), new ConcreteType(tfc3)]));
ne(
- new SetType([new ConcreteType(cid1, c1), new ConcreteType(cid2, c2)]),
- new NullableType(new SetType(
- [new ConcreteType(cid1, c1), new ConcreteType(cid2, c2)])));
+ new SetType([new ConcreteType(tfc1), new ConcreteType(tfc2)]),
+ new NullableType(
+ new SetType([new ConcreteType(tfc1), new ConcreteType(tfc2)])));
});
}
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index 224709f..3dc478d 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -413,13 +413,13 @@
StoreLocal r2
Push r2
PushNull
- StoreFieldTOS CP#18
+ StoreFieldTOS CP#16
Push r2
PushNull
- StoreFieldTOS CP#20
+ StoreFieldTOS CP#18
Push r2
PushConstant CP#4
- StoreFieldTOS CP#22
+ StoreFieldTOS CP#20
Push r2
Push r0
StoreFieldTOS CP#6
@@ -429,22 +429,22 @@
Push r0
Push r0
LoadContextVar 0, 10
- DirectCall CP#24, 1
+ DirectCall CP#22, 1
StoreContextVar 0, 4
Push r0
Push r0
LoadContextVar 0, 10
- DirectCall CP#26, 1
+ DirectCall CP#24, 1
StoreContextVar 0, 5
Push r0
LoadContextVar 0, 2
Push r0
LoadContextVar 0, 10
- DynamicCall CP#28, 2
+ DynamicCall CP#26, 2
Drop1
Push r0
LoadContextVar 0, 2
- InterfaceCall CP#30, 1
+ InterfaceCall CP#28, 1
ReturnTOS
}
ConstantPool {
@@ -458,28 +458,26 @@
[7] = Reserved
[8] = DirectCall 'dart:async::_awaitHelper', ArgDesc num-args 4, num-type-args 0, names []
[9] = Reserved
- [10] = InterfaceCall 'dart:core::num::+', ArgDesc num-args 2, num-type-args 0, names []
+ [10] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
[11] = Reserved
- [12] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
- [13] = Reserved
- [14] = Type dynamic
- [15] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
- [16] = Reserved
- [17] = EndClosureFunctionScope
- [18] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+ [12] = Type dynamic
+ [13] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
+ [14] = Reserved
+ [15] = EndClosureFunctionScope
+ [16] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+ [17] = Reserved
+ [18] = InstanceField dart:core::_Closure::_function_type_arguments (field)
[19] = Reserved
- [20] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+ [20] = InstanceField dart:core::_Closure::_function (field)
[21] = Reserved
- [22] = InstanceField dart:core::_Closure::_function (field)
+ [22] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
[23] = Reserved
- [24] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+ [24] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
[25] = Reserved
- [26] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+ [26] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
[27] = Reserved
- [28] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+ [28] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
[29] = Reserved
- [30] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
- [31] = Reserved
}
Closure #lib::simpleAsyncAwait::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
ClosureCode {
@@ -558,7 +556,7 @@
Push r4
LoadContextVar 0, 9
Push r1
- InterfaceCall CP#10, 2
+ AddInt
StoreContextVar 0, 3
Jump L4
L4:
@@ -566,7 +564,7 @@
LoadContextVar 0, 2
Push r4
LoadContextVar 0, 3
- DirectCall CP#12, 2
+ DirectCall CP#10, 2
Drop1
PushNull
ReturnTOS
@@ -589,7 +587,7 @@
LoadContextVar 0, 2
Push r8
Push r9
- InterfaceCall CP#15, 3
+ InterfaceCall CP#13, 3
Drop1
Jump L5
L5:
@@ -637,13 +635,13 @@
StoreLocal r2
Push r2
PushNull
- StoreFieldTOS CP#26
+ StoreFieldTOS CP#24
Push r2
PushNull
- StoreFieldTOS CP#28
+ StoreFieldTOS CP#26
Push r2
PushConstant CP#4
- StoreFieldTOS CP#30
+ StoreFieldTOS CP#28
Push r2
Push r0
StoreFieldTOS CP#6
@@ -653,22 +651,22 @@
Push r0
Push r0
LoadContextVar 0, 10
- DirectCall CP#32, 1
+ DirectCall CP#30, 1
StoreContextVar 0, 3
Push r0
Push r0
LoadContextVar 0, 10
- DirectCall CP#34, 1
+ DirectCall CP#32, 1
StoreContextVar 0, 4
Push r0
LoadContextVar 0, 1
Push r0
LoadContextVar 0, 10
- DynamicCall CP#36, 2
+ DynamicCall CP#34, 2
Drop1
Push r0
LoadContextVar 0, 1
- InterfaceCall CP#38, 1
+ InterfaceCall CP#36, 1
ReturnTOS
}
ConstantPool {
@@ -690,28 +688,26 @@
[15] = Reserved
[16] = DirectCall 'dart:async::_awaitHelper', ArgDesc num-args 4, num-type-args 0, names []
[17] = Reserved
- [18] = InterfaceCall 'dart:core::num::+', ArgDesc num-args 2, num-type-args 0, names []
+ [18] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
[19] = Reserved
- [20] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
- [21] = Reserved
- [22] = Type dynamic
- [23] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
- [24] = Reserved
- [25] = EndClosureFunctionScope
- [26] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+ [20] = Type dynamic
+ [21] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
+ [22] = Reserved
+ [23] = EndClosureFunctionScope
+ [24] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+ [25] = Reserved
+ [26] = InstanceField dart:core::_Closure::_function_type_arguments (field)
[27] = Reserved
- [28] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+ [28] = InstanceField dart:core::_Closure::_function (field)
[29] = Reserved
- [30] = InstanceField dart:core::_Closure::_function (field)
+ [30] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
[31] = Reserved
- [32] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+ [32] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
[33] = Reserved
- [34] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+ [34] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
[35] = Reserved
- [36] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+ [36] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
[37] = Reserved
- [38] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
- [39] = Reserved
}
Closure #lib::loops::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
ClosureCode {
@@ -857,8 +853,8 @@
LoadContextParent
LoadContextVar 0, 8
Push r1
- InterfaceCall CP#18, 2
- InterfaceCall CP#18, 2
+ AddInt
+ AddInt
StoreContextVar 1, 0
Push r4
LoadContextParent
@@ -917,7 +913,7 @@
LoadContextVar 0, 1
Push r4
LoadContextVar 0, 2
- DirectCall CP#20, 2
+ DirectCall CP#18, 2
Drop1
PushNull
ReturnTOS
@@ -940,7 +936,7 @@
LoadContextVar 0, 1
Push r8
Push r9
- InterfaceCall CP#23, 3
+ InterfaceCall CP#21, 3
Drop1
Jump L10
L10:
@@ -991,13 +987,13 @@
StoreLocal r2
Push r2
PushNull
- StoreFieldTOS CP#24
+ StoreFieldTOS CP#22
Push r2
PushNull
- StoreFieldTOS CP#26
+ StoreFieldTOS CP#24
Push r2
PushConstant CP#4
- StoreFieldTOS CP#28
+ StoreFieldTOS CP#26
Push r2
Push r0
StoreFieldTOS CP#6
@@ -1007,22 +1003,22 @@
Push r0
Push r0
LoadContextVar 0, 17
- DirectCall CP#30, 1
+ DirectCall CP#28, 1
StoreContextVar 0, 5
Push r0
Push r0
LoadContextVar 0, 17
- DirectCall CP#32, 1
+ DirectCall CP#30, 1
StoreContextVar 0, 6
Push r0
LoadContextVar 0, 3
Push r0
LoadContextVar 0, 17
- DynamicCall CP#34, 2
+ DynamicCall CP#32, 2
Drop1
Push r0
LoadContextVar 0, 3
- InterfaceCall CP#36, 1
+ InterfaceCall CP#34, 1
ReturnTOS
}
ConstantPool {
@@ -1036,34 +1032,32 @@
[7] = Reserved
[8] = DirectCall 'dart:async::_awaitHelper', ArgDesc num-args 4, num-type-args 0, names []
[9] = Reserved
- [10] = InterfaceCall 'dart:core::num::+', ArgDesc num-args 2, num-type-args 0, names []
- [11] = Reserved
- [12] = Type dynamic
- [13] = Type dart:core::Error
- [14] = InterfaceCall 'dart:core::Object::_simpleInstanceOf', ArgDesc num-args 2, num-type-args 0, names []
- [15] = Reserved
- [16] = ObjectRef 'fin'
- [17] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+ [10] = Type dynamic
+ [11] = Type dart:core::Error
+ [12] = InterfaceCall 'dart:core::Object::_simpleInstanceOf', ArgDesc num-args 2, num-type-args 0, names []
+ [13] = Reserved
+ [14] = ObjectRef 'fin'
+ [15] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+ [16] = Reserved
+ [17] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
[18] = Reserved
- [19] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
+ [19] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
[20] = Reserved
- [21] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
- [22] = Reserved
- [23] = EndClosureFunctionScope
- [24] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+ [21] = EndClosureFunctionScope
+ [22] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+ [23] = Reserved
+ [24] = InstanceField dart:core::_Closure::_function_type_arguments (field)
[25] = Reserved
- [26] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+ [26] = InstanceField dart:core::_Closure::_function (field)
[27] = Reserved
- [28] = InstanceField dart:core::_Closure::_function (field)
+ [28] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
[29] = Reserved
- [30] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+ [30] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
[31] = Reserved
- [32] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+ [32] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
[33] = Reserved
- [34] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+ [34] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
[35] = Reserved
- [36] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
- [37] = Reserved
}
Closure #lib::tryCatchRethrow::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
ClosureCode {
@@ -1145,7 +1139,7 @@
LoadContextParent
LoadContextVar 0, 14
Push r1
- InterfaceCall CP#10, 2
+ AddInt
StoreContextVar 1, 0
Jump L3
Try #2 end:
@@ -1172,8 +1166,8 @@
StoreContextVar 1, 1
Push r4
LoadContextVar 1, 1
- PushConstant CP#13
- InterfaceCall CP#14, 2
+ PushConstant CP#11
+ InterfaceCall CP#12, 2
JumpIfFalse L4
Push r4
LoadContextParent
@@ -1222,7 +1216,7 @@
LoadContextParent
LoadContextVar 0, 15
Push r1
- InterfaceCall CP#10, 2
+ AddInt
StoreContextVar 1, 0
Push r4
LoadContextParent
@@ -1252,8 +1246,8 @@
LoadContextParent
Push r9
StoreContextVar 0, 13
- PushConstant CP#16
- DirectCall CP#17, 1
+ PushConstant CP#14
+ DirectCall CP#15, 1
Drop1
Push r4
LoadContextParent
@@ -1296,7 +1290,7 @@
LoadContextParent
LoadContextVar 0, 16
Push r1
- InterfaceCall CP#10, 2
+ AddInt
StoreContextVar 1, 0
Push r4
LoadContextParent
@@ -1314,8 +1308,8 @@
Push r4
LoadContextVar 0, 10
PopLocal r4
- PushConstant CP#16
- DirectCall CP#17, 1
+ PushConstant CP#14
+ DirectCall CP#15, 1
Drop1
Push r4
LoadContextParent
@@ -1358,7 +1352,7 @@
LoadContextParent
LoadContextVar 0, 16
Push r1
- InterfaceCall CP#10, 2
+ AddInt
StoreContextVar 1, 0
Push r4
LoadContextParent
@@ -1376,8 +1370,8 @@
Push r4
LoadContextVar 0, 10
PopLocal r4
- PushConstant CP#16
- DirectCall CP#17, 1
+ PushConstant CP#14
+ DirectCall CP#15, 1
Drop1
Push r4
LoadContextParent
@@ -1420,7 +1414,7 @@
LoadContextParent
LoadContextVar 0, 16
Push r1
- InterfaceCall CP#10, 2
+ AddInt
StoreContextVar 1, 0
Push r4
LoadContextParent
@@ -1436,7 +1430,7 @@
LoadContextVar 0, 3
Push r4
LoadContextVar 0, 4
- DirectCall CP#19, 2
+ DirectCall CP#17, 2
Drop1
PushNull
ReturnTOS
@@ -1459,7 +1453,7 @@
LoadContextVar 0, 3
Push r8
Push r9
- InterfaceCall CP#21, 3
+ InterfaceCall CP#19, 3
Drop1
Jump L12
L12:
@@ -1812,13 +1806,13 @@
StoreLocal r2
Push r2
PushNull
- StoreFieldTOS CP#20
+ StoreFieldTOS CP#18
Push r2
PushNull
- StoreFieldTOS CP#22
+ StoreFieldTOS CP#20
Push r2
PushConstant CP#4
- StoreFieldTOS CP#24
+ StoreFieldTOS CP#22
Push r2
Push r0
StoreFieldTOS CP#6
@@ -1828,22 +1822,22 @@
Push r0
Push r0
LoadContextVar 0, 8
- DirectCall CP#26, 1
+ DirectCall CP#24, 1
StoreContextVar 0, 3
Push r0
Push r0
LoadContextVar 0, 8
- DirectCall CP#28, 1
+ DirectCall CP#26, 1
StoreContextVar 0, 4
Push r0
LoadContextVar 0, 1
Push r0
LoadContextVar 0, 8
- DynamicCall CP#30, 2
+ DynamicCall CP#28, 2
Drop1
Push r0
LoadContextVar 0, 1
- InterfaceCall CP#32, 1
+ InterfaceCall CP#30, 1
ReturnTOS
}
ConstantPool {
@@ -1857,30 +1851,28 @@
[7] = Reserved
[8] = DirectCall 'dart:async::_awaitHelper', ArgDesc num-args 4, num-type-args 0, names []
[9] = Reserved
- [10] = InterfaceCall 'dart:core::num::==', ArgDesc num-args 2, num-type-args 0, names []
+ [10] = DirectCall 'dart:core::_AssertionError::_throwNew', ArgDesc num-args 3, num-type-args 0, names []
[11] = Reserved
- [12] = DirectCall 'dart:core::_AssertionError::_throwNew', ArgDesc num-args 3, num-type-args 0, names []
+ [12] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
[13] = Reserved
- [14] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
- [15] = Reserved
- [16] = Type dynamic
- [17] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
- [18] = Reserved
- [19] = EndClosureFunctionScope
- [20] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+ [14] = Type dynamic
+ [15] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
+ [16] = Reserved
+ [17] = EndClosureFunctionScope
+ [18] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+ [19] = Reserved
+ [20] = InstanceField dart:core::_Closure::_function_type_arguments (field)
[21] = Reserved
- [22] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+ [22] = InstanceField dart:core::_Closure::_function (field)
[23] = Reserved
- [24] = InstanceField dart:core::_Closure::_function (field)
+ [24] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
[25] = Reserved
- [26] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+ [26] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
[27] = Reserved
- [28] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+ [28] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
[29] = Reserved
- [30] = DynamicCall 'start', ArgDesc num-args 2, num-type-args 0, names []
+ [30] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
[31] = Reserved
- [32] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
- [33] = Reserved
}
Closure #lib::testAssert::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
ClosureCode {
@@ -1931,13 +1923,12 @@
JumpIfNoAsserts L2
Push r1
PushInt 42
- InterfaceCall CP#10, 2
- AssertBoolean 0
+ CompareIntEq
JumpIfTrue L2
PushInt 0
PushInt 0
PushNull
- DirectCall CP#12, 3
+ DirectCall CP#10, 3
Drop1
L2:
Push r4
@@ -1949,7 +1940,7 @@
LoadContextVar 0, 1
Push r4
LoadContextVar 0, 2
- DirectCall CP#14, 2
+ DirectCall CP#12, 2
Drop1
PushNull
ReturnTOS
@@ -1972,7 +1963,7 @@
LoadContextVar 0, 1
Push r8
Push r9
- InterfaceCall CP#17, 3
+ InterfaceCall CP#15, 3
Drop1
Jump L5
L5:
@@ -2011,7 +2002,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -2019,7 +2010,7 @@
#L1:
{
[yield] let dynamic #t1 = dart.async::_awaitHelper(x, :async_op_then, :async_op_error, :async_op) in null;
- :result;
+ dart._internal::unsafeCast<dart.core::int*>(:result);
}
dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
return;
@@ -2039,7 +2030,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
@@ -2066,18 +2057,18 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
+ dart.core::int* :async_temporary_0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L3:
{
[yield] let dynamic #t2 = dart.async::_awaitHelper(a, :async_op_then, :async_op_error, :async_op) in null;
- :async_temporary_0 = :result;
+ :async_temporary_0 = dart._internal::unsafeCast<dart.core::int*>(:result);
[yield] let dynamic #t3 = dart.async::_awaitHelper(b, :async_op_then, :async_op_error, :async_op) in null;
- :return_value = :async_temporary_0.{dart.core::num::+}(:result);
+ :return_value = :async_temporary_0.{dart.core::num::+}(dart._internal::unsafeCast<dart.core::int*>(:result));
break #L3;
}
dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -2098,11 +2089,11 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
- dynamic :async_temporary_0;
- dynamic :async_temporary_1;
+ dart.core::int* :async_temporary_0;
+ dart.core::int* :async_temporary_1;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L4:
@@ -2113,7 +2104,7 @@
:async_temporary_1 = sum;
:async_temporary_0 = i.{dart.core::num::+}(j);
[yield] let dynamic #t4 = dart.async::_awaitHelper(#lib::foo(), :async_op_then, :async_op_error, :async_op) in null;
- sum = :async_temporary_1.{dart.core::num::+}(:async_temporary_0.{dart.core::num::+}(:result));
+ sum = :async_temporary_1.{dart.core::num::+}(:async_temporary_0.{dart.core::num::+}(dart._internal::unsafeCast<dart.core::int*>(:result)));
}
}
for (dart.core::int* k = 0; k.{dart.core::num::<}(10); k = k.{dart.core::num::+}(1)) {
@@ -2140,16 +2131,16 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
dynamic :saved_try_context_var2;
dynamic :exception0;
dynamic :stack_trace0;
- dynamic :async_temporary_0;
- dynamic :async_temporary_1;
- dynamic :async_temporary_2;
+ dart.core::int* :async_temporary_0;
+ dart.core::int* :async_temporary_1;
+ dart.core::int* :async_temporary_2;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
try {
#L5:
@@ -2159,7 +2150,7 @@
try {
:async_temporary_0 = x;
[yield] let dynamic #t5 = dart.async::_awaitHelper(a, :async_op_then, :async_op_error, :async_op) in null;
- x = :async_temporary_0.{dart.core::num::+}(:result);
+ x = :async_temporary_0.{dart.core::num::+}(dart._internal::unsafeCast<dart.core::int*>(:result));
}
on dynamic catch(final dynamic e) {
if(e is dart.core::Error*) {
@@ -2168,14 +2159,14 @@
}
:async_temporary_1 = x;
[yield] let dynamic #t6 = dart.async::_awaitHelper(b, :async_op_then, :async_op_error, :async_op) in null;
- x = :async_temporary_1.{dart.core::num::+}(:result);
+ x = :async_temporary_1.{dart.core::num::+}(dart._internal::unsafeCast<dart.core::int*>(:result));
rethrow;
}
finally {
dart.core::print("fin");
:async_temporary_2 = x;
[yield] let dynamic #t7 = dart.async::_awaitHelper(c, :async_op_then, :async_op_error, :async_op) in null;
- x = :async_temporary_2.{dart.core::num::+}(:result);
+ x = :async_temporary_2.{dart.core::num::+}(dart._internal::unsafeCast<dart.core::int*>(:result));
:return_value = x;
break #L5;
}
@@ -2200,7 +2191,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
dynamic :saved_try_context_var1;
@@ -2212,7 +2203,7 @@
try {
x = 5;
[yield] let dynamic #t8 = dart.async::_awaitHelper(a, :async_op_then, :async_op_error, :async_op) in null;
- y = :result;
+ y = dart._internal::unsafeCast<dart.core::int*>(:result);
:return_value = x.{dart.core::num::+}(y);
break #L6;
}
@@ -2240,7 +2231,7 @@
dynamic :async_stack_trace;
dynamic :async_op_then;
dynamic :async_op_error;
- dynamic :await_jump_var = 0;
+ dart.core::int* :await_jump_var = 0;
dynamic :await_ctx_var;
dynamic :saved_try_context_var0;
function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding
@@ -2249,7 +2240,7 @@
{
assert {
[yield] let dynamic #t9 = dart.async::_awaitHelper(a, :async_op_then, :async_op_error, :async_op) in null;
- assert(:result.{dart.core::num::==}(42));
+ assert(dart._internal::unsafeCast<dart.core::int*>(:result).{dart.core::num::==}(42));
}
:return_value = 7;
break #L7;
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 c6072b8..96a9042 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
@@ -8,13 +8,13 @@
t0* = _Call direct [#lib::foo] ()
t1 = _TypeCheck (t0 against dart.core::bool) (for #lib::foo() as{TypeError} dart.core::bool*)
t2* = _Call direct [#lib::bar] ()
-t3* = _Call [dart.core::num::+] (_T (dart.core::int*)+?, _T (dart.core::_Smi))
+t3* = _Call [dart.core::num::+] (_T (dart.core::int)+?, _T (dart.core::_Smi))
i = _Join [dart.core::int*] (_T (dart.core::_Smi), t3)
t5* = _Call [dart.core::num::<] (i, _T (dart.core::_Smi))
t6* = _Call direct [#lib::bar] ()
-x = _Join [dart.core::bool*] (t6, _T (dart.core::bool*)+)
+x = _Join [dart.core::bool*] (t6, _T (dart.core::bool)+)
t8* = _Call direct [#lib::foo] ()
-t9 = _Join [dynamic] (_T (dart.core::bool*)+, t8)
+t9 = _Join [dynamic] (_T (dart.core::bool)+, t8)
t10 = _Narrow (t9 to _T ANY?)
t11 = _TypeCheck (t10 against dart.core::bool) (for (x{dart.core::bool*} ?{dynamic} true : #lib::foo()) as{TypeError} dart.core::bool*)
t12* = _Call direct [#lib::bar] ()
@@ -23,7 +23,7 @@
t15 = _TypeCheck (t14 against dart.core::bool) (for #lib::foo() as{TypeError} dart.core::bool*)
t16* = _Call direct [#lib::foo] ()
t17 = _TypeCheck (t16 against dart.core::bool) (for #lib::foo() as{TypeError} dart.core::bool*)
-y = _Join [dart.core::bool*] (_T (dart.core::bool*)+, t11, _T (dart.core::bool*)+, _T (dart.core::bool*)+)
+y = _Join [dart.core::bool*] (_T (dart.core::bool)+, t11, _T (dart.core::bool)+, _T (dart.core::bool)+)
RESULT: _T {}?
------------ #lib::main ------------
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
index 5f9c5dd..55cbdec 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/calls.dart.expect
@@ -1,39 +1,39 @@
------------ #lib::A:: ------------
-%this = _Parameter #0 [_T (#lib::A*)+]
+%this = _Parameter #0 [_T (#lib::A)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::A::foo1 ------------
-%this = _Parameter #0 [_T (#lib::A*)+]
-%x = _Parameter #1 [_T (dart.core::Object*)+?]
+%this = _Parameter #0 [_T (#lib::A)+]
+%x = _Parameter #1 [_T (dart.core::Object)+?]
RESULT: _T {}?
------------ #lib::B:: ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
+%this = _Parameter #0 [_T (#lib::B)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::B::bar1 ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
-%arg = _Parameter #1 [_T (dart.core::Object*)+?]
+%this = _Parameter #0 [_T (#lib::B)+]
+%arg = _Parameter #1 [_T (dart.core::Object)+?]
RESULT: _T {}?
------------ #lib::B::bar2 ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
+%this = _Parameter #0 [_T (#lib::B)+]
RESULT: _T {}?
------------ #lib::B::bar3 ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
-%y = _Parameter #1 [_T (dart.core::int*)+?]
+%this = _Parameter #0 [_T (#lib::B)+]
+%y = _Parameter #1 [_T (dart.core::int)+?]
RESULT: _T {}?
------------ #lib::B::bar4 ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
+%this = _Parameter #0 [_T (#lib::B)+]
RESULT: _T {}?
------------ #lib::C:: ------------
-%this = _Parameter #0 [_T (#lib::C*)+]
+%this = _Parameter #0 [_T (#lib::C)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::C::interfaceCalls ------------
-%this = _Parameter #0 [_T (#lib::C*)+]
-%aa = _Parameter #1 [_T (#lib::A*)+?]
-%a2 = _Parameter #2 [_T (dart.core::Object*)+?]
-%a3 = _Parameter #3 [_T (dart.core::Object*)+?]
-%a4 = _Parameter #4 [_T (dart.core::Object*)+?]
+%this = _Parameter #0 [_T (#lib::C)+]
+%aa = _Parameter #1 [_T (#lib::A)+?]
+%a2 = _Parameter #2 [_T (dart.core::Object)+?]
+%a3 = _Parameter #3 [_T (dart.core::Object)+?]
+%a4 = _Parameter #4 [_T (dart.core::Object)+?]
t5 = _Call direct [#lib::B::] (_T (#lib::B))
t6 = _Call [#lib::A::foo1] (%aa, _T (#lib::B))
t7* = _Call get [#lib::A::foo2] (%aa)
@@ -45,11 +45,11 @@
a4 = _Join [dart.core::Object*] (%a4, _T ANY?)
RESULT: a4
------------ #lib::C::dynamicCalls ------------
-%this = _Parameter #0 [_T (#lib::C*)+]
+%this = _Parameter #0 [_T (#lib::C)+]
%aa = _Parameter #1 [_T ANY?]
-%a2 = _Parameter #2 [_T (dart.core::Object*)+?]
-%a3 = _Parameter #3 [_T (dart.core::Object*)+?]
-%a4 = _Parameter #4 [_T (dart.core::Object*)+?]
+%a2 = _Parameter #2 [_T (dart.core::Object)+?]
+%a3 = _Parameter #3 [_T (dart.core::Object)+?]
+%a4 = _Parameter #4 [_T (dart.core::Object)+?]
t5 = _Call direct [#lib::B::] (_T (#lib::B))
t6 = _Call dynamic [foo1] (%aa, _T (#lib::B))
t7* = _Call dynamic get [foo2] (%aa)
@@ -59,15 +59,15 @@
a4 = _Join [dart.core::Object*] (%a4, t10)
RESULT: a4
------------ #lib::D:: ------------
-%this = _Parameter #0 [_T (#lib::D*)+]
+%this = _Parameter #0 [_T (#lib::D)+]
t1 = _Call direct [#lib::B::] (%this)
RESULT: _T {}?
------------ #lib::D::superCalls ------------
-%this = _Parameter #0 [_T (#lib::D*)+]
-%a1 = _Parameter #1 [_T (dart.core::Object*)+?]
-%a2 = _Parameter #2 [_T (dart.core::Object*)+?]
-%a3 = _Parameter #3 [_T (dart.core::Object*)+?]
-%a4 = _Parameter #4 [_T (dart.core::Object*)+?]
+%this = _Parameter #0 [_T (#lib::D)+]
+%a1 = _Parameter #1 [_T (dart.core::Object)+?]
+%a2 = _Parameter #2 [_T (dart.core::Object)+?]
+%a3 = _Parameter #3 [_T (dart.core::Object)+?]
+%a4 = _Parameter #4 [_T (dart.core::Object)+?]
t5 = _Call direct [#lib::B::bar1] (%this, %a1)
t6* = _Call direct get [#lib::B::bar4] (%this)
t7 = _Call direct set [#lib::B::bar3] (%this, t6)
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect
index 4a9d2ed..75d7a9e 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_basic.dart.expect
@@ -1,86 +1,86 @@
------------ #lib::C:: ------------
-%this = _Parameter #0 [_T (#lib::C<dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::C)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::C::foo ------------
-%this = _Parameter #0 [_T (#lib::C<dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::C)+]
t1 = _Extract (%this[#lib::C/0])
t2 = _CreateConcreteType (#lib::D @ (t1))
t3 = _Call direct [#lib::D::] (t2)
RESULT: t2
------------ #lib::C::id1 ------------
-%this = _Parameter #0 [_T (#lib::C<dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::C)+]
%x = _Parameter #1
t2 = _Extract (%this[#lib::C/0])
t3 = _TypeCheck (%x against t2) (for x)
RESULT: t3
------------ #lib::C::id2 ------------
-%this = _Parameter #0 [_T (#lib::C<dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::C)+]
%x = _Parameter #1
t2 = _Extract (%this[#lib::C/0])
t3 = _TypeCheck (%x against t2) (for x)
RESULT: t3
------------ #lib::D:: ------------
-%this = _Parameter #0 [_T (#lib::D<dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::D)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::E:: ------------
-%this = _Parameter #0 [_T (#lib::E<dynamic, dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::E)+]
t1 = _Call direct [#lib::C::] (%this)
RESULT: _T {}?
------------ #lib::E::foo ------------
-%this = _Parameter #0 [_T (#lib::E<dynamic, dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::E)+]
t1* = _Call direct [#lib::C::foo] (%this)
RESULT: t1
------------ #lib::E::bar ------------
-%this = _Parameter #0 [_T (#lib::E<dynamic, dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::E)+]
t1 = _Extract (%this[#lib::E/0])
t2 = _CreateConcreteType (#lib::D @ (t1))
t3 = _Call direct [#lib::D::] (t2)
RESULT: t2
------------ #lib::E::baz ------------
-%this = _Parameter #0 [_T (#lib::E<dynamic, dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::E)+]
t1 = _Extract (%this[#lib::E/1])
t2 = _CreateConcreteType (#lib::D @ (t1))
t3 = _Call direct [#lib::D::] (t2)
RESULT: t2
------------ #lib::X:: ------------
-%this = _Parameter #0 [_T (#lib::X*)+]
+%this = _Parameter #0 [_T (#lib::X)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::Y:: ------------
-%this = _Parameter #0 [_T (#lib::Y*)+]
+%this = _Parameter #0 [_T (#lib::Y)+]
t1 = _Call direct [#lib::X::] (%this)
RESULT: _T {}?
------------ #lib::Z:: ------------
-%this = _Parameter #0 [_T (#lib::Z*)+]
+%this = _Parameter #0 [_T (#lib::Z)+]
t1 = _Call direct [#lib::X::] (%this)
RESULT: _T {}?
------------ #lib::I:: ------------
-%this = _Parameter #0 [_T (#lib::I<dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::I)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::J:: ------------
-%this = _Parameter #0 [_T (#lib::J*)+]
+%this = _Parameter #0 [_T (#lib::J)+]
t1 = _Call direct [#lib::I::] (%this)
RESULT: _T {}?
------------ #lib::K:: ------------
-%this = _Parameter #0 [_T (#lib::K<dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::K)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::C2:: ------------
-%this = _Parameter #0 [_T (#lib::C2<dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::C2)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::C2::id3 ------------
-%this = _Parameter #0 [_T (#lib::C2<dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::C2)+]
%x = _Parameter #1
t2 = _Extract (%this[#lib::C2/0])
t3 = _CreateRuntimeType (dart.core::Comparable @ (t2))
t4 = _TypeCheck (%x against t3) (for x)
RESULT: t4
------------ #lib::C2::id4 ------------
-%this = _Parameter #0 [_T (#lib::C2<dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::C2)+]
%x = _Parameter #1
t2 = _Extract (%this[#lib::C2/0])
t3 = _CreateRuntimeType (#lib::I @ (t2))
@@ -102,7 +102,7 @@
t11 = _Call direct [#lib::Z::] (_T (#lib::Z))
t12 = _Call [#lib::C::id2] (_T (#lib::C<#lib::Y>), _T (#lib::Z))
t13 = _Call direct [#lib::C2::] (_T (#lib::C2<dart.core::num>))
-t14 = _Call [#lib::C2::id3] (_T (#lib::C2<dart.core::num>), _T (dart.core::double*)+)
+t14 = _Call [#lib::C2::id3] (_T (#lib::C2<dart.core::num>), _T (dart.core::double)+)
t15 = _Call direct [#lib::K::] (_T (#lib::K<#lib::J>))
t16 = _Call [#lib::C2::id4] (_T (#lib::C2<dart.core::num>), _T (#lib::K<#lib::J>))
used = _Join [dynamic] (_T {}?, t1, t3, t5, t7)
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
index 1f6fa5b..6c510f9 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/class_generics_case1.dart.expect
@@ -1,5 +1,5 @@
------------ #lib::Element:: ------------
-%this = _Parameter #0 [_T (#lib::Element*)+]
+%this = _Parameter #0 [_T (#lib::Element)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::MockHashMap:: ------------
@@ -9,11 +9,11 @@
t3 = _Call direct [#lib::_NotRealHashMap::] (t2)
RESULT: t2
------------ #lib::_NotRealHashMap:: ------------
-%this = _Parameter #0 [_T (#lib::_NotRealHashMap<dynamic, dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::_NotRealHashMap)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::_NotRealHashMap::setEntry ------------
-%this = _Parameter #0 [_T (#lib::_NotRealHashMap<dynamic, dynamic>*)+]
+%this = _Parameter #0 [_T (#lib::_NotRealHashMap)+]
%key = _Parameter #1
%value = _Parameter #2
t3 = _Extract (%this[#lib::_NotRealHashMap/0])
@@ -22,18 +22,18 @@
t6 = _TypeCheck (%value against t5) (for value)
RESULT: _T {}?
------------ #lib::InheritedElement:: ------------
-%this = _Parameter #0 [_T (#lib::InheritedElement*)+]
+%this = _Parameter #0 [_T (#lib::InheritedElement)+]
t1 = _Call direct [#lib::Element::] (%this)
RESULT: _T {}?
------------ #lib::InheritedElement::setDependencies ------------
-%this = _Parameter #0 [_T (#lib::InheritedElement*)+]
-%dependent = _Parameter #1 [_T (#lib::Element*)+?]
-%value = _Parameter #2 [_T (dart.core::Object*)+?]
+%this = _Parameter #0 [_T (#lib::InheritedElement)+]
+%dependent = _Parameter #1 [_T (#lib::Element)+?]
+%value = _Parameter #2 [_T (dart.core::Object)+?]
t3* = _Call virtual get [#lib::InheritedElement::_dependents] (%this)
t4 = _Call [#lib::MockHashMap::setEntry] (t3, %dependent, %value)
RESULT: _T {}?
------------ #lib::InheritedElement::_dependents ------------
-%this = _Parameter #0 [_T (#lib::InheritedElement*)+]
+%this = _Parameter #0 [_T (#lib::InheritedElement)+]
t1* = _Call direct [#lib::MockHashMap::] (#lib::Element, dart.core::Object)
RESULT: t1
------------ #lib::main ------------
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
index 39e0f94..40d9eb1 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
@@ -3,15 +3,15 @@
RESULT: _T (dart.core::_Smi)
------------ #lib::intLiteral ------------
-RESULT: _T (dart.core::int*)+
+RESULT: _T (dart.core::int)+
------------ #lib::strLiteral ------------
RESULT: _T (dart.core::_OneByteString)
------------ #lib::indexingIntoConstantList1 ------------
-%i = _Parameter #0 [_T (dart.core::int*)+?]
+%i = _Parameter #0 [_T (dart.core::int)+?]
RESULT: _T (dart.core::_Smi)
------------ #lib::indexingIntoConstantList2 ------------
-%i = _Parameter #0 [_T (dart.core::int*)+?]
+%i = _Parameter #0 [_T (dart.core::int)+?]
t1 = _Join [dart.core::Object*] (_T (dart.core::_OneByteString), _T (dart.core::_Smi), _T {}?)
RESULT: t1
------------ #lib::main ------------
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
index 5488d3d..31ccb74 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
@@ -1,4 +1,4 @@
------------ #lib::main ------------
-%args = _Parameter #0 [_T (dart.core::List<dynamic>*)+?]
+%args = _Parameter #0 [_T (dart.core::List)+?]
t1 = _Call direct [dart.core::print] (_T (dart.core::_OneByteString))
RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect
index 0546dec..9a3e510 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/implicit_return_null.dart.expect
@@ -1,5 +1,5 @@
------------ #lib::T:: ------------
-%this = _Parameter #0 [_T (#lib::T*)+]
+%this = _Parameter #0 [_T (#lib::T)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::empty1 ------------
@@ -18,7 +18,7 @@
t0 = _Call direct [#lib::T::] (_T (#lib::T))
RESULT: _T (#lib::T)
------------ #lib::return2 ------------
-%i = _Parameter #0 [_T (dart.core::int*)+?]
+%i = _Parameter #0 [_T (dart.core::int)+?]
t1* = _Call [dart.core::num::-] (%i, _T (dart.core::_Smi))
t2* = _Call direct [#lib::return2] (t1)
RESULT: t2
@@ -32,77 +32,77 @@
t0 = _Call direct [#lib::T::] (_T (#lib::T))
RESULT: _T {}?
------------ #lib::expr2 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
t1 = _Call direct [#lib::T::] (_T (#lib::T))
t2 = _Call direct [#lib::T::] (_T (#lib::T))
%result = _Join [dynamic] (_T (#lib::T), _T {}?)
RESULT: %result
------------ #lib::expr3 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
-%x = _Parameter #1 [_T (dart.core::Object*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
+%x = _Parameter #1 [_T (dart.core::Object)+?]
t2 = _Call direct [#lib::T::] (_T (#lib::T))
t3 = _Call [dart.core::Object::toString] (%x)
%result = _Join [dynamic] (_T (#lib::T), _T {}?)
RESULT: %result
------------ #lib::throw1 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
-%x = _Parameter #1 [_T (dart.core::Object*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
+%x = _Parameter #1 [_T (dart.core::Object)+?]
RESULT: _T {}
------------ #lib::throw2 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
-%x = _Parameter #1 [_T (dart.core::Object*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
+%x = _Parameter #1 [_T (dart.core::Object)+?]
t2 = _Call direct [#lib::T::] (_T (#lib::T))
RESULT: _T (#lib::T)
------------ #lib::loop1 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
-%x = _Parameter #1 [_T (dart.core::Object*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
+%x = _Parameter #1 [_T (dart.core::Object)+?]
RESULT: _T {}?
------------ #lib::loop2 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
-%x = _Parameter #1 [_T (dart.core::Object*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
+%x = _Parameter #1 [_T (dart.core::Object)+?]
t2 = _Call direct [#lib::T::] (_T (#lib::T))
%result = _Join [dynamic] (_T (#lib::T), _T {}?)
RESULT: %result
------------ #lib::loop3 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
-%x = _Parameter #1 [_T (dart.core::Object*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
+%x = _Parameter #1 [_T (dart.core::Object)+?]
t2 = _Call direct [#lib::T::] (_T (#lib::T))
%result = _Join [dynamic] (_T (#lib::T), _T {}?)
RESULT: %result
------------ #lib::switch_ ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
-%i = _Parameter #1 [_T (dart.core::int*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
+%i = _Parameter #1 [_T (dart.core::int)+?]
t2 = _Call direct [#lib::T::] (_T (#lib::T))
%result = _Join [dynamic] (_T (#lib::T), _T {}?)
RESULT: %result
------------ #lib::if1 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
t1 = _Call direct [#lib::T::] (_T (#lib::T))
RESULT: _T (#lib::T)
------------ #lib::if2 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
t1 = _Call direct [#lib::T::] (_T (#lib::T))
%result = _Join [dynamic] (_T (#lib::T), _T {}?)
RESULT: %result
------------ #lib::if3 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
RESULT: _T {}?
------------ #lib::if4 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
RESULT: _T {}?
------------ #lib::if5 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
t1* = _Call direct [#lib::if5] (%c)
-t2* = _Call direct [#lib::if5] (_T (dart.core::bool*)+)
+t2* = _Call direct [#lib::if5] (_T (dart.core::bool)+)
%result = _Join [void] (t1, t2, _T {}?)
RESULT: %result
------------ #lib::label1 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
t1 = _Call direct [#lib::T::] (_T (#lib::T))
%result = _Join [dynamic] (_T (#lib::T), _T {}?)
RESULT: %result
------------ #lib::try1 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
t1 = _Call direct [#lib::T::] (_T (#lib::T))
%result = _Join [dynamic] (_T (#lib::T), _T {}?)
RESULT: %result
@@ -114,7 +114,7 @@
t0 = _Call direct [#lib::T::] (_T (#lib::T))
RESULT: _T (#lib::T)
------------ #lib::try4 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
t1 = _Call direct [#lib::T::] (_T (#lib::T))
%result = _Join [dynamic] (_T (#lib::T), _T {}?)
RESULT: %result
@@ -125,7 +125,7 @@
t0 = _Call direct [#lib::T::] (_T (#lib::T))
RESULT: _T (#lib::T)
------------ #lib::try7 ------------
-%c = _Parameter #0 [_T (dart.core::bool*)+?]
+%c = _Parameter #0 [_T (dart.core::bool)+?]
t1 = _Call direct [#lib::T::] (_T (#lib::T))
RESULT: _T (#lib::T)
------------ #lib::main ------------
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/setter_result.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/setter_result.dart.expect
index ceb6d33..e79a010 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/setter_result.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/setter_result.dart.expect
@@ -1,43 +1,43 @@
------------ #lib::T:: ------------
-%this = _Parameter #0 [_T (#lib::T*)+]
+%this = _Parameter #0 [_T (#lib::T)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::A:: ------------
-%this = _Parameter #0 [_T (#lib::A*)+]
+%this = _Parameter #0 [_T (#lib::A)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::A::foo ------------
-%this = _Parameter #0 [_T (#lib::A*)+]
+%this = _Parameter #0 [_T (#lib::A)+]
RESULT: _T {}?
------------ #lib::B:: ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
+%this = _Parameter #0 [_T (#lib::B)+]
t1 = _Call direct [#lib::A::] (%this)
RESULT: _T {}?
------------ #lib::B::foo ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
+%this = _Parameter #0 [_T (#lib::B)+]
%x = _Parameter #1 [_T ANY?]
RESULT: _T {}?
------------ #lib::B::testPropertySet ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
+%this = _Parameter #0 [_T (#lib::B)+]
%x = _Parameter #1 [_T ANY?]
t2 = _Call virtual set [#lib::B::foo] (%this, %x)
t3 = _Call direct [#lib::use] (%x)
RESULT: _T {}?
------------ #lib::B::testDynamicPropertySet ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
+%this = _Parameter #0 [_T (#lib::B)+]
%x = _Parameter #1 [_T ANY?]
%y = _Parameter #2 [_T ANY?]
t3 = _Call dynamic set [foo] (%x, %y)
t4 = _Call direct [#lib::use] (%y)
RESULT: _T {}?
------------ #lib::B::testSuperPropertySet ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
+%this = _Parameter #0 [_T (#lib::B)+]
%x = _Parameter #1 [_T ANY?]
t2 = _Call direct set [#lib::A::foo] (%this, %x)
t3 = _Call direct [#lib::use] (%x)
RESULT: _T {}?
------------ #lib::B::testStaticPropertySet ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
+%this = _Parameter #0 [_T (#lib::B)+]
%x = _Parameter #1 [_T ANY?]
t2 = _Call direct set [#lib::B::bar] (%x)
t3 = _Call direct [#lib::use] (%x)
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 81dbe5b..107564e 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
@@ -1,14 +1,14 @@
------------ #lib::A:: ------------
-%this = _Parameter #0 [_T (#lib::A*)+]
+%this = _Parameter #0 [_T (#lib::A)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::B:: ------------
-%this = _Parameter #0 [_T (#lib::B*)+]
+%this = _Parameter #0 [_T (#lib::B)+]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::foo ------------
-%a1 = _Parameter #0 [_T (dart.core::Object*)+?]
-%a2 = _Parameter #1 [_T (dart.core::Object*)+?]
+%a1 = _Parameter #0 [_T (dart.core::Object)+?]
+%a2 = _Parameter #1 [_T (dart.core::Object)+?]
t2* = _Call direct get [#lib::someStatic] ()
t3 = _Call direct [#lib::A::] (_T (#lib::A))
a1 = _Join [dart.core::Object*] (%a1, _T (#lib::A), _T (#lib::B))
@@ -16,29 +16,29 @@
t6 = _Call direct [#lib::B::] (_T (#lib::B))
t7* = _Call [dart.core::Object::==] (a1, %a2)
t8 = _Join [dart.core::Object*] (a1, %a2)
-t9 = _Narrow (t8 to _T (dart.core::Object*)+?)
+t9 = _Narrow (t8 to _T (dart.core::Object)+?)
RESULT: t9
------------ #lib::bar ------------
-%a1 = _Parameter #0 [_T (dart.core::Object*)+?]
-%a2 = _Parameter #1 [_T (dart.core::int*)+?]
-t2 = _Narrow (%a1 to _T (dart.core::int*)+)
+%a1 = _Parameter #0 [_T (dart.core::Object)+?]
+%a2 = _Parameter #1 [_T (dart.core::int)+?]
+t2 = _Narrow (%a1 to _T (dart.core::int)+)
t3* = _Call [dart.core::num::+] (t2, %a2)
t4* = _Call [dart.core::num::*] (t3, _T (dart.core::_Smi))
t5* = _Call [dart.core::int::unary-] (_T (dart.core::_Smi))
%result = _Join [dart.core::int*] (t4, t5)
RESULT: %result
------------ #lib::loop1 ------------
-%a1 = _Parameter #0 [_T (dart.core::Object*)+?]
-%a2 = _Parameter #1 [_T (dart.core::Object*)+?]
-t2* = _Call direct [#lib::loop1] (_T (dart.core::Object*)+?, %a1)
+%a1 = _Parameter #0 [_T (dart.core::Object)+?]
+%a2 = _Parameter #1 [_T (dart.core::Object)+?]
+t2* = _Call direct [#lib::loop1] (_T (dart.core::Object)+?, %a1)
x = _Join [dart.core::Object*] (%a1, t2, %a2)
RESULT: x
------------ #lib::loop2 ------------
-%x = _Parameter #0 [_T (dart.core::int*)+?]
-t1* = _Call [dart.core::num::+] (_T (dart.core::int*)+?, _T (dart.core::_Smi))
+%x = _Parameter #0 [_T (dart.core::int)+?]
+t1* = _Call [dart.core::num::+] (_T (dart.core::int)+?, _T (dart.core::_Smi))
i = _Join [dart.core::int*] (_T (dart.core::_Smi), t1)
t3* = _Call [dart.core::num::<] (i, _T (dart.core::_Smi))
-t4* = _Call [dart.core::num::+] (_T (dart.core::int*)+?, _T (dart.core::_Smi))
+t4* = _Call [dart.core::num::+] (_T (dart.core::int)+?, _T (dart.core::_Smi))
x = _Join [dart.core::int*] (%x, t4)
RESULT: x
------------ #lib::main ------------
diff --git a/pkg/vm_service/README.md b/pkg/vm_service/README.md
index a87d2bc..11194fd 100644
--- a/pkg/vm_service/README.md
+++ b/pkg/vm_service/README.md
@@ -1,6 +1,6 @@
# vm_service
-[![pub package](https://img.shields.io/pub/v/vm_service.svg)](https://pub.dartlang.org/packages/vm_service)
+[![pub package](https://img.shields.io/pub/v/vm_service.svg)](https://pub.dev/packages/vm_service)
A library to access the VM Service Protocol.
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 4933877..50a049d 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -540,7 +540,9 @@
]
args = []
if (use_nnbd) {
- args += [ "--enable-experiment=non-nullable" ]
+ # TODO(sigmund): reenable this flag once the CFE can build targets without
+ # issues.
+ # args += [ "--enable-experiment=non-nullable" ]
}
args += [
"--deterministic",
diff --git a/runtime/bin/vmservice/loader.dart b/runtime/bin/vmservice/loader.dart
index a450179..7407e50 100644
--- a/runtime/bin/vmservice/loader.dart
+++ b/runtime/bin/vmservice/loader.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.6
+
part of vmservice_io;
_sanitizeWindowsPath(path) {
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index f4cfc6a..88ee8fe 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.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.6
+
part of vmservice_io;
final bool silentObservatory = new bool.fromEnvironment('SILENT_OBSERVATORY');
diff --git a/runtime/bin/vmservice/vmservice_io.dart b/runtime/bin/vmservice/vmservice_io.dart
index 393f1f3..4ed2f63 100644
--- a/runtime/bin/vmservice/vmservice_io.dart
+++ b/runtime/bin/vmservice/vmservice_io.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.6
+
library vmservice_io;
import 'dart:async';
diff --git a/runtime/docs/aot_binary_size_analysis.md b/runtime/docs/aot_binary_size_analysis.md
index 71e66fc..160b03d 100644
--- a/runtime/docs/aot_binary_size_analysis.md
+++ b/runtime/docs/aot_binary_size_analysis.md
@@ -17,6 +17,12 @@
% pkg/vm/tool/precompiler2 --print-instructions-sizes-to=hello_sizes.json hello.dart hello.dart.aot
```
+In Flutter, pass this argument to `flutter build`:
+
+```
+% flutter build aot --release --extra-gen-snapshot-options=--print-instructions-sizes-to=hello_sizes.json
+```
+
## Visualizing the information from the binary size json file
To visualize the information emitted by the AOT compiler one can use our binary
@@ -42,3 +48,25 @@
+---------+--------+--------------+
...
```
+
+## Object-level data
+
+gen_snapshot also accepts an extra `--write-v8-snapshot-profile-to=hello.heapsnapshot`
+flag. If supplied the AOT compiler will emit snapshot size information for all objects in the snapshot
+to `sizes.json` in V8 snapshot format.
+
+This flag can be passed to `gen_snapshot` directly, or to the various wrapper
+scripts (e.g. `pkg/vm/tool/precompiler2`):
+
+```
+% tools/build.py -mrelease -ax64 runtime_kernel dart_precompiled_runtime
+% pkg/vm/tool/precompiler2 --write-v8-snapshot-profile-to=hello.heapsnapshot hello.dart hello.dart.aot
+```
+
+In Flutter, pass this argument to `flutter build`:
+
+```
+% flutter build aot --release --extra-gen-snapshot-options=--write-v8-snapshot-profile-to=hello.heapsnapshot
+```
+
+This output can be visualized by loading it in the "Memory" tab in Chrome's developer tools, or by loading it into [Graph Explorer](../tools/graphexplorer/graphexplorer.html).
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 355d1e3..9a7b24e 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -277,7 +277,8 @@
auto& new_value_type =
AbstractType::Handle(zone, new_value.GetType(Heap::kNew));
- if (!new_value_type.IsSubtypeOf(pointer_type_arg, Heap::kNew)) {
+ if (!new_value_type.IsSubtypeOf(NNBDMode::kLegacy, pointer_type_arg,
+ Heap::kNew)) {
const String& error = String::Handle(String::NewFormatted(
"New value (%s) is not a subtype of '%s'.",
String::Handle(new_value_type.UserVisibleName()).ToCString(),
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 058f2ec..465c84f 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -28,11 +28,6 @@
namespace dart {
-DEFINE_FLAG(bool,
- enable_isolate_groups,
- true,
- "Whether to enable support for isolate groups.");
-
DEFINE_NATIVE_ENTRY(CapabilityImpl_factory, 0, 1) {
ASSERT(
TypeArguments::CheckedHandle(zone, arguments->NativeArgAt(0)).IsNull());
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 9c8f617..9a1ca57 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -633,16 +633,17 @@
// TODO(regis): Until mirrors reflect nullability, force kLegacy, except for
// Null type, which should remain nullable.
if (!type.IsNullType()) {
- const Type& legacy_type =
- Type::Handle(Type::Cast(type).ToNullability(kLegacy, Heap::kOld));
+ const Type& legacy_type = Type::Handle(
+ Type::Cast(type).ToNullability(Nullability::kLegacy, Heap::kOld));
return CreateClassMirror(cls, legacy_type, Bool::False(),
Object::null_instance());
}
return CreateClassMirror(cls, type, Bool::False(), Object::null_instance());
} else if (type.IsTypeParameter()) {
// TODO(regis): Until mirrors reflect nullability, force kLegacy.
- const TypeParameter& legacy_type = TypeParameter::Handle(
- TypeParameter::Cast(type).ToNullability(kLegacy, Heap::kOld));
+ const TypeParameter& legacy_type =
+ TypeParameter::Handle(TypeParameter::Cast(type).ToNullability(
+ Nullability::kLegacy, Heap::kOld));
return CreateTypeVariableMirror(legacy_type, Object::null_instance());
}
UNREACHABLE();
@@ -710,8 +711,8 @@
instantiator_type_args = instantiator.arguments();
}
AbstractType& result = AbstractType::Handle(type.InstantiateFrom(
- instantiator_type_args, Object::null_type_arguments(), kAllFree, NULL,
- Heap::kOld));
+ NNBDMode::kLegacy, instantiator_type_args, Object::null_type_arguments(),
+ kAllFree, NULL, Heap::kOld));
ASSERT(result.IsFinalized());
return result.Canonicalize();
}
@@ -1480,8 +1481,8 @@
// type arguments of the type reflected by the class mirror.
ASSERT(redirect_type.IsInstantiated(kFunctions));
redirect_type ^= redirect_type.InstantiateFrom(
- type_arguments, Object::null_type_arguments(), kNoneFree, NULL,
- Heap::kOld);
+ NNBDMode::kLegacy, type_arguments, Object::null_type_arguments(),
+ kNoneFree, NULL, Heap::kOld);
redirect_type ^= redirect_type.Canonicalize();
}
@@ -1510,7 +1511,8 @@
ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
- if (!redirected_constructor.AreValidArguments(args_descriptor, NULL)) {
+ if (!redirected_constructor.AreValidArguments(NNBDMode::kLegacy,
+ args_descriptor, NULL)) {
external_constructor_name = redirected_constructor.name();
ThrowNoSuchMethod(AbstractType::Handle(klass.RareType()),
external_constructor_name, explicit_args, arg_names,
@@ -1520,7 +1522,7 @@
}
const Object& type_error =
Object::Handle(redirected_constructor.DoArgumentTypesMatch(
- args, args_descriptor, type_arguments));
+ NNBDMode::kLegacy, args, args_descriptor, type_arguments));
if (!type_error.IsNull()) {
Exceptions::PropagateError(Error::Cast(type_error));
UNREACHABLE();
@@ -1758,7 +1760,7 @@
DEFINE_NATIVE_ENTRY(TypeMirror_subtypeTest, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, a, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(AbstractType, b, arguments->NativeArgAt(1));
- return Bool::Get(a.IsSubtypeOf(b, Heap::kNew)).raw();
+ return Bool::Get(a.IsSubtypeOf(NNBDMode::kLegacy, b, Heap::kNew)).raw();
}
#endif // !DART_PRECOMPILED_RUNTIME
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 7d40155..c7b78de 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -141,8 +141,9 @@
const AbstractType& type =
AbstractType::CheckedHandle(zone, arguments->NativeArgAt(3));
ASSERT(type.IsFinalized());
- const bool is_instance_of = instance.IsInstanceOf(
- type, instantiator_type_arguments, function_type_arguments);
+ const bool is_instance_of = instance.IsInstanceOf(NNBDMode::kLegacy, type,
+ instantiator_type_arguments,
+ function_type_arguments);
if (FLAG_trace_type_checks) {
const char* result_str = is_instance_of ? "true" : "false";
OS::PrintErr("Native Object.instanceOf: result %s\n", result_str);
@@ -166,7 +167,8 @@
ASSERT(type.IsFinalized());
ASSERT(type.IsInstantiated());
const bool is_instance_of = instance.IsInstanceOf(
- type, Object::null_type_arguments(), Object::null_type_arguments());
+ NNBDMode::kLegacy, type, Object::null_type_arguments(),
+ Object::null_type_arguments());
return Bool::Get(is_instance_of).raw();
}
@@ -223,8 +225,8 @@
if (!cur_interface_type_args.IsNull() &&
!cur_interface_type_args.IsInstantiated()) {
cur_interface_type_args = cur_interface_type_args.InstantiateFrom(
- instance_type_args, Object::null_type_arguments(), kNoneFree, NULL,
- Heap::kNew);
+ NNBDMode::kLegacy, instance_type_args,
+ Object::null_type_arguments(), kNoneFree, NULL, Heap::kNew);
}
if (ExtractInterfaceTypeArgs(zone, cur_interface_cls,
cur_interface_type_args, interface_cls,
@@ -378,7 +380,8 @@
// The supertype may not be instantiated.
if (!AbstractType::InstantiateAndTestSubtype(
- &subtype, &supertype, instantiator_type_args, function_type_args)) {
+ NNBDMode::kLegacy, &subtype, &supertype, instantiator_type_args,
+ function_type_args)) {
// Throw a dynamic type error.
TokenPosition location;
{
diff --git a/runtime/lib/stacktrace.cc b/runtime/lib/stacktrace.cc
index 1b9600a..1df0056 100644
--- a/runtime/lib/stacktrace.cc
+++ b/runtime/lib/stacktrace.cc
@@ -23,7 +23,7 @@
// Determine how big the stack trace is.
const intptr_t stack_trace_length =
- StackTraceUtils::CountFrames(thread, skip_frames, null_function);
+ StackTraceUtils::CountFrames(thread, skip_frames, null_function, nullptr);
// Allocate once.
const Array& code_array =
@@ -64,8 +64,9 @@
// Determine the size of the stack trace.
const intptr_t extra_frames = for_async_function ? 1 : 0;
- const intptr_t synchronous_stack_trace_length =
- StackTraceUtils::CountFrames(thread, skip_frames, async_function);
+ bool sync_async_end = false;
+ const intptr_t synchronous_stack_trace_length = StackTraceUtils::CountFrames(
+ thread, skip_frames, async_function, &sync_async_end);
const intptr_t capacity = synchronous_stack_trace_length +
extra_frames; // For the asynchronous gap.
@@ -94,7 +95,11 @@
ASSERT(write_cursor == capacity);
- return StackTrace::New(code_array, pc_offset_array, async_stack_trace);
+ const StackTrace& result = StackTrace::Handle(
+ zone, StackTrace::New(code_array, pc_offset_array, async_stack_trace,
+ sync_async_end));
+
+ return result.raw();
}
RawStackTrace* GetStackTraceForException() {
diff --git a/runtime/observatory/lib/src/allocation_profile/allocation_profile.dart b/runtime/observatory/lib/src/allocation_profile/allocation_profile.dart
index fa64125..c1e7aa1 100644
--- a/runtime/observatory/lib/src/allocation_profile/allocation_profile.dart
+++ b/runtime/observatory/lib/src/allocation_profile/allocation_profile.dart
@@ -11,6 +11,7 @@
final DateTime lastAccumulatorReset;
final S.HeapSpace newSpace;
final S.HeapSpace oldSpace;
+ final S.HeapSpace totalSpace;
final Iterable<M.ClassHeapStats> members;
AllocationProfile(S.ServiceMap map, {Map/*<String, List<String>>*/ defaults})
@@ -18,7 +19,11 @@
lastServiceGC = _intString2DateTime(map[_lastServiceGC]),
oldSpace = new S.HeapSpace()..update(map['_heaps']['old']),
newSpace = new S.HeapSpace()..update(map['_heaps']['new']),
- members = _convertMembers(map['members'], defaults: defaults);
+ totalSpace = new S.HeapSpace(),
+ members = _convertMembers(map['members'], defaults: defaults) {
+ totalSpace.add(oldSpace);
+ totalSpace.add(newSpace);
+ }
static DateTime _intString2DateTime(String milliseconds) {
if ((milliseconds == null) || milliseconds == '') {
@@ -66,15 +71,11 @@
final String displayName = null;
final S.Allocations newSpace;
final S.Allocations oldSpace;
- final int promotedInstances;
- final int promotedBytes;
ClassHeapStats(Map map)
: clazz = map['class'],
oldSpace = new S.Allocations()..update(map['_old']),
- newSpace = new S.Allocations()..update(map['_new']),
- promotedInstances = map['_promotedInstances'],
- promotedBytes = map['_promotedBytes'];
+ newSpace = new S.Allocations()..update(map['_new']);
}
class ClassesHeapStats implements M.ClassHeapStats {
@@ -82,12 +83,8 @@
final String displayName;
final S.Allocations newSpace;
final S.Allocations oldSpace;
- final int promotedInstances;
- final int promotedBytes;
ClassesHeapStats(this.displayName, Iterable<ClassHeapStats> classes)
: oldSpace = new S.Allocations()..combine(classes.map((m) => m.oldSpace)),
- newSpace = new S.Allocations()..combine(classes.map((m) => m.newSpace)),
- promotedInstances = classes.fold(0, (v, m) => v + m.promotedInstances),
- promotedBytes = classes.fold(0, (v, m) => v + m.promotedBytes);
+ newSpace = new S.Allocations()..combine(classes.map((m) => m.newSpace));
}
diff --git a/runtime/observatory/lib/src/elements/allocation_profile.dart b/runtime/observatory/lib/src/elements/allocation_profile.dart
index b4ddc92..d589289 100644
--- a/runtime/observatory/lib/src/elements/allocation_profile.dart
+++ b/runtime/observatory/lib/src/elements/allocation_profile.dart
@@ -21,18 +21,18 @@
import 'package:observatory/utils.dart';
enum _SortingField {
- accumulatedSize,
- accumulatedInstances,
- currentSize,
- currentInstances,
- newAccumulatedSize,
- newAccumulatedInstances,
- newCurrentSize,
- newCurrentInstances,
- oldAccumulatedSize,
- oldAccumulatedInstances,
- oldCurrentSize,
- oldCurrentInstances,
+ newInstances,
+ newInternalSize,
+ newExternalSize,
+ newSize,
+ oldInstances,
+ oldInternalSize,
+ oldExternalSize,
+ oldSize,
+ instances,
+ internalSize,
+ externalSize,
+ size,
className,
}
@@ -64,7 +64,7 @@
bool _autoRefresh = false;
bool _isCompacted = false;
StreamSubscription _gcSubscription;
- _SortingField _sortingField = _SortingField.currentSize;
+ _SortingField _sortingField = _SortingField.size;
_SortingDirection _sortingDirection = _SortingDirection.descending;
M.VMRef get vm => _vm;
@@ -126,9 +126,6 @@
label: 'Download', disabled: _profile == null, queue: _r.queue)
..onRefresh.listen((_) => _downloadCSV()))
.element,
- (new NavRefreshElement(label: 'Reset Accumulator', queue: _r.queue)
- ..onRefresh.listen((_) => _refresh(reset: true)))
- .element,
(new NavRefreshElement(label: 'GC', queue: _r.queue)
..onRefresh.listen((_) => _refresh(gc: true)))
.element,
@@ -166,6 +163,8 @@
final newChartLegend = new DivElement()..classes = ['legend'];
final oldChartHost = new DivElement()..classes = ['host'];
final oldChartLegend = new DivElement()..classes = ['legend'];
+ final totalChartHost = new DivElement()..classes = ['host'];
+ final totalChartLegend = new DivElement()..classes = ['legend'];
children.addAll([
new DivElement()
..classes = ['content-centered-big']
@@ -187,18 +186,6 @@
? '---'
: '${_profile.lastServiceGC}',
],
- new DivElement()
- ..classes = ['memberItem']
- ..children = <Element>[
- new DivElement()
- ..classes = ['memberName']
- ..text = 'last accumulator reset at',
- new DivElement()
- ..classes = ['memberValue']
- ..text = _profile.lastAccumulatorReset == null
- ? '---'
- : '${_profile.lastAccumulatorReset}',
- ]
],
new HRElement(),
],
@@ -225,12 +212,12 @@
..children = <Element>[newChartLegend, newChartHost]
],
new DivElement()
- ..classes = ['heap-space', 'right']
+ ..classes = ['heap-space', 'left']
..children = _isCompacted
? [
new HeadingElement.h2()
- ..text = '(${_usedCaption(_profile.oldSpace)}) '
- 'Old Generation',
+ ..text = 'Old Generation '
+ '(${_usedCaption(_profile.oldSpace)})',
]
: [
new HeadingElement.h2()..text = 'Old Generation',
@@ -243,13 +230,32 @@
..classes = ['chart']
..children = <Element>[oldChartLegend, oldChartHost]
],
+ new DivElement()
+ ..classes = ['heap-space', 'left']
+ ..children = _isCompacted
+ ? [
+ new HeadingElement.h2()
+ ..text = 'Total '
+ '(${_usedCaption(_profile.totalSpace)})',
+ ]
+ : [
+ new HeadingElement.h2()..text = 'Total',
+ new BRElement(),
+ new DivElement()
+ ..classes = ['memberList']
+ ..children = _createSpaceMembers(_profile.totalSpace),
+ new BRElement(),
+ new DivElement()
+ ..classes = ['chart']
+ ..children = <Element>[totalChartLegend, totalChartHost]
+ ],
new ButtonElement()
..classes = ['compact']
..text = _isCompacted ? 'expand â–¼' : 'compact â–²'
..onClick.listen((_) {
- _isCompacted = !_isCompacted;
- _r.dirty();
- }),
+ _isCompacted = !_isCompacted;
+ _r.dirty();
+ }),
new HRElement()
],
new DivElement()
@@ -266,47 +272,48 @@
]);
_renderGraph(newChartHost, newChartLegend, _profile.newSpace);
_renderGraph(oldChartHost, oldChartLegend, _profile.oldSpace);
+ _renderGraph(totalChartHost, totalChartLegend, _profile.totalSpace);
}
}
_createSorter() {
var getter;
switch (_sortingField) {
- case _SortingField.accumulatedSize:
- getter = _getAccumulatedSize;
+ case _SortingField.newInternalSize:
+ getter = _getNewInternalSize;
break;
- case _SortingField.accumulatedInstances:
- getter = _getAccumulatedInstances;
+ case _SortingField.newExternalSize:
+ getter = _getNewExternalSize;
break;
- case _SortingField.currentSize:
- getter = _getCurrentSize;
+ case _SortingField.newSize:
+ getter = _getNewSize;
break;
- case _SortingField.currentInstances:
- getter = _getCurrentInstances;
+ case _SortingField.newInstances:
+ getter = _getNewInstances;
break;
- case _SortingField.newAccumulatedSize:
- getter = _getNewAccumulatedSize;
+ case _SortingField.oldInternalSize:
+ getter = _getOldInternalSize;
break;
- case _SortingField.newAccumulatedInstances:
- getter = _getNewAccumulatedInstances;
+ case _SortingField.oldExternalSize:
+ getter = _getOldExternalSize;
break;
- case _SortingField.newCurrentSize:
- getter = _getNewCurrentSize;
+ case _SortingField.oldSize:
+ getter = _getOldSize;
break;
- case _SortingField.newCurrentInstances:
- getter = _getNewCurrentInstances;
+ case _SortingField.oldInstances:
+ getter = _getOldInstances;
break;
- case _SortingField.oldAccumulatedSize:
- getter = _getOldAccumulatedSize;
+ case _SortingField.internalSize:
+ getter = _getInternalSize;
break;
- case _SortingField.oldAccumulatedInstances:
- getter = _getOldAccumulatedInstances;
+ case _SortingField.externalSize:
+ getter = _getExternalSize;
break;
- case _SortingField.oldCurrentSize:
- getter = _getOldCurrentSize;
+ case _SortingField.size:
+ getter = _getSize;
break;
- case _SortingField.oldCurrentInstances:
- getter = _getOldCurrentInstances;
+ case _SortingField.instances:
+ getter = _getInstances;
break;
case _SortingField.className:
getter = (M.ClassHeapStats s) => s.clazz.name;
@@ -333,8 +340,8 @@
..classes = ['bytes']
..text = '0B',
new SpanElement()
- ..classes = ['instances']
- ..text = '0',
+ ..classes = ['bytes']
+ ..text = '0B',
new SpanElement()
..classes = ['bytes']
..text = '0B',
@@ -345,8 +352,8 @@
..classes = ['bytes']
..text = '0B',
new SpanElement()
- ..classes = ['instances']
- ..text = '0',
+ ..classes = ['bytes']
+ ..text = '0B',
new SpanElement()
..classes = ['bytes']
..text = '0B',
@@ -357,8 +364,8 @@
..classes = ['bytes']
..text = '0B',
new SpanElement()
- ..classes = ['instances']
- ..text = '0',
+ ..classes = ['bytes']
+ ..text = '0B',
new SpanElement()
..classes = ['bytes']
..text = '0B',
@@ -374,65 +381,53 @@
..children = <Element>[
new SpanElement()
..classes = ['group']
- ..text = 'Accumulated',
+ ..text = 'New Generation',
new SpanElement()
..classes = ['group']
- ..text = 'Current',
+ ..text = 'Old Generation',
new SpanElement()
..classes = ['group']
- ..text = '(NEW) Accumulated',
+ ..text = 'Total',
new SpanElement()
..classes = ['group']
- ..text = '(NEW) Current',
- new SpanElement()
- ..classes = ['group']
- ..text = '(OLD) Accumulated',
- new SpanElement()
- ..classes = ['group']
- ..text = '(OLD) Current',
+ ..text = '',
],
new DivElement()
..classes = ['collection-item']
..children = <Element>[
+ _createHeaderButton(const ['bytes'], 'Internal',
+ _SortingField.newInternalSize, _SortingDirection.descending),
+ _createHeaderButton(const ['bytes'], 'External',
+ _SortingField.newExternalSize, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'Size',
- _SortingField.accumulatedSize, _SortingDirection.descending),
+ _SortingField.newSize, _SortingDirection.descending),
_createHeaderButton(
- const ['instances'],
- 'Instances',
- _SortingField.accumulatedInstances,
+ const ['instances'], 'Instances',
+ _SortingField.newInstances,
_SortingDirection.descending),
+
+ _createHeaderButton(const ['bytes'], 'Internal',
+ _SortingField.oldInternalSize, _SortingDirection.descending),
+ _createHeaderButton(const ['bytes'], 'External',
+ _SortingField.oldExternalSize, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'Size',
- _SortingField.currentSize, _SortingDirection.descending),
- _createHeaderButton(const ['instances'], 'Instances',
- _SortingField.currentInstances, _SortingDirection.descending),
- _createHeaderButton(const ['bytes'], 'Size',
- _SortingField.newAccumulatedSize, _SortingDirection.descending),
+ _SortingField.oldSize, _SortingDirection.descending),
_createHeaderButton(
- const ['instances'],
- 'Instances',
- _SortingField.newAccumulatedInstances,
+ const ['instances'], 'Instances',
+ _SortingField.oldInstances,
_SortingDirection.descending),
+
+ _createHeaderButton(const ['bytes'], 'Internal',
+ _SortingField.internalSize, _SortingDirection.descending),
+ _createHeaderButton(const ['bytes'], 'External',
+ _SortingField.externalSize, _SortingDirection.descending),
_createHeaderButton(const ['bytes'], 'Size',
- _SortingField.newCurrentSize, _SortingDirection.descending),
+ _SortingField.size, _SortingDirection.descending),
_createHeaderButton(
- const ['instances'],
- 'Instances',
- _SortingField.newCurrentInstances,
+ const ['instances'], 'Instances',
+ _SortingField.instances,
_SortingDirection.descending),
- _createHeaderButton(const ['bytes'], 'Size',
- _SortingField.oldAccumulatedSize, _SortingDirection.descending),
- _createHeaderButton(
- const ['instances'],
- 'Instances',
- _SortingField.oldAccumulatedInstances,
- _SortingDirection.descending),
- _createHeaderButton(const ['bytes'], 'Size',
- _SortingField.oldCurrentSize, _SortingDirection.descending),
- _createHeaderButton(
- const ['instances'],
- 'Instances',
- _SortingField.oldCurrentInstances,
- _SortingDirection.descending),
+
_createHeaderButton(const ['name'], 'Class',
_SortingField.className, _SortingDirection.ascending)
],
@@ -468,18 +463,18 @@
void _updateCollectionLine(Element e, itemDynamic, index) {
M.ClassHeapStats item = itemDynamic;
- e.children[0].text = Utils.formatSize(_getAccumulatedSize(item));
- e.children[1].text = '${_getAccumulatedInstances(item)}';
- e.children[2].text = Utils.formatSize(_getCurrentSize(item));
- e.children[3].text = '${_getCurrentInstances(item)}';
- e.children[4].text = Utils.formatSize(_getNewAccumulatedSize(item));
- e.children[5].text = '${_getNewAccumulatedInstances(item)}';
- e.children[6].text = Utils.formatSize(_getNewCurrentSize(item));
- e.children[7].text = '${_getNewCurrentInstances(item)}';
- e.children[8].text = Utils.formatSize(_getOldAccumulatedSize(item));
- e.children[9].text = '${_getOldAccumulatedInstances(item)}';
- e.children[10].text = Utils.formatSize(_getOldCurrentSize(item));
- e.children[11].text = '${_getOldCurrentInstances(item)}';
+ e.children[0].text = Utils.formatSize(_getNewInternalSize(item));
+ e.children[1].text = Utils.formatSize(_getNewExternalSize(item));
+ e.children[2].text = Utils.formatSize(_getNewSize(item));
+ e.children[3].text = '${_getNewInstances(item)}';
+ e.children[4].text = Utils.formatSize(_getOldInternalSize(item));
+ e.children[5].text = Utils.formatSize(_getOldExternalSize(item));
+ e.children[6].text = Utils.formatSize(_getOldSize(item));
+ e.children[7].text = '${_getOldInstances(item)}';
+ e.children[8].text = Utils.formatSize(_getInternalSize(item));
+ e.children[9].text = Utils.formatSize(_getExternalSize(item));
+ e.children[10].text = Utils.formatSize(_getSize(item));
+ e.children[11].text = '${_getInstances(item)}';
e.children[12] = new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
.element
..classes = ['name'];
@@ -546,26 +541,6 @@
..classes = ['memberValue']
..text = avgCollectionTime
],
- new DivElement()
- ..classes = ['memberItem']
- ..children = <Element>[
- new DivElement()
- ..classes = ['memberName']
- ..text = 'cumulative collection time',
- new DivElement()
- ..classes = ['memberValue']
- ..text = totalCollectionTime
- ],
- new DivElement()
- ..classes = ['memberItem']
- ..children = <Element>[
- new DivElement()
- ..classes = ['memberName']
- ..text = 'average time between collections',
- new DivElement()
- ..classes = ['memberValue']
- ..text = avgCollectionPeriod
- ]
];
}
@@ -604,18 +579,18 @@
void _downloadCSV() {
assert(_profile != null);
final header = [
- '"Accumulator Size"',
- '"Accumulator Instances"',
- '"Current Size"',
- '"Current Instances"',
- '"(NEW) Accumulator Size"',
- '"(NEW) Accumulator Instances"',
- '"(NEW) Current Size"',
- '"(NEW) Current Instances"',
- '"(OLD) Accumulator Size"',
- '"(OLD) Accumulator Instances"',
- '"(OLD) Current Size"',
- '"(OLD) Current Instances"',
+ '"New Internal"',
+ '"New External"',
+ '"New Size"',
+ '"New Instances"',
+ '"Old Internal"',
+ '"Old External"',
+ '"Old Size"',
+ '"Old Instances"',
+ '"Internal"',
+ '"External"',
+ '"Size"',
+ '"Instances"',
'Class'
].join(',') +
'\n';
@@ -632,42 +607,44 @@
static _csvOut(M.ClassHeapStats s) {
return [
- _getAccumulatedSize(s),
- _getAccumulatedInstances(s),
- _getCurrentSize(s),
- _getCurrentInstances(s),
- _getNewAccumulatedSize(s),
- _getNewAccumulatedInstances(s),
- _getNewCurrentSize(s),
- _getNewCurrentInstances(s),
- _getOldAccumulatedSize(s),
- _getOldAccumulatedInstances(s),
- _getOldCurrentSize(s),
- _getOldCurrentInstances(s),
+ _getNewInternalSize(s),
+ _getNewExternalSize(s),
+ _getNewSize(s),
+ _getNewInstances(s),
+ _getOldInternalSize(s),
+ _getOldExternalSize(s),
+ _getOldSize(s),
+ _getOldInstances(s),
+ _getInternalSize(s),
+ _getExternalSize(s),
+ _getSize(s),
+ _getInstances(s),
s.clazz.name
].join(',');
}
- static int _getAccumulatedSize(M.ClassHeapStats s) =>
- s.newSpace.accumulated.bytes + s.oldSpace.accumulated.bytes;
- static int _getAccumulatedInstances(M.ClassHeapStats s) =>
- s.newSpace.accumulated.instances + s.oldSpace.accumulated.instances;
- static int _getCurrentSize(M.ClassHeapStats s) =>
- s.newSpace.current.bytes + s.oldSpace.current.bytes;
- static int _getCurrentInstances(M.ClassHeapStats s) =>
- s.newSpace.current.instances + s.oldSpace.current.instances;
- static int _getNewAccumulatedSize(M.ClassHeapStats s) =>
- s.newSpace.accumulated.bytes;
- static int _getNewAccumulatedInstances(M.ClassHeapStats s) =>
- s.newSpace.accumulated.instances;
- static int _getNewCurrentSize(M.ClassHeapStats s) => s.newSpace.current.bytes;
- static int _getNewCurrentInstances(M.ClassHeapStats s) =>
- s.newSpace.current.instances;
- static int _getOldAccumulatedSize(M.ClassHeapStats s) =>
- s.oldSpace.accumulated.bytes;
- static int _getOldAccumulatedInstances(M.ClassHeapStats s) =>
- s.oldSpace.accumulated.instances;
- static int _getOldCurrentSize(M.ClassHeapStats s) => s.oldSpace.current.bytes;
- static int _getOldCurrentInstances(M.ClassHeapStats s) =>
- s.oldSpace.current.instances;
+ static int _getNewInstances(M.ClassHeapStats s) =>
+ s.newSpace.instances;
+ static int _getNewInternalSize(M.ClassHeapStats s) =>
+ s.newSpace.internalSize;
+ static int _getNewExternalSize(M.ClassHeapStats s) =>
+ s.newSpace.externalSize;
+ static int _getNewSize(M.ClassHeapStats s) =>
+ s.newSpace.size;
+ static int _getOldInstances(M.ClassHeapStats s) =>
+ s.oldSpace.instances;
+ static int _getOldInternalSize(M.ClassHeapStats s) =>
+ s.oldSpace.internalSize;
+ static int _getOldExternalSize(M.ClassHeapStats s) =>
+ s.oldSpace.externalSize;
+ static int _getOldSize(M.ClassHeapStats s) =>
+ s.oldSpace.size;
+ static int _getInstances(M.ClassHeapStats s) =>
+ s.newSpace.instances + s.oldSpace.instances;
+ static int _getInternalSize(M.ClassHeapStats s) =>
+ s.newSpace.internalSize + s.oldSpace.internalSize;
+ static int _getExternalSize(M.ClassHeapStats s) =>
+ s.newSpace.externalSize + s.oldSpace.externalSize;
+ static int _getSize(M.ClassHeapStats s) =>
+ s.newSpace.size + s.oldSpace.size;
}
diff --git a/runtime/observatory/lib/src/elements/class_instances.dart b/runtime/observatory/lib/src/elements/class_instances.dart
index 792f8e9..b81d859 100644
--- a/runtime/observatory/lib/src/elements/class_instances.dart
+++ b/runtime/observatory/lib/src/elements/class_instances.dart
@@ -87,10 +87,8 @@
new StronglyReachableInstancesElement(
_isolate, _cls, _stronglyReachableInstances, _objects,
queue: _r.queue);
- final instanceCount =
- _cls.newSpace.current.instances + _cls.oldSpace.current.instances;
- final size = Utils.formatSize(
- _cls.newSpace.current.bytes + _cls.oldSpace.current.bytes);
+ final instanceCount = _cls.newSpace.instances + _cls.oldSpace.instances;
+ final size = Utils.formatSize(_cls.newSpace.size + _cls.oldSpace.size);
children = <Element>[
new DivElement()
..classes = ['memberList']
diff --git a/runtime/observatory/lib/src/elements/css/shared.css b/runtime/observatory/lib/src/elements/css/shared.css
index f573064..da445fe 100644
--- a/runtime/observatory/lib/src/elements/css/shared.css
+++ b/runtime/observatory/lib/src/elements/css/shared.css
@@ -399,7 +399,7 @@
.allocation-profile .heap-space {
display: inline-block;
- width: 50%;
+ width: 33%;
}
.allocation-profile .heap-space.right,
@@ -499,33 +499,41 @@
}
.allocation-profile .collection-item :nth-child(2n+2).group,
-.allocation-profile .collection-item :nth-child(4n+3),
-.allocation-profile .collection-item :nth-child(4n+4) {
+.allocation-profile .collection-item :nth-child(8n+1),
+.allocation-profile .collection-item :nth-child(8n+2),
+.allocation-profile .collection-item :nth-child(8n+3),
+.allocation-profile .collection-item :nth-child(8n+4) {
background-color: #EEEEEE;
}
-.allocation-profile .collection-item:hover :nth-child(2n+2).group,
-.allocation-profile .collection-item:hover :nth-child(4n+3),
-.allocation-profile .collection-item:hover :nth-child(4n+4) {
+.allocation-profile .collection-item:hover :nth-child(2n+1).group,
+.allocation-profile .collection-item:hover :nth-child(8n+1),
+.allocation-profile .collection-item:hover :nth-child(8n+2),
+.allocation-profile .collection-item:hover :nth-child(8n+3),
+.allocation-profile .collection-item:hover :nth-child(8n+4) {
background-color: #afd5fd;
}
-.allocation-profile .header .collection-item :nth-child(2n+1).group,
-.allocation-profile .header .collection-item :nth-child(4n+1),
-.allocation-profile .header .collection-item :nth-child(4n+2) {
+.allocation-profile .header .collection-item :nth-child(2n+2).group,
+.allocation-profile .header .collection-item :nth-child(8n+5),
+.allocation-profile .header .collection-item :nth-child(8n+6),
+.allocation-profile .header .collection-item :nth-child(8n+7),
+.allocation-profile .header .collection-item :nth-child(8n+8) {
background-color: #FFFFFF;
}
-.allocation-profile .header .collection-item :nth-child(2n+2).group,
-.allocation-profile .header .collection-item :nth-child(4n+3),
-.allocation-profile .header .collection-item :nth-child(4n+4) {
+.allocation-profile .header .collection-item :nth-child(2n+1).group,
+.allocation-profile .header .collection-item :nth-child(8n+1),
+.allocation-profile .header .collection-item :nth-child(8n+2),
+.allocation-profile .header .collection-item :nth-child(8n+3),
+.allocation-profile .header .collection-item :nth-child(8n+4) {
background-color: #DDDDDD;
}
.allocation-profile .collection-item .group {
display: inline-block;
- width: 12em;
- text-align: right;
+ width: 24em;
+ text-align: center;
padding-right: 0.5em;
line-height: 20px;
border-right: solid 1px #AAAAAA;
diff --git a/runtime/observatory/lib/src/elements/timeline_page.dart b/runtime/observatory/lib/src/elements/timeline_page.dart
index 7e54388..8619098 100644
--- a/runtime/observatory/lib/src/elements/timeline_page.dart
+++ b/runtime/observatory/lib/src/elements/timeline_page.dart
@@ -65,7 +65,7 @@
attached() {
super.attached();
_r.enable();
- _setupInitialState();
+ _updateRecorderUI();
}
@override
@@ -84,6 +84,9 @@
void render() {
if (_frame == null) {
_frame = new IFrameElement()..src = 'timeline.html';
+ _frame.onLoad.listen((event) {
+ _refresh();
+ });
}
if (_content == null) {
_content = new DivElement()..classes = ['content-centered-big'];
@@ -187,8 +190,7 @@
"This VM is forwarding timeline events to Fuchsia's system tracing. See the ",
new AnchorElement()
..text = "Fuchsia Tracing Usage Guide"
- ..href =
- "https://fuchsia.googlesource.com/garnet/+/master/docs/tracing_usage_guide.md",
+ ..href = "https://fuchsia.dev/fuchsia-src/development/tracing",
new SpanElement()..text = ".",
];
}
@@ -232,6 +234,7 @@
}
Future _refresh() async {
+ _postMessage('loading');
final traceData = await _repository.getTimeline(vm);
return _postMessage('refresh', traceData);
}
@@ -260,11 +263,6 @@
return null;
}
- Future _setupInitialState() async {
- await _updateRecorderUI();
- await _refresh();
- }
-
void _applyPreset(M.TimelineProfile profile) {
_recordedStreams = new Set<M.TimelineStream>.from(profile.streams);
_applyStreamChanges();
diff --git a/runtime/observatory/lib/src/models/objects/allocation_profile.dart b/runtime/observatory/lib/src/models/objects/allocation_profile.dart
index 4f113a6..f9aa5a6 100644
--- a/runtime/observatory/lib/src/models/objects/allocation_profile.dart
+++ b/runtime/observatory/lib/src/models/objects/allocation_profile.dart
@@ -9,6 +9,7 @@
DateTime get lastAccumulatorReset;
HeapSpace get newSpace;
HeapSpace get oldSpace;
+ HeapSpace get totalSpace;
Iterable<ClassHeapStats> get members;
}
@@ -20,16 +21,11 @@
String get displayName;
Allocations get newSpace;
Allocations get oldSpace;
- int get promotedInstances;
- int get promotedBytes;
}
abstract class Allocations {
- AllocationCount get accumulated;
- AllocationCount get current;
-}
-
-abstract class AllocationCount {
- int get instances;
- int get bytes;
+ int instances = 0;
+ int internalSize = 0;
+ int externalSize = 0;
+ int size = 0;
}
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 754075c..86f8cc7 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1268,6 +1268,20 @@
totalCollectionTimeInSeconds = heapMap['time'];
averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis'];
}
+
+ void add(HeapSpace other) {
+ used += other.used;
+ capacity += other.capacity;
+ external += other.external;
+ collections += other.collections;
+ totalCollectionTimeInSeconds += other.totalCollectionTimeInSeconds;
+ if (collections == 0) {
+ averageCollectionPeriodInMillis = 0.0;
+ } else {
+ averageCollectionPeriodInMillis =
+ (totalCollectionTimeInSeconds / collections) * 1000.0;
+ }
+ }
}
class IsolateGroup extends ServiceObjectOwner implements M.IsolateGroup {
@@ -2519,50 +2533,30 @@
String toString() => "Library($uri)";
}
-class AllocationCount implements M.AllocationCount {
- int instances = 0;
- int bytes = 0;
-
- void reset() {
- instances = 0;
- bytes = 0;
- }
-
- bool get empty => (instances == 0) && (bytes == 0);
- bool get notEmpty => (instances != 0) || (bytes != 0);
-}
-
class Allocations implements M.Allocations {
// Indexes into VM provided array. (see vm/class_table.h).
- static const ALLOCATED_BEFORE_GC = 0;
- static const ALLOCATED_BEFORE_GC_SIZE = 1;
- static const LIVE_AFTER_GC = 2;
- static const LIVE_AFTER_GC_SIZE = 3;
- static const ALLOCATED_SINCE_GC = 4;
- static const ALLOCATED_SINCE_GC_SIZE = 5;
- static const ACCUMULATED = 6;
- static const ACCUMULATED_SIZE = 7;
- final AllocationCount accumulated = new AllocationCount();
- final AllocationCount current = new AllocationCount();
+ int instances = 0;
+ int internalSize = 0;
+ int externalSize = 0;
+ int size = 0;
void update(List stats) {
- accumulated.instances = stats[ACCUMULATED];
- accumulated.bytes = stats[ACCUMULATED_SIZE];
- current.instances = stats[LIVE_AFTER_GC] + stats[ALLOCATED_SINCE_GC];
- current.bytes = stats[LIVE_AFTER_GC_SIZE] + stats[ALLOCATED_SINCE_GC_SIZE];
+ instances = stats[0];
+ internalSize = stats[1];
+ externalSize = stats[2];
+ size = internalSize + externalSize;
}
void combine(Iterable<Allocations> allocations) {
- accumulated.instances =
- allocations.fold(0, (v, a) => v + a.accumulated.instances);
- accumulated.bytes = allocations.fold(0, (v, a) => v + a.accumulated.bytes);
- current.instances = allocations.fold(0, (v, a) => v + a.current.instances);
- current.bytes = allocations.fold(0, (v, a) => v + a.current.bytes);
+ instances = allocations.fold(0, (v, a) => v + a.instances);
+ internalSize = allocations.fold(0, (v, a) => v + a.internalSize);
+ externalSize = allocations.fold(0, (v, a) => v + a.externalSize);
+ size = allocations.fold(0, (v, a) => v + a.size);
}
- bool get empty => accumulated.empty && current.empty;
- bool get notEmpty => accumulated.notEmpty || current.notEmpty;
+ bool get empty => size == 0;
+ bool get notEmpty => size != 0;
}
class Class extends HeapObject implements M.Class {
@@ -2580,7 +2574,6 @@
final Allocations newSpace = new Allocations();
final Allocations oldSpace = new Allocations();
- final AllocationCount promotedByLastNewGC = new AllocationCount();
bool get hasAllocations => newSpace.notEmpty || oldSpace.notEmpty;
bool get hasNoAllocations => newSpace.empty && oldSpace.empty;
@@ -2663,14 +2656,6 @@
traceAllocations =
(map['_traceAllocations'] != null) ? map['_traceAllocations'] : false;
-
- var allocationStats = map['_allocationStats'];
- if (allocationStats != null) {
- newSpace.update(allocationStats['_new']);
- oldSpace.update(allocationStats['_old']);
- promotedByLastNewGC.instances = allocationStats['promotedInstances'];
- promotedByLastNewGC.bytes = allocationStats['promotedBytes'];
- }
}
void _addSubclass(Class subclass) {
diff --git a/runtime/observatory/tests/service/allocations_test.dart b/runtime/observatory/tests/service/allocations_test.dart
index e21ec15..4b0f23b 100644
--- a/runtime/observatory/tests/service/allocations_test.dart
+++ b/runtime/observatory/tests/service/allocations_test.dart
@@ -18,15 +18,12 @@
var tests = <IsolateTest>[
(Isolate isolate) async {
- Library lib = await isolate.rootLibrary.load();
- expect(lib.uri.endsWith('allocations_test.dart'), isTrue);
- expect(lib.classes.length, equals(1));
- Class fooClass = await lib.classes.first.load();
- expect(fooClass.name, equals('Foo'));
- expect(
- fooClass.newSpace.current.instances +
- fooClass.oldSpace.current.instances,
- equals(3));
+ var profile = await isolate.invokeRpcNoUpgrade('_getAllocationProfile', {});
+ var classHeapStats = profile['members'].singleWhere((stats) {
+ return stats['class']['name'] == 'Foo';
+ });
+ expect(classHeapStats['instancesCurrent'], equals(3));
+ expect(classHeapStats['instancesAccumulated'], equals(3));
},
];
diff --git a/runtime/observatory/tests/service/causal_async_stack_contents_test.dart b/runtime/observatory/tests/service/causal_async_stack_contents_test.dart
index 209c2f6b..c21879b 100644
--- a/runtime/observatory/tests/service/causal_async_stack_contents_test.dart
+++ b/runtime/observatory/tests/service/causal_async_stack_contents_test.dart
@@ -11,8 +11,8 @@
import 'test_helper.dart';
const LINE_C = 19;
-const LINE_A = 24;
-const LINE_B = 30;
+const LINE_A = 25;
+const LINE_B = 31;
foobar() {
debugger();
@@ -20,6 +20,7 @@
}
helper() async {
+ await 0; // force async gap
debugger();
print('helper'); // LINE_A.
foobar();
@@ -64,10 +65,10 @@
expect(asyncStack[3].toString(), contains('testMain'));
// Line 19.
expect(await asyncStack[0].location.toUserString(), contains('.dart:19'));
- // Line 25.
- expect(await asyncStack[1].location.toUserString(), contains('.dart:25'));
- // Line 30.
- expect(await asyncStack[3].location.toUserString(), contains('.dart:30'));
+ // Line 26.
+ expect(await asyncStack[1].location.toUserString(), contains('.dart:26'));
+ // Line 31.
+ expect(await asyncStack[3].location.toUserString(), contains('.dart:31'));
},
];
diff --git a/runtime/observatory/tests/service/causal_async_star_stack_contents_test.dart b/runtime/observatory/tests/service/causal_async_star_stack_contents_test.dart
index 3525105..80eb931 100644
--- a/runtime/observatory/tests/service/causal_async_star_stack_contents_test.dart
+++ b/runtime/observatory/tests/service/causal_async_star_stack_contents_test.dart
@@ -10,11 +10,12 @@
import 'service_test_common.dart';
import 'test_helper.dart';
-const LINE_A = 26;
-const LINE_B = 19;
-const LINE_C = 21;
+const LINE_A = 28;
+const LINE_B = 20;
+const LINE_C = 22;
foobar() async* {
+ await 0; // force async gap
debugger();
yield 1; // LINE_B.
debugger();
@@ -22,6 +23,7 @@
}
helper() async {
+ await 0; // force async gap
debugger();
print('helper'); // LINE_A.
await for (var i in foobar()) {
@@ -76,12 +78,13 @@
expect(asyncStack[2].toString(), contains('helper'));
expect(asyncStack[3].kind, equals(M.FrameKind.asyncSuspensionMarker));
expect(asyncStack[4].toString(), contains('testMain'));
- // Line 21.
- expect(await asyncStack[0].location.toUserString(), contains('.dart:21'));
- // Line 27.
- expect(await asyncStack[2].location.toUserString(), contains('.dart:27'));
- // Line 30.
- expect(await asyncStack[4].location.toUserString(), contains('.dart:33'));
+ // Line 22.
+ expect(
+ await asyncStack[0].location.toUserString(), contains('.dart:$LINE_C'));
+ // Line 29.
+ expect(await asyncStack[2].location.toUserString(), contains('.dart:29'));
+ // Line 35.
+ expect(await asyncStack[4].location.toUserString(), contains('.dart:35'));
},
];
diff --git a/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart b/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart
index a03cbfc..8d5c88e 100644
--- a/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_allocation_profile_rpc_test.dart
@@ -32,8 +32,6 @@
expect(member['type'], equals('ClassHeapStats'));
expect(member.containsKey('_new'), isTrue);
expect(member.containsKey('_old'), isTrue);
- expect(member.containsKey('_promotedInstances'), isTrue);
- expect(member.containsKey('_promotedBytes'), isTrue);
expect(member.containsKey('instancesAccumulated'), isTrue);
expect(member.containsKey('instancesCurrent'), isTrue);
expect(member.containsKey('bytesCurrent'), isTrue);
@@ -57,8 +55,6 @@
expect(member['type'], equals('ClassHeapStats'));
expect(member.containsKey('_new'), isTrue);
expect(member.containsKey('_old'), isTrue);
- expect(member.containsKey('_promotedInstances'), isTrue);
- expect(member.containsKey('_promotedBytes'), isTrue);
expect(member.containsKey('instancesAccumulated'), isTrue);
expect(member.containsKey('instancesCurrent'), isTrue);
expect(member.containsKey('bytesCurrent'), isTrue);
@@ -88,8 +84,6 @@
expect(member['type'], equals('ClassHeapStats'));
expect(member.containsKey('_new'), isTrue);
expect(member.containsKey('_old'), isTrue);
- expect(member.containsKey('_promotedInstances'), isTrue);
- expect(member.containsKey('_promotedBytes'), isTrue);
expect(member.containsKey('instancesAccumulated'), isTrue);
expect(member.containsKey('instancesCurrent'), isTrue);
expect(member.containsKey('bytesCurrent'), isTrue);
diff --git a/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart b/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart
index 89ebcbf..90cbea3b 100644
--- a/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart
+++ b/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart
@@ -10,7 +10,7 @@
import 'test_helper.dart';
import 'service_test_common.dart';
-const LINE_A = 34;
+const LINE_A = 35;
class Foo {}
@@ -20,6 +20,7 @@
}
asyncThrower() async {
+ await 0; // force async gap
doThrow();
}
diff --git a/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions_test.dart b/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions_test.dart
index b832931..8f955f3 100644
--- a/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions_test.dart
+++ b/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions_test.dart
@@ -9,7 +9,7 @@
import 'test_helper.dart';
import 'service_test_common.dart';
-const LINE_A = 34;
+const LINE_A = 35;
class Foo {}
@@ -19,6 +19,7 @@
}
asyncThrower() async {
+ await 0; // force async gap
doThrow();
}
diff --git a/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart b/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
index c36f561..5c4a65a 100644
--- a/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
+++ b/runtime/observatory/tests/service/step_through_mixin_from_sdk_test.dart
@@ -35,19 +35,19 @@
List<String> expected = [
"$file:${LINE + 0}:17", // on "Foo" (in "new Foo()")
"$file:${LINE + 1}:11", // on "="
- "list.dart:105:24", // on parameter to "contains"
- "list.dart:106:23", // on "length" in "this.length"
- "list.dart:107:16", // on "=" in "i = 0"
- "list.dart:107:23", // on "<" in "i < length"
- "list.dart:108:15", // on "[" in "this[i]"
+ "list.dart:107:24", // on parameter to "contains"
+ "list.dart:108:23", // on "length" in "this.length"
+ "list.dart:109:16", // on "=" in "i = 0"
+ "list.dart:109:23", // on "<" in "i < length"
+ "list.dart:110:15", // on "[" in "this[i]"
"$file:${LINE + 13}:23", // on parameter in "operator []"
"$file:${LINE + 14}:5", // on "return"
- "list.dart:108:19", // on "=="
- "list.dart:109:26", // on "length" in "this.length"
- "list.dart:109:18", // on "!="
- "list.dart:107:34", // on "++" in "i++"
- "list.dart:107:23", // on "<" in "i < length"
- "list.dart:113:5", // on "return"
+ "list.dart:110:19", // on "=="
+ "list.dart:111:26", // on "length" in "this.length"
+ "list.dart:111:18", // on "!="
+ "list.dart:109:34", // on "++" in "i++"
+ "list.dart:109:23", // on "<" in "i < length"
+ "list.dart:115:5", // on "return"
"$file:${LINE + 4}:5", // on "print"
"$file:${LINE + 6}:1" // on ending '}'
];
diff --git a/runtime/observatory/tests/service/verify_http_timeline_test.dart b/runtime/observatory/tests/service/verify_http_timeline_test.dart
new file mode 100644
index 0000000..9b41df0
--- /dev/null
+++ b/runtime/observatory/tests/service/verify_http_timeline_test.dart
@@ -0,0 +1,288 @@
+// Copyright (c) 2019, 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.
+// VMOptions=--timeline_streams=Dart
+
+import 'dart:async';
+import 'dart:developer';
+import 'dart:io';
+import 'dart:math';
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+
+import 'test_helper.dart';
+
+final rng = Random();
+
+// Enable to test redirects.
+const shouldTestRedirects = false;
+
+const maxRequestDelayMs = 3000;
+const maxResponseDelayMs = 500;
+const serverShutdownDelayMs = 2000;
+
+void randomlyAddCookie(HttpResponse response) {
+ if (rng.nextInt(3) == 0) {
+ response.cookies.add(Cookie('Cookie-Monster', 'Me-want-cookie!'));
+ }
+}
+
+Future<bool> randomlyRedirect(HttpServer server, HttpResponse response) async {
+ if (shouldTestRedirects && rng.nextInt(5) == 0) {
+ final redirectUri = Uri(host: 'www.google.com', port: 80);
+ response.redirect(redirectUri);
+ return true;
+ }
+ return false;
+}
+
+// Execute HTTP requests with random delays so requests have some overlap. This
+// way we can be certain that timeline events are matching up properly even when
+// connections are interrupted or can't be established.
+Future<void> executeWithRandomDelay(Function f) =>
+ Future<void>.delayed(Duration(milliseconds: rng.nextInt(maxRequestDelayMs)))
+ .then((_) async {
+ try {
+ await f();
+ } on HttpException catch (_) {} on SocketException catch (_) {} on StateError catch (_) {}
+ });
+
+Uri randomlyAddRequestParams(Uri uri) {
+ const possiblePathSegments = <String>['foo', 'bar', 'baz', 'foobar'];
+ final segmentSubset =
+ possiblePathSegments.sublist(0, rng.nextInt(possiblePathSegments.length));
+ uri = uri.replace(pathSegments: segmentSubset);
+ if (rng.nextInt(3) == 0) {
+ uri = uri.replace(queryParameters: {
+ 'foo': 'bar',
+ 'year': '2019',
+ });
+ }
+ return uri;
+}
+
+Future<HttpServer> startServer() async {
+ final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 8011);
+ server.listen((request) async {
+ final response = request.response;
+ randomlyAddCookie(response);
+ if (await randomlyRedirect(server, response)) {
+ // Redirect calls close() on the response.
+ return;
+ }
+ // Randomly delay response.
+ await Future.delayed(
+ Duration(milliseconds: rng.nextInt(maxResponseDelayMs)));
+ response.close();
+ });
+ return server;
+}
+
+Future<void> testMain() async {
+ // Ensure there's a chance some requests will be interrupted.
+ expect(maxRequestDelayMs > serverShutdownDelayMs, isTrue);
+ expect(maxResponseDelayMs < serverShutdownDelayMs, isTrue);
+
+ final server = await startServer();
+ HttpClient.enableTimelineLogging = true;
+ final client = HttpClient();
+ final requests = <Future>[];
+ final address =
+ Uri(scheme: 'http', host: server.address.host, port: server.port);
+
+ // HTTP DELETE
+ for (int i = 0; i < 10; ++i) {
+ final future = executeWithRandomDelay(() async {
+ final r = await client.deleteUrl(randomlyAddRequestParams(address));
+ await r.close();
+ });
+ requests.add(future);
+ }
+
+ // HTTP GET
+ for (int i = 0; i < 10; ++i) {
+ final future = executeWithRandomDelay(() async {
+ final r = await client.getUrl(randomlyAddRequestParams(address));
+ await r.close();
+ });
+ requests.add(future);
+ }
+
+ // HTTP HEAD
+ for (int i = 0; i < 10; ++i) {
+ final future = executeWithRandomDelay(() async {
+ final r = await client.headUrl(randomlyAddRequestParams(address));
+ await r.close();
+ });
+ requests.add(future);
+ }
+
+ // HTTP CONNECT
+ for (int i = 0; i < 10; ++i) {
+ final future = executeWithRandomDelay(() async {
+ final r =
+ await client.openUrl('connect', randomlyAddRequestParams(address));
+ await r.close();
+ });
+ requests.add(future);
+ }
+
+ // HTTP PATCH
+ for (int i = 0; i < 10; ++i) {
+ final future = executeWithRandomDelay(() async {
+ final r = await client.patchUrl(randomlyAddRequestParams(address));
+ await r.close();
+ });
+ requests.add(future);
+ }
+
+ // HTTP POST
+ for (int i = 0; i < 10; ++i) {
+ final future = executeWithRandomDelay(() async {
+ final r = await client.postUrl(randomlyAddRequestParams(address));
+ await r.close();
+ });
+ requests.add(future);
+ }
+
+ // HTTP PUT
+ for (int i = 0; i < 10; ++i) {
+ final future = executeWithRandomDelay(() async {
+ final r = await client.putUrl(randomlyAddRequestParams(address));
+ await r.close();
+ });
+ requests.add(future);
+ }
+
+ // Purposefully close server before some connections can be made to ensure
+ // that refused / interrupted connections correctly create finish timeline
+ // events.
+ await Future.delayed(Duration(milliseconds: serverShutdownDelayMs));
+ await server.close();
+
+ // Ensure all requests complete before finishing.
+ await Future.wait(requests);
+}
+
+bool isStartEvent(Map event) => (event['ph'] == 'b');
+bool isFinishEvent(Map event) => (event['ph'] == 'e');
+
+bool hasCompletedEvents(List traceEvents) {
+ final events = <String, int>{};
+ for (final event in traceEvents) {
+ if (isStartEvent(event)) {
+ final id = event['id'];
+ events.putIfAbsent(id, () => 0);
+ events[id]++;
+ } else if (isFinishEvent(event)) {
+ final id = event['id'];
+ events[id]--;
+ }
+ }
+ bool valid = true;
+ events.forEach((id, count) {
+ if (count != 0) {
+ valid = false;
+ }
+ });
+ return valid;
+}
+
+List filterEventsByName(List traceEvents, String name) =>
+ traceEvents.where((e) => e['name'].contains(name)).toList();
+
+void hasValidHttpConnections(List traceEvents) {
+ final events = filterEventsByName(traceEvents, 'HTTP Connection');
+ expect(hasCompletedEvents(events), isTrue);
+}
+
+void validateHttpStartEvent(Map event, String method) {
+ expect(event.containsKey('args'), isTrue);
+ final args = event['args'];
+ expect(args.containsKey('method'), isTrue);
+ expect(args['method'], method);
+ if (!args.containsKey('error')) {
+ expect(args.containsKey('requestHeaders'), isTrue);
+ expect(args['requestHeaders'] != null, isTrue);
+ expect(args.containsKey('compressionState'), isTrue);
+ expect(args.containsKey('connectionInfo'), isTrue);
+ expect(args.containsKey('contentLength'), isTrue);
+ expect(args.containsKey('cookies'), isTrue);
+ expect(args.containsKey('responseHeaders'), isTrue);
+ expect(args.containsKey('isRedirect'), isTrue);
+ expect(args.containsKey('persistentConnection'), isTrue);
+ expect(args.containsKey('reasonPhrase'), isTrue);
+ expect(args.containsKey('redirects'), isTrue);
+ expect(args.containsKey('statusCode'), isTrue);
+ // If proxyInfo is non-null, uri and port _must_ be non-null.
+ if (args.containsKey('proxyInfo')) {
+ final proxyInfo = args['proxyInfo'];
+ expect(proxyInfo.containsKey('uri'), isTrue);
+ expect(proxyInfo.containsKey('port'), isTrue);
+ }
+ }
+}
+
+void validateHttpFinishEvent(Map event) {
+ expect(event.containsKey('args'), isTrue);
+ final args = event['args'];
+ expect(args.containsKey('compressionState'), isTrue);
+ expect(args.containsKey('connectionInfo'), isTrue);
+ expect(args.containsKey('contentLength'), isTrue);
+ expect(args.containsKey('cookies'), isTrue);
+ expect(args.containsKey('responseHeaders'), isTrue);
+ expect(args.containsKey('isRedirect'), isTrue);
+ expect(args.containsKey('persistentConnection'), isTrue);
+ expect(args.containsKey('reasonPhrase'), isTrue);
+ expect(args.containsKey('redirects'), isTrue);
+ expect(args.containsKey('statusCode'), isTrue);
+}
+
+void hasValidHttpRequests(List traceEvents, String method) {
+ final events = filterEventsByName(traceEvents, 'HTTP Client $method');
+ expect(hasCompletedEvents(events), isTrue);
+ for (final event in events) {
+ if (isStartEvent(event)) {
+ validateHttpStartEvent(event, method);
+ } else if (isFinishEvent(event)) {
+ validateHttpFinishEvent(event);
+ } else {
+ fail('unexpected event type: ${event["ph"]}');
+ }
+ }
+}
+
+void hasValidHttpCONNECTs(List traceEvents) =>
+ hasValidHttpRequests(traceEvents, 'CONNECT');
+void hasValidHttpDELETEs(List traceEvents) =>
+ hasValidHttpRequests(traceEvents, 'DELETE');
+void hasValidHttpGETs(List traceEvents) =>
+ hasValidHttpRequests(traceEvents, 'GET');
+void hasValidHttpHEADs(List traceEvents) =>
+ hasValidHttpRequests(traceEvents, 'HEAD');
+void hasValidHttpPATCHs(List traceEvents) =>
+ hasValidHttpRequests(traceEvents, 'PATCH');
+void hasValidHttpPOSTs(List traceEvents) =>
+ hasValidHttpRequests(traceEvents, 'POST');
+void hasValidHttpPUTs(List traceEvents) =>
+ hasValidHttpRequests(traceEvents, 'PUT');
+
+var tests = <IsolateTest>[
+ (Isolate isolate) async {
+ final result = await isolate.vm.invokeRpcNoUpgrade('getVMTimeline', {});
+ expect(result['type'], 'Timeline');
+ expect(result.containsKey('traceEvents'), isTrue);
+ final traceEvents = result['traceEvents'];
+ expect(traceEvents.length > 0, isTrue);
+ hasValidHttpConnections(traceEvents);
+ hasValidHttpCONNECTs(traceEvents);
+ hasValidHttpDELETEs(traceEvents);
+ hasValidHttpGETs(traceEvents);
+ hasValidHttpHEADs(traceEvents);
+ hasValidHttpPATCHs(traceEvents);
+ hasValidHttpPOSTs(traceEvents);
+ hasValidHttpPUTs(traceEvents);
+ },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore: testMain);
diff --git a/runtime/observatory/web/timeline_message_handler.js b/runtime/observatory/web/timeline_message_handler.js
index 04925ec..4b3f11a 100644
--- a/runtime/observatory/web/timeline_message_handler.js
+++ b/runtime/observatory/web/timeline_message_handler.js
@@ -20,6 +20,9 @@
var params = request['params'];
console.log('method: ' + method)
switch (method) {
+ case 'loading':
+ showLoadingOverlay('Fetching timeline...');
+ break;
case 'refresh':
traceObject = params;
if (typeof populateTimeline != 'undefined') {
diff --git a/runtime/tests/vm/dart/causal_stacks/sync_async_start_pkg_test_test.dart b/runtime/tests/vm/dart/causal_stacks/sync_async_start_pkg_test_test.dart
new file mode 100644
index 0000000..e2bcd2f
--- /dev/null
+++ b/runtime/tests/vm/dart/causal_stacks/sync_async_start_pkg_test_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+//
+// This test ensures that "pkg:stack_trace" (used by "pkg:test") doesn't break
+// when causal async stacks are enabled by dropping frames below a synchronous
+// start to an async function.
+
+import "package:test/test.dart";
+import "package:stack_trace/src/stack_zone_specification.dart";
+
+import 'dart:async';
+
+void main() {
+ test("Stacktrace includes sync-starts.", () async {
+ final st = await firstMethod();
+ expect("$st", allOf([contains("firstMethod"), contains("secondMethod")]));
+ });
+}
+
+Future<StackTrace> firstMethod() async {
+ return await secondMethod();
+}
+
+Future<StackTrace> secondMethod() async {
+ return StackTrace.current;
+}
diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart
index 6038e33..ce5116b 100644
--- a/runtime/tests/vm/dart/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart/causal_stacks/utils.dart
@@ -124,11 +124,8 @@
Map<int, String> noYieldsMapCausal = {
0: '#0 throwSync ',
1: '#1 noYields3 ',
- 2: '<asynchronous suspension>',
- 3: '#2 noYields2 ',
- 4: '<asynchronous suspension>',
- 5: '#3 noYields ',
- 4: '<asynchronous suspension>',
+ 2: '#2 noYields2 ',
+ 3: '#3 noYields ',
// Callers, like doTest and main ..
};
@@ -168,11 +165,9 @@
0: '#0 throwAsync ',
1: '<asynchronous suspension>',
2: '#1 mixedYields3 ',
- 3: '<asynchronous suspension>',
- 4: '#2 mixedYields2 ',
- 5: '<asynchronous suspension>',
- 6: '#3 mixedYields ',
- 7: '<asynchronous suspension>',
+ 3: '#2 mixedYields2 ',
+ 4: '<asynchronous suspension>',
+ 5: '#3 mixedYields ',
// Callers, like doTest and main ..
};
@@ -207,7 +202,6 @@
3: '#2 syncSuffix2 ',
4: '<asynchronous suspension>',
5: '#3 syncSuffix ',
- 6: '<asynchronous suspension>',
// Callers, like doTest and main ..
};
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 9cd25d6..1801067 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -175,6 +175,9 @@
dart/data_uri_spawn_test: Skip # Please triage.
dart/snapshot_version_test: RuntimeError # Please triage.
+[ $hot_reload || $hot_reload_rollback ]
+dart/isolates/spawn_function_test: Skip # This test explicitly enables isolate groups (off-by-default atm). It will be enabled once full IG reloading is implemented.
+
[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
dart/data_uri_spawn_test: Skip # Timeout
dart/kernel_determinism_test: SkipSlow
diff --git a/runtime/tools/dartfuzz/dartfuzz.dart b/runtime/tools/dartfuzz/dartfuzz.dart
index d47151e..82d0316 100644
--- a/runtime/tools/dartfuzz/dartfuzz.dart
+++ b/runtime/tools/dartfuzz/dartfuzz.dart
@@ -14,7 +14,7 @@
// Version of DartFuzz. Increase this each time changes are made
// to preserve the property that a given version of DartFuzz yields
// the same fuzzed program for a deterministic random seed.
-const String version = '1.65';
+const String version = '1.71';
// Restriction on statements and expressions.
const int stmtDepth = 1;
@@ -27,6 +27,7 @@
const int numMethodParams = 4;
const int numClasses = 4;
const int numExtensionMethodsPerClass = 3;
+const int numDartTypeExtensions = 5;
// Naming conventions.
const varName = 'var';
@@ -69,16 +70,15 @@
fuzzer.emitNewline();
}
- void emitCall(int depth,
- {RhsFilter rhsFilter,
- bool includeSemicolon = false,
- bool extensionApplication = false}) {
+ String emitCall(int depth,
+ {RhsFilter rhsFilter, bool includeSemicolon = false}) {
String outputName = name;
fuzzer.emitLn(outputName, newline: false);
fuzzer.emitExprList(depth + 1, parameters, rhsFilter: rhsFilter);
if (includeSemicolon) {
fuzzer.emit(';');
}
+ return outputName;
}
// Main emitter for a method.
@@ -134,10 +134,8 @@
: super(name, parameters, fuzzer) {}
@override
- void emitCall(int depth,
- {RhsFilter rhsFilter,
- bool includeSemicolon = false,
- bool extensionApplication = false}) {
+ String emitCall(int depth,
+ {RhsFilter rhsFilter, bool includeSemicolon = false}) {
String outputName = name;
if (fuzzer.currentClass == null) {
// If we're calling an instance method from outside the class, then we
@@ -149,6 +147,7 @@
if (includeSemicolon) {
fuzzer.emit(';');
}
+ return outputName;
}
final String className;
@@ -157,23 +156,26 @@
// Class for extension methods generated by DartFuzz.
class ExtensionMethod extends Method {
ExtensionMethod(String name, List<DartType> parameters, DartFuzz fuzzer,
- this.className, this.extensionName)
+ this.className, this.extensionName, this.type)
: super(name, parameters, fuzzer) {}
-
@override
- void emitCall(int depth,
- {RhsFilter rhsFilter,
- bool includeSemicolon = false,
- bool extensionApplication = false}) {
+ String emitCall(int depth,
+ {RhsFilter rhsFilter, bool includeSemicolon = false}) {
String outputName = name;
- if (fuzzer.currentClass == null) {
- // If we're calling an extension method from outside the class, we can
- // call it using an object of the class or using explicit extension
- // application.
- if (extensionApplication) {
- outputName = "${extensionName}(${className}()).${name}";
+
+ // If we're calling an extension method on a class from outside the class,
+ // we must call it using an object of the class or using explicit extension
+ // application. Extension methods on Dart types are presently always called
+ // using a variable of the Dart type or using explicit extension
+ // application.
+ if (fuzzer.currentClass == null || type != null) {
+ String invokingObject =
+ type != null ? fuzzer.pickScalarVar(type) : "${className}()";
+
+ if (extensionName != null && fuzzer.coinFlip()) {
+ outputName = "${extensionName}(${invokingObject}).${name}";
} else {
- outputName = "${className}().${name}";
+ outputName = "${invokingObject}.${name}";
}
}
fuzzer.emitLn(outputName, newline: false);
@@ -181,10 +183,12 @@
if (includeSemicolon) {
fuzzer.emit(';');
}
+ return outputName;
}
final String className;
final String extensionName;
+ final DartType type;
}
// Class that tracks the state of the filter applied to the
@@ -213,54 +217,52 @@
/// Class that specifies the api for calling library and ffi functions (if
/// enabled).
class DartApi {
- DartApi(bool ffi)
- : intLibs = [
- if (ffi) ...const [
- DartLib('intComputation', 'VIIII'),
- DartLib('takeMaxUint16', 'VI'),
- DartLib('sumPlus42', 'VII'),
- DartLib('returnMaxUint8', 'VV'),
- DartLib('returnMaxUint16', 'VV'),
- DartLib('returnMaxUint32', 'VV'),
- DartLib('returnMinInt8', 'VV'),
- DartLib('returnMinInt16', 'VV'),
- DartLib('returnMinInt32', 'VV'),
- DartLib('takeMinInt16', 'VI'),
- DartLib('takeMinInt32', 'VI'),
- DartLib('uintComputation', 'VIIII'),
- DartLib('sumSmallNumbers', 'VIIIIII'),
- DartLib('takeMinInt8', 'VI'),
- DartLib('takeMaxUint32', 'VI'),
- DartLib('takeMaxUint8', 'VI'),
- DartLib('minInt64', 'VV'),
- DartLib('minInt32', 'VV'),
- // Use small int to avoid overflow divergences due to size
- // differences in intptr_t on 32-bit and 64-bit platforms.
- DartLib('sumManyIntsOdd', 'Viiiiiiiiiii'),
- DartLib('sumManyInts', 'Viiiiiiiiii'),
- DartLib('regress37069', 'Viiiiiiiiiii'),
- ],
- ...DartLib.intLibs,
+ DartApi(bool ffi) : typeToLibraryMethods = DartLib.typeToLibraryMethods {
+ if (ffi) {
+ typeToLibraryMethods[DartType.INT] = [
+ ...const [
+ DartLib('intComputation', 'VIIII'),
+ DartLib('takeMaxUint16', 'VI'),
+ DartLib('sumPlus42', 'VII'),
+ DartLib('returnMaxUint8', 'VV'),
+ DartLib('returnMaxUint16', 'VV'),
+ DartLib('returnMaxUint32', 'VV'),
+ DartLib('returnMinInt8', 'VV'),
+ DartLib('returnMinInt16', 'VV'),
+ DartLib('returnMinInt32', 'VV'),
+ DartLib('takeMinInt16', 'VI'),
+ DartLib('takeMinInt32', 'VI'),
+ DartLib('uintComputation', 'VIIII'),
+ DartLib('sumSmallNumbers', 'VIIIIII'),
+ DartLib('takeMinInt8', 'VI'),
+ DartLib('takeMaxUint32', 'VI'),
+ DartLib('takeMaxUint8', 'VI'),
+ DartLib('minInt64', 'VV'),
+ DartLib('minInt32', 'VV'),
+ // Use small int to avoid overflow divergences due to size
+ // differences in intptr_t on 32-bit and 64-bit platforms.
+ DartLib('sumManyIntsOdd', 'Viiiiiiiiiii'),
+ DartLib('sumManyInts', 'Viiiiiiiiii'),
+ DartLib('regress37069', 'Viiiiiiiiiii'),
],
- doubleLibs = [
- if (ffi) ...const [
- DartLib('times1_337Float', 'VD'),
- DartLib('sumManyDoubles', 'VDDDDDDDDDD'),
- DartLib('times1_337Double', 'VD'),
- DartLib('sumManyNumbers', 'VIDIDIDIDIDIDIDIDIDID'),
- DartLib('inventFloatValue', 'VV'),
- DartLib('smallDouble', 'VV'),
- ],
- ...DartLib.doubleLibs,
- ];
+ ...DartLib.intLibs,
+ ];
- final boolLibs = DartLib.boolLibs;
- final stringLibs = DartLib.stringLibs;
- final listLibs = DartLib.listLibs;
- final setLibs = DartLib.setLibs;
- final mapLibs = DartLib.mapLibs;
- final List<DartLib> intLibs;
- final List<DartLib> doubleLibs;
+ typeToLibraryMethods[DartType.DOUBLE] = [
+ if (ffi) ...const [
+ DartLib('times1_337Float', 'VD'),
+ DartLib('sumManyDoubles', 'VDDDDDDDDDD'),
+ DartLib('times1_337Double', 'VD'),
+ DartLib('sumManyNumbers', 'VIDIDIDIDIDIDIDIDIDID'),
+ DartLib('inventFloatValue', 'VV'),
+ DartLib('smallDouble', 'VV'),
+ ],
+ ...DartLib.doubleLibs,
+ ];
+ }
+ }
+
+ final typeToLibraryMethods;
}
/// Class that generates a random, but runnable Dart program for fuzz testing.
@@ -305,6 +307,12 @@
emitHeader();
emitVariableDeclarations(varName, globalVars);
emitMethods(globalMethods);
+ for (int i = 0; i < numDartTypeExtensions; ++i) {
+ DartType type = oneOfSet(dartType.allTypes);
+ emitAndAddExtensionMethods(globalMethods, type.name, "${methodName}E${i}",
+ "${methodName}${i}_Extension",
+ type: type);
+ }
emitClasses();
emitMain();
// Sanity.
@@ -315,13 +323,16 @@
assert(localVars.isEmpty);
}
- List<Method> getMethods(int maxMethods, int maxParams, MethodType type,
- {String className = "", String extensionName = "", String namePrefix}) {
+ List<Method> getMethods(int maxMethods, int maxParams, MethodType methodType,
+ {String className,
+ String extensionName,
+ String namePrefix,
+ DartType type}) {
final List<Method> list = <Method>[];
for (int i = 0, n = chooseOneUpTo(maxMethods); i < n; i++) {
- final List<DartType> params =
- fillTypes1(limit: maxParams, isFfi: type == MethodType.ffiMethod);
- switch (type) {
+ final List<DartType> params = fillTypes1(
+ limit: maxParams, isFfi: methodType == MethodType.ffiMethod);
+ switch (methodType) {
case MethodType.globalMethod:
list.add(GlobalMethod("${namePrefix}${i}", params, this));
break;
@@ -333,8 +344,8 @@
InstanceMethod("${namePrefix}${i}", params, this, className));
break;
case MethodType.extensionMethod:
- list.add(ExtensionMethod(
- "${namePrefix}${i}", params, this, className, extensionName));
+ list.add(ExtensionMethod("${namePrefix}${i}", params, this, className,
+ extensionName, type));
break;
}
}
@@ -727,23 +738,29 @@
});
emitNewline();
emitNewline();
- emitExtensionMethods();
+ emitAndAddExtensionMethods(classMethods[currentClass], "X${currentClass}",
+ "XE${currentClass}", "${methodName}${currentClass}_Extension");
currentClass = null;
}
}
- void emitExtensionMethods() {
- classMethods[currentClass].addAll(getMethods(numExtensionMethodsPerClass,
- numMethodParams, MethodType.extensionMethod,
- className: "X${currentClass}",
- extensionName: "XE${currentClass}",
- namePrefix: "${methodName}${currentClass}_Extension"));
- emit("extension XE$currentClass on X$currentClass ");
+ void emitAndAddExtensionMethods(
+ List<Method> methodList, className, extensionName, namePrefix,
+ {DartType type}) {
+ int endIndex = methodList.length;
+ methodList.addAll(getMethods(numExtensionMethodsPerClass, numMethodParams,
+ MethodType.extensionMethod,
+ className: className,
+ // Randomly select between named and anonymous extensions.
+ extensionName: coinFlip() ? extensionName : "",
+ namePrefix: namePrefix,
+ type: type));
+ emit("extension $extensionName on $className ");
emitBraceWrapped(() {
- for (int i = 0; i < classMethods[currentClass].length; i++) {
+ // Emit the newly added methods.
+ for (int i = endIndex; i < methodList.length; i++) {
currentMethod = i;
- if (classMethods[currentClass][i] is ExtensionMethod)
- classMethods[currentClass][i].emit();
+ methodList[i].emit();
currentMethod = null;
}
});
@@ -771,24 +788,23 @@
// Call each global method once.
for (int i = 0; i < globalMethods.length; i++) {
- final outputName = '$methodName$i';
- emitTryCatchFinally(() {
- globalMethods[i].emitCall(1, includeSemicolon: true);
- }, () {
- emitPrint('$outputName() throws');
- });
+ String outputName;
+ emitTryCatchFinally(
+ () => outputName =
+ globalMethods[i].emitCall(1, includeSemicolon: true),
+ () => emitPrint('$outputName() throws'));
emitNewline();
}
// Call each class method once.
for (int i = 0; i < classMethods.length; i++) {
for (int j = 0; j < classMethods[i].length; j++) {
+ String outputName;
emitNewline();
- emitTryCatchFinally(() {
- classMethods[i][j].emitCall(1, includeSemicolon: true);
- }, () {
- emitPrint('X$i().${classMethods[i][j].name}() throws');
- });
+ emitTryCatchFinally(
+ () => outputName =
+ classMethods[i][j].emitCall(1, includeSemicolon: true),
+ () => emitPrint('${outputName} throws'));
}
// Call each virtual class method once.
int parentClass = classParents[i];
@@ -797,12 +813,12 @@
for (int j = 0;
j < virtualClassMethods[i][parentClass].length;
j++) {
- final outputName = 'X${i}().$methodName${parentClass}_${j}';
+ String outputName;
emitNewline();
emitTryCatchFinally(
- () => classMethods[parentClass][j]
+ () => outputName = classMethods[parentClass][j]
.emitCall(1, includeSemicolon: true),
- () => emitPrint('$outputName() throws'));
+ () => emitPrint('${outputName} throws'));
}
}
parentClass = classParents[parentClass];
@@ -897,7 +913,6 @@
// Emit an assignment statement.
bool emitAssign() {
- // Select a type at random.
final tp = oneOfSet(dartType.allTypes);
String assignOp;
if (DartType.isGrowableType(tp)) {
@@ -1218,7 +1233,7 @@
return emitAssign();
}
// Possibly nested statement.
- switch (choose(16)) {
+ switch (choose(17)) {
// Favors assignment.
case 0:
return emitPrint();
@@ -1248,6 +1263,9 @@
return emitTryCatch(depth);
case 13:
return emitForEach(depth);
+ case 14:
+ emitLibraryCall(depth, DartType.VOID, includeSemicolon: true);
+ return true;
default:
return emitAssign();
}
@@ -1564,7 +1582,8 @@
}
}
- String emitScalarVar(DartType tp, {bool isLhs = false, RhsFilter rhsFilter}) {
+ // Pick an existing variable of the given type.
+ String pickScalarVar(DartType tp, {bool isLhs = false, RhsFilter rhsFilter}) {
// Randomly specialize interface type, unless emitting left hand side.
if (!isLhs) tp = maybeSpecializeInterface(tp);
// Collect all choices from globals, fields, locals, and parameters.
@@ -1617,11 +1636,18 @@
if (choices.isEmpty) {
throw 'No variable to emit for type ${tp.name}';
}
- final emittedVar = '${choices.elementAt(choose(choices.length))}';
- if (rhsFilter != null && (emittedVar == rhsFilter.lhsVar)) {
- rhsFilter.consume();
+
+ return '${choices.elementAt(choose(choices.length))}';
+ }
+
+ String emitScalarVar(DartType tp, {bool isLhs = false, RhsFilter rhsFilter}) {
+ final emittedVar = pickScalarVar(tp, isLhs: isLhs, rhsFilter: rhsFilter);
+ if (emittedVar != null) {
+ if (rhsFilter != null && (emittedVar == rhsFilter.lhsVar)) {
+ rhsFilter.consume();
+ }
+ emit(emittedVar);
}
- emit(emittedVar);
return emittedVar;
}
@@ -1761,31 +1787,45 @@
}
}
+ bool isTypedDataFloatType(String proto) {
+ for (int i = 0; i < proto.length; ++i) {
+ if (DartLib.typedDataFloatTypes.contains(proto[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
// Emit library call.
- void emitLibraryCall(int depth, DartType tp, {RhsFilter rhsFilter}) {
+ void emitLibraryCall(int depth, DartType tp,
+ {RhsFilter rhsFilter, bool includeSemicolon = false}) {
DartLib lib = getLibraryMethod(tp);
- if (lib == null) {
- // no matching lib: resort to literal.
+ if (lib == null || (!fp && isTypedDataFloatType(lib.proto))) {
+ // We cannot find a library method, or we found a library method but its
+ // prototype has a floating point type, and fp is disabled. This can only
+ // happen for non-void types. In those cases, we resort to a literal.
+ assert(tp != DartType.VOID);
emitLiteral(depth + 1, tp, rhsFilter: rhsFilter);
return;
}
emitParenWrapped(() {
- String proto = lib.proto;
+ String prototype = lib.proto;
// Receiver.
- if (proto[0] != 'V') {
+ if (prototype[0] != 'V') {
emitParenWrapped(
- () => emitArg(depth + 1, proto[0], rhsFilter: rhsFilter));
+ () => emitArg(depth + 1, prototype[0], rhsFilter: rhsFilter));
emit('.');
}
// Call.
emit('${lib.name}');
// Parameters.
- if (proto[1] != 'v') {
+ if (prototype[1] != 'v') {
emitParenWrapped(() {
- if (proto[1] != 'V') {
+ if (prototype[1] != 'V') {
emitCommaSeparated(
- (int i) => emitArg(depth + 1, proto[i], rhsFilter: rhsFilter),
- proto.length,
+ (int i) =>
+ emitArg(depth + 1, prototype[i], rhsFilter: rhsFilter),
+ prototype.length,
start: 1);
}
});
@@ -1795,6 +1835,9 @@
emit(' as ${tp.name}');
}
});
+ if (includeSemicolon) {
+ emit(';');
+ }
}
// Helper for a method call.
@@ -1802,9 +1845,7 @@
{RhsFilter rhsFilter}) {
for (int i = m - 1; i >= 0; i--) {
if (tp == methods[i].returnType) {
- bool extensionApplication = methods[i] is ExtensionMethod && coinFlip();
- methods[i].emitCall(depth + 1,
- rhsFilter: rhsFilter, extensionApplication: extensionApplication);
+ methods[i].emitCall(depth + 1, rhsFilter: rhsFilter);
return true;
}
}
@@ -1917,58 +1958,29 @@
//
// Get a library method that returns given type.
- DartLib getLibraryMethod(DartType tp) {
- if (tp == DartType.BOOL) {
- return oneOf(api.boolLibs);
- } else if (tp == DartType.INT) {
- return oneOf(api.intLibs);
- } else if (tp == DartType.DOUBLE) {
- return oneOf(api.doubleLibs);
- } else if (tp == DartType.STRING) {
- return oneOf(DartLib.stringLibs);
- } else if (tp == DartType.LIST_INT) {
- return oneOf(DartLib.listLibs);
- } else if (tp == DartType.SET_INT) {
- return oneOf(DartLib.setLibs);
- } else if (tp == DartType.MAP_INT_STRING) {
- return oneOf(DartLib.mapLibs);
- }
- // No library method available that returns this type.
- return null;
- }
+ DartLib getLibraryMethod(DartType tp) =>
+ api.typeToLibraryMethods.containsKey(tp)
+ ? oneOf(api.typeToLibraryMethods[tp])
+ : null;
// Emit a library argument, possibly subject to restrictions.
void emitArg(int depth, String p, {RhsFilter rhsFilter}) {
switch (p) {
- case 'B':
- emitExpr(depth, DartType.BOOL);
- break;
case 'i': // emit small int
emitSmallPositiveInt();
break;
- case 'I':
- emitExpr(depth, DartType.INT);
- break;
- case 'D':
+ case 'D': // resort to INT if floating point is disabled
emitExpr(depth, fp ? DartType.DOUBLE : DartType.INT);
break;
- case 'S':
- emitExpr(depth, DartType.STRING, rhsFilter: rhsFilter);
- break;
case 's': // emit small string
emitString(length: 2);
break;
- case 'L':
- emitExpr(depth, DartType.LIST_INT, rhsFilter: rhsFilter);
- break;
- case 'X':
- emitExpr(depth, DartType.SET_INT, rhsFilter: rhsFilter);
- break;
- case 'M':
- emitExpr(depth, DartType.MAP_INT_STRING, rhsFilter: rhsFilter);
- break;
default:
- throw ArgumentError('Invalid p value: $p');
+ DartType type = DartLib.stringToType[p];
+ if (type == null) {
+ throw ArgumentError('Invalid p value: $p');
+ }
+ emitExpr(depth, type, rhsFilter: rhsFilter);
}
}
diff --git a/runtime/tools/dartfuzz/dartfuzz_api_table.dart b/runtime/tools/dartfuzz/dartfuzz_api_table.dart
index 26e4852..c2f5948 100644
--- a/runtime/tools/dartfuzz/dartfuzz_api_table.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_api_table.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 "dartfuzz_type_table.dart";
+
/// Class that represents Dart library methods.
///
/// The invididual lists are organized by return type.
@@ -24,7 +26,23 @@
/// L List<int>
/// X Set<int>
/// M Map<int, String>
-///
+/// A Int8List
+/// C Int16List
+/// E Int32List
+/// F Int32x4
+/// G Int32x4List
+/// H Int64List
+/// J Float32List
+/// K Float32x4
+/// N Float32x4List
+/// O Float64List
+/// P Float64x2
+/// Q Float64x2List
+/// R uint8ClampedList
+/// T uint8List
+/// U uint16List
+/// W uint32List
+/// Y uint64List
/// NOTE: this code has been generated automatically.
///
class DartLib {
@@ -32,12 +50,90 @@
final String proto;
const DartLib(this.name, this.proto);
+ static const stringToType = {
+ 'V': DartType.VOID,
+ 'B': DartType.BOOL,
+ 'I': DartType.INT,
+ 'D': DartType.DOUBLE,
+ 'S': DartType.STRING,
+ 'L': DartType.LIST_INT,
+ 'X': DartType.SET_INT,
+ 'M': DartType.MAP_INT_STRING,
+ 'A': DartType.INT8LIST,
+ 'C': DartType.INT16LIST,
+ 'E': DartType.INT32LIST,
+ 'F': DartType.INT32X4,
+ 'G': DartType.INT32X4LIST,
+ 'H': DartType.INT64LIST,
+ 'J': DartType.FLOAT32LIST,
+ 'K': DartType.FLOAT32X4,
+ 'N': DartType.FLOAT32X4LIST,
+ 'O': DartType.FLOAT64LIST,
+ 'P': DartType.FLOAT64X2,
+ 'Q': DartType.FLOAT64X2LIST,
+ 'R': DartType.UINT8CLAMPEDLIST,
+ 'T': DartType.UINT8LIST,
+ 'U': DartType.UINT16LIST,
+ 'W': DartType.UINT32LIST,
+ 'Y': DartType.UINT64LIST,
+ };
+ static final typeToLibraryMethods = {
+ DartType.VOID: voidLibs,
+ DartType.BOOL: boolLibs,
+ DartType.INT: intLibs,
+ DartType.DOUBLE: doubleLibs,
+ DartType.STRING: stringLibs,
+ DartType.LIST_INT: listLibs,
+ DartType.SET_INT: setLibs,
+ DartType.MAP_INT_STRING: mapLibs,
+ DartType.INT8LIST: int8ListLibs,
+ DartType.INT16LIST: int16ListLibs,
+ DartType.INT32LIST: int32ListLibs,
+ DartType.INT32X4: int32x4Libs,
+ DartType.INT32X4LIST: int32x4ListLibs,
+ DartType.INT64LIST: int64ListLibs,
+ DartType.FLOAT32LIST: float32ListLibs,
+ DartType.FLOAT32X4: float32x4Libs,
+ DartType.FLOAT32X4LIST: float32x4ListLibs,
+ DartType.FLOAT64LIST: float64ListLibs,
+ DartType.FLOAT64X2: float64x2Libs,
+ DartType.FLOAT64X2LIST: float64x2ListLibs,
+ DartType.UINT8CLAMPEDLIST: uint8ClampedListLibs,
+ DartType.UINT8LIST: uint8ListLibs,
+ DartType.UINT16LIST: uint16ListLibs,
+ DartType.UINT32LIST: uint32ListLibs,
+ DartType.UINT64LIST: uint64ListLibs,
+ };
+ static const typedDataFloatTypes = [
+ 'J',
+ 'K',
+ 'N',
+ 'O',
+ 'P',
+ 'Q',
+ ];
+ static const voidLibs = [
+ DartLib('RangeError.checkNotNegative', 'VISS'),
+ DartLib('RangeError.checkValueInInterval', 'VIIISS'),
+ DartLib('add', 'LI'),
+ DartLib('addAll', 'MM'),
+ DartLib('clear', 'LV'),
+ DartLib('clear', 'MV'),
+ DartLib('clear', 'XV'),
+ DartLib('fillRange', 'LIII'),
+ DartLib('insert', 'LII'),
+ DartLib('removeRange', 'LII'),
+ ];
static const boolLibs = [
DartLib('NetworkInterface.listSupported', 'Vv'),
DartLib('SecurityContext.alpnSupported', 'Vv'),
DartLib('add', 'XI'),
DartLib('bool.fromEnvironment', 'VS'),
DartLib('endsWith', 'SS'),
+ DartLib('flagW', 'Fv'),
+ DartLib('flagX', 'Fv'),
+ DartLib('flagY', 'Fv'),
+ DartLib('flagZ', 'Fv'),
DartLib('isEmpty', 'Mv'),
DartLib('isEmpty', 'Sv'),
DartLib('isEven', 'Iv'),
@@ -658,8 +754,8 @@
DartLib('ceil', 'DV'),
DartLib('ceil', 'IV'),
DartLib('codeUnitAt', 'SI'),
- DartLib('compareTo', 'DD'),
DartLib('compareTo', 'SS'),
+ DartLib('compareTo', 'DD'),
DartLib('floor', 'IV'),
DartLib('floor', 'DV'),
DartLib('floor', 'DV'),
@@ -670,8 +766,8 @@
DartLib('int.tryParse', 'VS'),
DartLib('lastIndexOf', 'LII'),
DartLib('length', 'Mv'),
- DartLib('length', 'Lv'),
DartLib('length', 'Sv'),
+ DartLib('length', 'Lv'),
DartLib('modInverse', 'II'),
DartLib('modPow', 'III'),
DartLib('removeAt', 'LI'),
@@ -680,14 +776,21 @@
DartLib('round', 'IV'),
DartLib('round', 'DV'),
DartLib('sign', 'Iv'),
+ DartLib('signMask', 'Pv'),
+ DartLib('signMask', 'Kv'),
+ DartLib('signMask', 'Fv'),
DartLib('toInt', 'DV'),
DartLib('toSigned', 'II'),
DartLib('toUnsigned', 'II'),
- DartLib('truncate', 'DV'),
DartLib('truncate', 'IV'),
DartLib('truncate', 'DV'),
+ DartLib('truncate', 'DV'),
DartLib('unicodeBomCharacterRune', 'Vv'),
DartLib('unicodeReplacementCharacterRune', 'Vv'),
+ DartLib('w', 'Fv'),
+ DartLib('x', 'Fv'),
+ DartLib('y', 'Fv'),
+ DartLib('z', 'Fv'),
];
static const doubleLibs = [
DartLib('abs', 'DV'),
@@ -697,8 +800,8 @@
DartLib('atan', 'VD'),
DartLib('atan2', 'VDD'),
DartLib('ceilToDouble', 'DV'),
- DartLib('ceilToDouble', 'DV'),
DartLib('ceilToDouble', 'IV'),
+ DartLib('ceilToDouble', 'DV'),
DartLib('clamp', 'DDD'),
DartLib('cos', 'VD'),
DartLib('double.infinity', 'Vv'),
@@ -733,9 +836,15 @@
DartLib('sqrt2', 'Vv'),
DartLib('tan', 'VD'),
DartLib('toDouble', 'DV'),
+ DartLib('truncateToDouble', 'DV'),
DartLib('truncateToDouble', 'IV'),
DartLib('truncateToDouble', 'DV'),
- DartLib('truncateToDouble', 'DV'),
+ DartLib('w', 'Kv'),
+ DartLib('x', 'Kv'),
+ DartLib('x', 'Pv'),
+ DartLib('y', 'Pv'),
+ DartLib('y', 'Kv'),
+ DartLib('z', 'Kv'),
];
static const stringLibs = [
DartLib('ListBase.listToString', 'VL'),
@@ -771,23 +880,129 @@
DartLib('trimRight', 'SV'),
];
static const listLibs = [
- DartLib('List.filled', 'ViI'),
+ DartLib('List<int>.filled', 'ViI'),
DartLib('Uri.parseIPv4Address', 'VS'),
DartLib('Uri.parseIPv6Address', 'VSII'),
DartLib('codeUnits', 'Sv'),
DartLib('sublist', 'LII'),
];
static const setLibs = [
- DartLib('Set.identity', 'VV'),
+ DartLib('Set<int>.identity', 'VV'),
DartLib('difference', 'XX'),
DartLib('intersection', 'XX'),
DartLib('toSet', 'XV'),
DartLib('union', 'XX'),
];
static const mapLibs = [
- DartLib('Map.from', 'VM'),
- DartLib('Map.identity', 'VV'),
- DartLib('Map.of', 'VM'),
- DartLib('Map.unmodifiable', 'VM'),
+ DartLib('Map<int, String>.from', 'VM'),
+ DartLib('Map<int, String>.identity', 'VV'),
+ DartLib('Map<int, String>.of', 'VM'),
+ DartLib('Map<int, String>.unmodifiable', 'VM'),
+ ];
+ static const int8ListLibs = [
+ DartLib('Int8List.fromList', 'VL'),
+ DartLib('sublist', 'AII'),
+ ];
+ static const int16ListLibs = [
+ DartLib('Int16List.fromList', 'VL'),
+ DartLib('sublist', 'CII'),
+ ];
+ static const int32ListLibs = [
+ DartLib('Int32List.fromList', 'VL'),
+ DartLib('sublist', 'EII'),
+ ];
+ static const int32x4Libs = [
+ DartLib('Int32x4.bool', 'VBBBB'),
+ DartLib('Int32x4.fromFloat32x4Bits', 'VK'),
+ DartLib('equal', 'KK'),
+ DartLib('greaterThan', 'KK'),
+ DartLib('greaterThanOrEqual', 'KK'),
+ DartLib('lessThan', 'KK'),
+ DartLib('lessThanOrEqual', 'KK'),
+ DartLib('notEqual', 'KK'),
+ DartLib('shuffle', 'FI'),
+ DartLib('shuffleMix', 'FFI'),
+ DartLib('withFlagW', 'FB'),
+ DartLib('withFlagX', 'FB'),
+ DartLib('withFlagY', 'FB'),
+ DartLib('withFlagZ', 'FB'),
+ DartLib('withW', 'FI'),
+ DartLib('withX', 'FI'),
+ DartLib('withY', 'FI'),
+ DartLib('withZ', 'FI'),
+ ];
+ static const int32x4ListLibs = [
+ DartLib('sublist', 'GII'),
+ ];
+ static const int64ListLibs = [
+ DartLib('Int64List.fromList', 'VL'),
+ DartLib('sublist', 'HII'),
+ ];
+ static const float32ListLibs = [
+ DartLib('sublist', 'JII'),
+ ];
+ static const float32x4Libs = [
+ DartLib('Float32x4.fromFloat64x2', 'VP'),
+ DartLib('Float32x4.fromInt32x4Bits', 'VF'),
+ DartLib('Float32x4.splat', 'VD'),
+ DartLib('Float32x4.zero', 'VV'),
+ DartLib('abs', 'KV'),
+ DartLib('clamp', 'KKK'),
+ DartLib('max', 'KK'),
+ DartLib('min', 'KK'),
+ DartLib('reciprocal', 'KV'),
+ DartLib('reciprocalSqrt', 'KV'),
+ DartLib('scale', 'KD'),
+ DartLib('select', 'FKK'),
+ DartLib('shuffle', 'KI'),
+ DartLib('shuffleMix', 'KKI'),
+ DartLib('sqrt', 'KV'),
+ DartLib('withW', 'KD'),
+ DartLib('withX', 'KD'),
+ DartLib('withY', 'KD'),
+ DartLib('withZ', 'KD'),
+ ];
+ static const float32x4ListLibs = [
+ DartLib('sublist', 'NII'),
+ ];
+ static const float64ListLibs = [
+ DartLib('sublist', 'OII'),
+ ];
+ static const float64x2Libs = [
+ DartLib('Float64x2.fromFloat32x4', 'VK'),
+ DartLib('Float64x2.splat', 'VD'),
+ DartLib('Float64x2.zero', 'VV'),
+ DartLib('abs', 'PV'),
+ DartLib('clamp', 'PPP'),
+ DartLib('max', 'PP'),
+ DartLib('min', 'PP'),
+ DartLib('scale', 'PD'),
+ DartLib('sqrt', 'PV'),
+ DartLib('withX', 'PD'),
+ DartLib('withY', 'PD'),
+ ];
+ static const float64x2ListLibs = [
+ DartLib('sublist', 'QII'),
+ ];
+ static const uint8ClampedListLibs = [
+ DartLib('Uint8ClampedList.fromList', 'VL'),
+ DartLib('sublist', 'RII'),
+ ];
+ static const uint8ListLibs = [
+ DartLib('Uint8List.fromList', 'VL'),
+ DartLib('base64Decode', 'VS'),
+ DartLib('sublist', 'TII'),
+ ];
+ static const uint16ListLibs = [
+ DartLib('Uint16List.fromList', 'VL'),
+ DartLib('sublist', 'UII'),
+ ];
+ static const uint32ListLibs = [
+ DartLib('Uint32List.fromList', 'VL'),
+ DartLib('sublist', 'WII'),
+ ];
+ static const uint64ListLibs = [
+ DartLib('Uint64List.fromList', 'VL'),
+ DartLib('sublist', 'YII'),
];
}
diff --git a/runtime/tools/dartfuzz/dartfuzz_type_table.dart b/runtime/tools/dartfuzz/dartfuzz_type_table.dart
index bcd16d2..889b210 100644
--- a/runtime/tools/dartfuzz/dartfuzz_type_table.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_type_table.dart
@@ -148,6 +148,7 @@
return _allTypes;
}
+ static const VOID = const DartType._withName("void");
static const INT8LIST = const DartType._withName("Int8List");
static const UINT8LIST = const DartType._withName("Uint8List");
static const UINT8CLAMPEDLIST = const DartType._withName("Uint8ClampedList");
@@ -2939,6 +2940,8 @@
return _allTypes;
}
+ static const VOID = const DartType._withName("void");
+
// All types extracted from analyzer.
static const _allTypes = {
DartType.INT8LIST,
@@ -4649,6 +4652,8 @@
return _allTypes;
}
+ static const VOID = const DartType._withName("void");
+
// All types extracted from analyzer.
static const _allTypes = {
DartType.INT8LIST,
@@ -6576,6 +6581,8 @@
return _allTypes;
}
+ static const VOID = const DartType._withName("void");
+
// All types extracted from analyzer.
static const _allTypes = {
DartType.INT8LIST,
diff --git a/runtime/tools/dartfuzz/gen_api_table.dart b/runtime/tools/dartfuzz/gen_api_table.dart
index f8f2ba1..a2f7a6b 100644
--- a/runtime/tools/dartfuzz/gen_api_table.dart
+++ b/runtime/tools/dartfuzz/gen_api_table.dart
@@ -29,6 +29,7 @@
}
// Lists of recognized methods, organized by return type.
+var voidTable = <DartLib>[];
var boolTable = <DartLib>[];
var intTable = <DartLib>[];
var doubleTable = <DartLib>[];
@@ -36,6 +37,140 @@
var listTable = <DartLib>[];
var setTable = <DartLib>[];
var mapTable = <DartLib>[];
+var int8ListTable = <DartLib>[];
+var int16ListTable = <DartLib>[];
+var int32ListTable = <DartLib>[];
+var int32x4Table = <DartLib>[];
+var int32x4ListTable = <DartLib>[];
+var int64ListTable = <DartLib>[];
+var float32ListTable = <DartLib>[];
+var float32x4ListTable = <DartLib>[];
+var float32x4Table = <DartLib>[];
+var float64ListTable = <DartLib>[];
+var float64x2Table = <DartLib>[];
+var float64x2ListTable = <DartLib>[];
+var uint8ClampedListTable = <DartLib>[];
+var uint8ListTable = <DartLib>[];
+var uint16ListTable = <DartLib>[];
+var uint32ListTable = <DartLib>[];
+var uint64ListTable = <DartLib>[];
+
+const voidEncoding = 'V';
+const boolEncoding = 'B';
+const intEncoding = 'I';
+const doubleEncoding = 'D';
+const stringEncoding = 'S';
+const listEncoding = 'L';
+const setEncoding = 'X';
+const mapEncoding = 'M';
+const int8ListEncoding = 'A';
+const int16ListEncoding = 'C';
+const int32ListEncoding = 'E';
+const int32x4Encoding = 'F';
+const int32x4ListEncoding = 'G';
+const int64ListEncoding = 'H';
+const float32ListEncoding = 'J';
+const float32x4Encoding = 'K';
+const float32x4ListEncoding = 'N';
+const float64ListEncoding = 'O';
+const float64x2Encoding = 'P';
+const float64x2ListEncoding = 'Q';
+const uint8ClampedListEncoding = 'R';
+const uint8ListEncoding = 'T';
+const uint16ListEncoding = 'U';
+const uint32ListEncoding = 'W';
+const uint64ListEncoding = 'Y';
+
+final voidLibs = 'voidLibs';
+final boolLibs = 'boolLibs';
+final intLibs = 'intLibs';
+final doubleLibs = 'doubleLibs';
+final stringLibs = 'stringLibs';
+final listLibs = 'listLibs';
+final setLibs = 'setLibs';
+final mapLibs = 'mapLibs';
+final int8ListLibs = 'int8ListLibs';
+final int16ListLibs = 'int16ListLibs';
+final int32ListLibs = 'int32ListLibs';
+final int32x4Libs = 'int32x4Libs';
+final int32x4ListLibs = 'int32x4ListLibs';
+final int64ListLibs = 'int64ListLibs';
+final float32ListLibs = 'float32ListLibs';
+final float32x4Libs = 'float32x4Libs';
+final float32x4ListLibs = 'float32x4ListLibs';
+final float64ListLibs = 'float64ListLibs';
+final float64x2Libs = 'float64x2Libs';
+final float64x2ListLibs = 'float64x2ListLibs';
+final uint8ClampedListLibs = 'uint8ClampedListLibs';
+final uint8ListLibs = 'uint8ListLibs';
+final uint16ListLibs = 'uint16ListLibs';
+final uint32ListLibs = 'uint32ListLibs';
+final uint64ListLibs = 'uint64ListLibs';
+
+final stringToType = {
+ voidEncoding: 'DartType.VOID',
+ boolEncoding: 'DartType.BOOL',
+ intEncoding: 'DartType.INT',
+ doubleEncoding: 'DartType.DOUBLE',
+ stringEncoding: 'DartType.STRING',
+ listEncoding: 'DartType.LIST_INT',
+ setEncoding: 'DartType.SET_INT',
+ mapEncoding: 'DartType.MAP_INT_STRING',
+ int8ListEncoding: 'DartType.INT8LIST',
+ int16ListEncoding: 'DartType.INT16LIST',
+ int32ListEncoding: 'DartType.INT32LIST',
+ int32x4Encoding: 'DartType.INT32X4',
+ int32x4ListEncoding: 'DartType.INT32X4LIST',
+ int64ListEncoding: 'DartType.INT64LIST',
+ float32ListEncoding: 'DartType.FLOAT32LIST',
+ float32x4Encoding: 'DartType.FLOAT32X4',
+ float32x4ListEncoding: 'DartType.FLOAT32X4LIST',
+ float64ListEncoding: 'DartType.FLOAT64LIST',
+ float64x2Encoding: 'DartType.FLOAT64X2',
+ float64x2ListEncoding: 'DartType.FLOAT64X2LIST',
+ uint8ClampedListEncoding: 'DartType.UINT8CLAMPEDLIST',
+ uint8ListEncoding: 'DartType.UINT8LIST',
+ uint16ListEncoding: 'DartType.UINT16LIST',
+ uint32ListEncoding: 'DartType.UINT32LIST',
+ uint64ListEncoding: 'DartType.UINT64LIST'
+};
+
+final typeToLibraryMethods = {
+ 'DartType.VOID': voidLibs,
+ 'DartType.BOOL': boolLibs,
+ 'DartType.INT': intLibs,
+ 'DartType.DOUBLE': doubleLibs,
+ 'DartType.STRING': stringLibs,
+ 'DartType.LIST_INT': listLibs,
+ 'DartType.SET_INT': setLibs,
+ 'DartType.MAP_INT_STRING': mapLibs,
+ 'DartType.INT8LIST': int8ListLibs,
+ 'DartType.INT16LIST': int16ListLibs,
+ 'DartType.INT32LIST': int32ListLibs,
+ 'DartType.INT32X4': int32x4Libs,
+ 'DartType.INT32X4LIST': int32x4ListLibs,
+ 'DartType.INT64LIST': int64ListLibs,
+ 'DartType.FLOAT32LIST': float32ListLibs,
+ 'DartType.FLOAT32X4': float32x4Libs,
+ 'DartType.FLOAT32X4LIST': float32x4ListLibs,
+ 'DartType.FLOAT64LIST': float64ListLibs,
+ 'DartType.FLOAT64X2': float64x2Libs,
+ 'DartType.FLOAT64X2LIST': float64x2ListLibs,
+ 'DartType.UINT8CLAMPEDLIST': uint8ClampedListLibs,
+ 'DartType.UINT8LIST': uint8ListLibs,
+ 'DartType.UINT16LIST': uint16ListLibs,
+ 'DartType.UINT32LIST': uint32ListLibs,
+ 'DartType.UINT64LIST': uint64ListLibs
+};
+
+final typedDataFloatTypes = [
+ float32ListEncoding,
+ float32x4Encoding,
+ float32x4ListEncoding,
+ float64ListEncoding,
+ float64x2Encoding,
+ float64x2ListEncoding
+];
main() async {
final AnalysisSession session = GenUtil.createAnalysisSession();
@@ -53,13 +188,34 @@
// Generate the tables in a stand-alone Dart class.
dumpHeader();
- dumpTable('boolLibs', boolTable);
- dumpTable('intLibs', intTable);
- dumpTable('doubleLibs', doubleTable);
- dumpTable('stringLibs', stringTable);
- dumpTable('listLibs', listTable);
- dumpTable('setLibs', setTable);
- dumpTable('mapLibs', mapTable);
+ dumpStringToTypeMap();
+ dumpTypeToLibraryMethodMap();
+ dumpTypedDataFloatTypes();
+ dumpTable(voidLibs, voidTable);
+ dumpTable(boolLibs, boolTable);
+ dumpTable(intLibs, intTable);
+ dumpTable(doubleLibs, doubleTable);
+ dumpTable(stringLibs, stringTable);
+ dumpTable(listLibs, listTable);
+ dumpTable(setLibs, setTable);
+ dumpTable(mapLibs, mapTable);
+ dumpTable(int8ListLibs, int8ListTable);
+ dumpTable(int16ListLibs, int16ListTable);
+ dumpTable(int32ListLibs, int32ListTable);
+ dumpTable(int32x4Libs, int32x4Table);
+ dumpTable(int32x4ListLibs, int32x4ListTable);
+ dumpTable(int64ListLibs, int64ListTable);
+ dumpTable(float32ListLibs, float32ListTable);
+ dumpTable(float32x4Libs, float32x4Table);
+ dumpTable(float32x4ListLibs, float32x4ListTable);
+ dumpTable(float64ListLibs, float64ListTable);
+ dumpTable(float64x2Libs, float64x2Table);
+ dumpTable(float64x2ListLibs, float64x2ListTable);
+ dumpTable(uint8ClampedListLibs, uint8ClampedListTable);
+ dumpTable(uint8ListLibs, uint8ListTable);
+ dumpTable(uint16ListLibs, uint16ListTable);
+ dumpTable(uint32ListLibs, uint32ListTable);
+ dumpTable(uint64ListLibs, uint64ListTable);
dumpFooter();
}
@@ -122,7 +278,7 @@
constructor.name.isNotEmpty) {
addToTable(
typeString(classElement.thisType),
- '${classElement.name}.${constructor.name}',
+ '${classString(classElement)}.${constructor.name}',
protoString(null, constructor.parameters));
}
}
@@ -131,7 +287,7 @@
if (method.isStatic) {
addToTable(
typeString(method.returnType),
- '${classElement.name}.${method.name}',
+ '${classString(classElement)}.${method.name}',
protoString(null, method.parameters));
} else {
addToTable(typeString(method.returnType), method.name,
@@ -153,50 +309,101 @@
}
}
+// Function that returns the explicit class name.
+String classString(ClassElement classElement) {
+ switch (typeString(classElement.thisType)) {
+ case setEncoding:
+ return 'Set<int>';
+ case listEncoding:
+ return 'List<int>';
+ case mapEncoding:
+ return 'Map<int, String>';
+ default:
+ return classElement.name;
+ }
+}
+
// Types are represented by an instance of `DartType`. For classes, the type
// will be an instance of `InterfaceType`, which will provide access to the
// defining (class) element, as well as any type arguments.
String typeString(DartType type) {
if (type.isDartCoreBool) {
- return 'B';
+ return boolEncoding;
} else if (type.isDartCoreInt) {
- return 'I';
+ return intEncoding;
} else if (type.isDartCoreDouble) {
- return 'D';
+ return doubleEncoding;
} else if (type.isDartCoreString) {
- return 'S';
+ return stringEncoding;
}
// Supertypes or type parameters are specialized in a consistent manner.
// TODO(ajcbik): inspect type structure semantically, not by display name
// and unify DartFuzz's DartType with analyzer DartType.
switch (type.displayName) {
+ case 'void':
+ return voidEncoding;
case 'E':
- return 'I';
+ return intEncoding;
case 'num':
- return 'D';
+ return doubleEncoding;
case 'List<E>':
case 'List<Object>':
case 'List<dynamic>':
case 'List<int>':
case 'List':
- return 'L';
+ return listEncoding;
case 'Set<E>':
case 'Set<Object>':
case 'Set<dynamic>':
case 'Set<int>':
case 'Set':
- return 'X';
+ return setEncoding;
case 'Map<K, V>':
case 'Map<dynamic, dynamic>':
case 'Map<int, String>':
case 'Map':
- return 'M';
+ return mapEncoding;
+ // TypedData types.
+ case 'Int8List':
+ return int8ListEncoding;
+ case 'Int16List':
+ return int16ListEncoding;
+ case 'Int32List':
+ return int32ListEncoding;
+ case 'Int32x4':
+ return int32x4Encoding;
+ case 'Int32x4List':
+ return int32x4ListEncoding;
+ case 'Int64List':
+ return int64ListEncoding;
+ case 'Float32List':
+ return float32ListEncoding;
+ case 'Float32x4':
+ return float32x4Encoding;
+ case 'Float32x4List':
+ return float32x4ListEncoding;
+ case 'Float64List':
+ return float64ListEncoding;
+ case 'Float64x2':
+ return float64x2Encoding;
+ case 'Float64x2List':
+ return float64x2ListEncoding;
+ case 'Uint8ClampedList':
+ return uint8ClampedListEncoding;
+ case 'Uint8List':
+ return uint8ListEncoding;
+ case 'Uint16List':
+ return uint16ListEncoding;
+ case 'Uint32List':
+ return uint32ListEncoding;
+ case 'Uint64List':
+ return uint64ListEncoding;
}
return '?';
}
String protoString(DartType receiver, List<ParameterElement> parameters) {
- var proto = receiver == null ? 'V' : typeString(receiver);
+ var proto = receiver == null ? voidEncoding : typeString(receiver);
// Construct prototype for non-named parameters.
for (ParameterElement parameter in parameters) {
if (!parameter.isNamed) {
@@ -204,25 +411,62 @@
}
}
// Use 'void' for an empty parameter list.
- return proto.length == 1 ? proto + 'V' : proto;
+ return proto.length == 1 ? proto + voidEncoding : proto;
}
List<DartLib> getTable(String ret) {
switch (ret) {
- case 'B':
+ case voidEncoding:
+ return voidTable;
+ case boolEncoding:
return boolTable;
- case 'I':
+ case intEncoding:
return intTable;
- case 'D':
+ case doubleEncoding:
return doubleTable;
- case 'S':
+ case stringEncoding:
return stringTable;
- case 'L':
+ case listEncoding:
return listTable;
- case 'X':
+ case setEncoding:
return setTable;
- case 'M':
+ case mapEncoding:
return mapTable;
+ // TypedData types.
+ case int8ListEncoding:
+ return int8ListTable;
+ case int16ListEncoding:
+ return int16ListTable;
+ case int32ListEncoding:
+ return int32ListTable;
+ case int32x4Encoding:
+ return int32x4Table;
+ case int32x4ListEncoding:
+ return int32x4ListTable;
+ case int64ListEncoding:
+ return int64ListTable;
+ case float32ListEncoding:
+ return float32ListTable;
+ case float32x4Encoding:
+ return float32x4Table;
+ case float32x4ListEncoding:
+ return float32x4ListTable;
+ case float64ListEncoding:
+ return float64ListTable;
+ case float64x2Encoding:
+ return float64x2Table;
+ case float64x2ListEncoding:
+ return float64x2ListTable;
+ case uint8ClampedListEncoding:
+ return uint8ClampedListTable;
+ case uint8ListEncoding:
+ return uint8ListTable;
+ case uint16ListEncoding:
+ return uint16ListTable;
+ case uint32ListEncoding:
+ return uint32ListTable;
+ case uint64ListEncoding:
+ return uint64ListTable;
default:
throw ArgumentError('Invalid ret value: $ret');
}
@@ -235,8 +479,11 @@
if (ret.contains('?') || proto.contains('?')) {
return;
}
- // Avoid some obvious false divergences.
- if (name == 'pid' || name == 'hashCode' || name == 'exitCode') {
+ // Avoid the exit function and other functions that give false divergences.
+ if (name == 'exit' ||
+ name == 'pid' ||
+ name == 'hashCode' ||
+ name == 'exitCode') {
return;
}
// Restrict parameters for a few hardcoded cases,
@@ -244,8 +491,8 @@
// allocation in the generated fuzzing program.
if (name == 'padLeft' || name == 'padRight') {
proto = proto.replaceFirst('IS', 'is');
- } else if (name == 'List.filled') {
- proto = proto.replaceFirst('I', 'i');
+ } else if (name == 'List<int>.filled') {
+ proto = proto.replaceFirst(intEncoding, 'i');
}
// Add to table.
getTable(ret).add(DartLib(name, proto));
@@ -257,6 +504,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 \"dartfuzz_type_table.dart\";
+
/// Class that represents Dart library methods.
///
/// The invididual lists are organized by return type.
@@ -279,7 +528,23 @@
/// L List<int>
/// X Set<int>
/// M Map<int, String>
-///
+/// A Int8List
+/// C Int16List
+/// E Int32List
+/// F Int32x4
+/// G Int32x4List
+/// H Int64List
+/// J Float32List
+/// K Float32x4
+/// N Float32x4List
+/// O Float64List
+/// P Float64x2
+/// Q Float64x2List
+/// R uint8ClampedList
+/// T uint8List
+/// U uint16List
+/// W uint32List
+/// Y uint64List
/// NOTE: this code has been generated automatically.
///
class DartLib {
@@ -289,6 +554,30 @@
""");
}
+void dumpStringToTypeMap() {
+ print(' static const stringToType = {');
+ for (var key in stringToType.keys) {
+ print(' \'${key}\': ${stringToType[key]},');
+ }
+ print(' };');
+}
+
+void dumpTypeToLibraryMethodMap() {
+ print(' static final typeToLibraryMethods = {');
+ for (var key in typeToLibraryMethods.keys) {
+ print(' ${key}: ${typeToLibraryMethods[key]},');
+ }
+ print(' };');
+}
+
+void dumpTypedDataFloatTypes() {
+ print(' static const typedDataFloatTypes = [');
+ for (var type in typedDataFloatTypes) {
+ print(' \'${type}\',');
+ }
+ print(' ];');
+}
+
void dumpTable(String identifier, List<DartLib> table) {
print(' static const $identifier = [');
table.sort((a, b) => a.name.compareTo(b.name));
diff --git a/runtime/tools/dartfuzz/gen_type_table.dart b/runtime/tools/dartfuzz/gen_type_table.dart
index f2a08eb..945d7f0 100644
--- a/runtime/tools/dartfuzz/gen_type_table.dart
+++ b/runtime/tools/dartfuzz/gen_type_table.dart
@@ -655,6 +655,7 @@
""");
+ print(" static const VOID = const " + "DartType._withName(\"void\");");
Set<String> instTypes = {};
// Generate one static DartType instance for all instantiable types.
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index cc4a18f..1b76c4e 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -134,7 +134,12 @@
}
single_root_scheme = "org-dartlang-sdk"
single_root_base = rebase_path("../../")
- libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json"
+ if (use_nnbd) {
+ libraries_specification_uri =
+ "org-dartlang-sdk:///sdk_nnbd/lib/libraries.json"
+ } else {
+ libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json"
+ }
outputs = [
"$root_out_dir/vm_platform" + output_postfix + ".dill",
"$root_out_dir/vm_outline" + output_postfix + ".dill",
@@ -148,7 +153,9 @@
"-Ddart.isVM=true",
]
if (use_nnbd) {
- args += [ "--enable-experiment=non-nullable" ]
+ # TODO(sigmund): reenable this flag once the CFE can build targets without
+ # issues.
+ # args += [ "--enable-experiment=non-nullable" ]
}
if (defined(invoker.exclude_source) && invoker.exclude_source) {
args += [ "--exclude-source" ]
diff --git a/runtime/vm/bitmap_test.cc b/runtime/vm/bitmap_test.cc
index 8447aab..e8f6418 100644
--- a/runtime/vm/bitmap_test.cc
+++ b/runtime/vm/bitmap_test.cc
@@ -56,8 +56,8 @@
EXPECT(it1.MoveNext());
EXPECT_EQ(kTestPcOffset, it1.pc_offset());
- EXPECT_EQ(kTestSpillSlotBitCount, it1.spill_slot_bit_count());
- EXPECT_EQ(1024, it1.length());
+ EXPECT_EQ(kTestSpillSlotBitCount, it1.SpillSlotBitCount());
+ EXPECT_EQ(1024, it1.Length());
value = true;
for (int32_t i = 0; i < 1024; i++) {
EXPECT_EQ(value, it1.IsObject(i));
@@ -88,8 +88,8 @@
EXPECT(it2.MoveNext());
EXPECT_EQ(kTestPcOffset, it2.pc_offset());
- EXPECT_EQ(kTestSpillSlotBitCount, it2.spill_slot_bit_count());
- EXPECT_EQ(2049, it2.length());
+ EXPECT_EQ(kTestSpillSlotBitCount, it2.SpillSlotBitCount());
+ EXPECT_EQ(2049, it2.Length());
for (int32_t i = 0; i <= 256; i++) {
EXPECT(!it2.IsObject(i));
}
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index f8030dc..4b667d2 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -23,7 +23,7 @@
// point.
static struct NativeEntries {
const char* name_;
- Dart_NativeFunction function_;
+ BootstrapNativeFunction function_;
int argument_count_;
} BootStrapEntries[] = {BOOTSTRAP_NATIVE_LIST(REGISTER_NATIVE_ENTRY)
#if !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 7fceaf7..233c978 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -485,7 +485,8 @@
static const uint8_t* Symbol(Dart_NativeFunction* nf);
#define DECLARE_BOOTSTRAP_NATIVE(name, ignored) \
- static void DN_##name(Dart_NativeArguments args);
+ static RawObject* DN_##name(Thread* thread, Zone* zone, \
+ NativeArguments* arguments);
BOOTSTRAP_NATIVE_LIST(DECLARE_BOOTSTRAP_NATIVE)
#if !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index b730cf6..f8ad310 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -383,14 +383,16 @@
!pending_arguments.IsSubvectorInstantiated(first_type_param,
num_type_params)) {
const TypeArguments& instantiated_arguments = TypeArguments::Handle(
- zone, arguments.InstantiateFrom(Object::null_type_arguments(),
+ zone, arguments.InstantiateFrom(NNBDMode::kLegacy,
+ Object::null_type_arguments(),
Object::null_type_arguments(),
kNoneFree, NULL, Heap::kNew));
const TypeArguments& instantiated_pending_arguments =
- TypeArguments::Handle(zone, pending_arguments.InstantiateFrom(
- Object::null_type_arguments(),
- Object::null_type_arguments(),
- kNoneFree, NULL, Heap::kNew));
+ TypeArguments::Handle(
+ zone, pending_arguments.InstantiateFrom(
+ NNBDMode::kLegacy, Object::null_type_arguments(),
+ Object::null_type_arguments(), kNoneFree, NULL,
+ Heap::kNew));
if (!instantiated_pending_arguments.IsSubvectorEquivalent(
instantiated_arguments, first_type_param, num_type_params)) {
const String& type_name = String::Handle(zone, type.Name());
@@ -619,9 +621,13 @@
arguments.SetTypeAt(i, super_type_arg);
continue;
}
+ // The nullability of the supertype should never be relevant.
+ // TODO(regis): Should we introduce a kIgnore mode in addition to
+ // the kLegacy mode of instantiation so that unnecessary cloning
+ // never occurs?
super_type_arg = super_type_arg.InstantiateFrom(
- arguments, Object::null_type_arguments(), kNoneFree,
- instantiation_trail, Heap::kOld);
+ NNBDMode::kLegacy, arguments, Object::null_type_arguments(),
+ kNoneFree, instantiation_trail, Heap::kOld);
if (super_type_arg.IsBeingFinalized()) {
// The super_type_arg was instantiated from a type being finalized.
// We need to finish finalizing its type arguments.
@@ -778,8 +784,8 @@
const TypeArguments& instantiator_type_arguments =
TypeArguments::Handle(zone, fun_type.arguments());
signature = signature.InstantiateSignatureFrom(
- instantiator_type_arguments, Object::null_type_arguments(),
- kNoneFree, Heap::kOld);
+ NNBDMode::kLegacy, instantiator_type_arguments,
+ Object::null_type_arguments(), kNoneFree, Heap::kOld);
// Note that if instantiator_type_arguments contains type parameters,
// as in F<K>, the signature is still uninstantiated (the typedef type
// parameters were substituted in the signature with typedef type
@@ -1631,6 +1637,7 @@
for (intptr_t i = 0; i < types.Length(); i++) {
type ^= types.At(i);
bool present = types_table.Insert(type);
+ // Two recursive types with different topology (and hashes) may be equal.
ASSERT(!present || type.IsRecursive());
}
object_store->set_canonical_types(types_table.Release());
@@ -1662,6 +1669,7 @@
for (intptr_t i = 0; i < typeargs.Length(); i++) {
typearg ^= typeargs.At(i);
bool present = typeargs_table.Insert(typearg);
+ // Two recursive types with different topology (and hashes) may be equal.
ASSERT(!present || typearg.IsRecursive());
}
object_store->set_canonical_type_arguments(typeargs_table.Release());
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index fa8108f..83d65f5 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -9,6 +9,7 @@
#include "vm/growable_array.h"
#include "vm/heap/heap.h"
#include "vm/object.h"
+#include "vm/object_graph.h"
#include "vm/raw_object.h"
#include "vm/visitor.h"
@@ -47,10 +48,10 @@
table_[kNeverCid] = vm_shared_class_table->SizeAt(kNeverCid);
}
#ifndef PRODUCT
- class_heap_stats_table_ = static_cast<ClassHeapStats*>(
- malloc(capacity_ * sizeof(ClassHeapStats))); // NOLINT
+ trace_allocation_table_ =
+ static_cast<uint8_t*>(malloc(capacity_ * sizeof(uint8_t))); // NOLINT
for (intptr_t i = 0; i < capacity_; i++) {
- class_heap_stats_table_[i].Initialize();
+ trace_allocation_table_[i] = 0;
}
#endif // !PRODUCT
}
@@ -60,14 +61,13 @@
delete old_tables_;
free(table_);
}
- NOT_IN_PRODUCT(free(class_heap_stats_table_));
+ NOT_IN_PRODUCT(free(trace_allocation_table_));
}
ClassTable::ClassTable(SharedClassTable* shared_class_table)
: top_(kNumPredefinedCids),
capacity_(0),
table_(NULL),
- old_tables_(new MallocGrowableArray<ClassAndSize*>()),
old_class_tables_(new MallocGrowableArray<RawClass**>()),
shared_class_table_(shared_class_table) {
if (Dart::vm_isolate() == NULL) {
@@ -100,33 +100,33 @@
: top_(original->top_),
capacity_(original->top_),
table_(original->table_),
- old_tables_(nullptr),
old_class_tables_(nullptr),
shared_class_table_(shared_class_table) {}
ClassTable::~ClassTable() {
- if (old_tables_ != nullptr || old_class_tables_ != nullptr) {
+ if (old_class_tables_ != nullptr) {
FreeOldTables();
- delete old_tables_;
delete old_class_tables_;
}
free(table_);
}
-void ClassTable::AddOldTable(ClassAndSize* old_table) {
+void ClassTable::AddOldTable(RawClass** old_class_table) {
ASSERT(Thread::Current()->IsMutatorThread());
- old_tables_->Add(old_table);
+ old_class_tables_->Add(old_class_table);
}
void ClassTable::FreeOldTables() {
- while (old_tables_->length() > 0) {
- free(old_tables_->RemoveLast());
- }
while (old_class_tables_->length() > 0) {
free(old_class_tables_->RemoveLast());
}
}
+void SharedClassTable::AddOldTable(intptr_t* old_table) {
+ ASSERT(Thread::Current()->IsMutatorThread());
+ old_tables_->Add(old_table);
+}
+
void SharedClassTable::FreeOldTables() {
while (old_tables_->length() > 0) {
free(old_tables_->RemoveLast());
@@ -254,21 +254,18 @@
memmove(new_table, table_, top_ * sizeof(intptr_t));
memset(new_table + top_, 0, (new_capacity - top_) * sizeof(intptr_t));
#ifndef PRODUCT
- auto new_stats_table = reinterpret_cast<ClassHeapStats*>(
- malloc(new_capacity * sizeof(ClassHeapStats)));
- for (intptr_t i = 0; i < capacity_; i++) {
- new_stats_table[i] = class_heap_stats_table_[i];
- }
- free(class_heap_stats_table_);
+ auto new_stats_table =
+ static_cast<uint8_t*>(realloc(trace_allocation_table_,
+ new_capacity * sizeof(uint8_t))); // NOLINT
#endif
for (intptr_t i = capacity_; i < new_capacity; i++) {
new_table[i] = 0;
- NOT_IN_PRODUCT(new_stats_table[i].Initialize());
+ NOT_IN_PRODUCT(new_stats_table[i] = 0);
}
capacity_ = new_capacity;
old_tables_->Add(table_);
table_ = new_table; // TODO(koda): This should use atomics.
- NOT_IN_PRODUCT(class_heap_stats_table_ = new_stats_table);
+ NOT_IN_PRODUCT(trace_allocation_table_ = new_stats_table);
}
void ClassTable::Unregister(intptr_t index) {
@@ -364,10 +361,6 @@
table_[index] = raw_cls;
}
-ClassAndSize::ClassAndSize(RawClass* clazz) : class_(clazz) {
- size_ = clazz == NULL ? 0 : Class::instance_size(clazz);
-}
-
#ifndef PRODUCT
void ClassTable::PrintToJSONObject(JSONObject* object) {
if (!FLAG_support_service) {
@@ -386,244 +379,14 @@
}
}
-void ClassHeapStats::Initialize() {
- pre_gc.Reset();
- post_gc.Reset();
- recent.Reset();
- accumulated.Reset();
- last_reset.Reset();
- promoted_count = 0;
- promoted_size = 0;
- state_ = 0;
- USE(align_);
-}
-
-void ClassHeapStats::ResetAtNewGC() {
- Verify();
- pre_gc.new_count = post_gc.new_count + recent.new_count;
- pre_gc.new_size = post_gc.new_size + recent.new_size;
- pre_gc.new_external_size =
- post_gc.new_external_size + recent.new_external_size;
- pre_gc.old_external_size =
- post_gc.old_external_size + recent.old_external_size;
- // Accumulate allocations.
- accumulated.new_count += recent.new_count - last_reset.new_count;
- accumulated.new_size += recent.new_size - last_reset.new_size;
- accumulated.new_external_size +=
- recent.new_external_size - last_reset.new_external_size;
- accumulated.old_external_size +=
- recent.old_external_size - last_reset.old_external_size;
- last_reset.ResetNew();
- post_gc.ResetNew();
- recent.ResetNew();
- old_pre_new_gc_count_ = recent.old_count;
- old_pre_new_gc_size_ = recent.old_size;
-}
-
-void ClassHeapStats::ResetAtOldGC() {
- Verify();
- pre_gc.old_count = post_gc.old_count + recent.old_count;
- pre_gc.old_size = post_gc.old_size + recent.old_size;
- pre_gc.old_external_size =
- post_gc.old_external_size + recent.old_external_size;
- pre_gc.new_external_size =
- post_gc.new_external_size + recent.new_external_size;
- // Accumulate allocations.
- accumulated.old_count += recent.old_count - last_reset.old_count;
- accumulated.old_size += recent.old_size - last_reset.old_size;
- accumulated.old_external_size +=
- recent.old_external_size - last_reset.old_external_size;
- accumulated.new_external_size +=
- recent.new_external_size - last_reset.new_external_size;
- last_reset.ResetOld();
- post_gc.ResetOld();
- recent.ResetOld();
-}
-
-void ClassHeapStats::Verify() {
- pre_gc.Verify();
- post_gc.Verify();
- recent.Verify();
- accumulated.Verify();
- last_reset.Verify();
-}
-
-void ClassHeapStats::UpdateSize(intptr_t instance_size) {
- pre_gc.UpdateSize(instance_size);
- post_gc.UpdateSize(instance_size);
- recent.UpdateSize(instance_size);
- accumulated.UpdateSize(instance_size);
- last_reset.UpdateSize(instance_size);
- promoted_size = promoted_count * instance_size;
- old_pre_new_gc_size_ = old_pre_new_gc_count_ * instance_size;
-}
-
-void ClassHeapStats::ResetAccumulator() {
- // Remember how much was allocated so we can subtract this from the result
- // when printing.
- last_reset.new_count = recent.new_count;
- last_reset.new_size = recent.new_size;
- last_reset.new_external_size = recent.new_external_size;
- last_reset.old_count = recent.old_count;
- last_reset.old_size = recent.old_size;
- last_reset.old_external_size = recent.old_external_size;
- accumulated.Reset();
-}
-
-void ClassHeapStats::UpdatePromotedAfterNewGC() {
- promoted_count = recent.old_count - old_pre_new_gc_count_;
- promoted_size = recent.old_size - old_pre_new_gc_size_;
-}
-
-void ClassHeapStats::PrintToJSONObject(const Class& cls,
- JSONObject* obj,
- bool internal) const {
- if (!FLAG_support_service) {
- return;
- }
- obj->AddProperty("type", "ClassHeapStats");
- obj->AddProperty("class", cls);
- int64_t accumulated_new =
- accumulated.new_count + recent.new_count - last_reset.new_count;
- int64_t accumulated_old =
- accumulated.old_count + recent.old_count - last_reset.old_count;
- int64_t accumulated_new_size =
- accumulated.new_size + accumulated.new_external_size + recent.new_size +
- recent.new_external_size - last_reset.new_size -
- last_reset.new_external_size;
- int64_t accumulated_old_size =
- accumulated.old_size + accumulated.old_external_size + recent.old_size +
- recent.old_external_size - last_reset.old_size -
- last_reset.old_external_size;
- int64_t instances_new = post_gc.new_count + recent.new_count;
- int64_t instances_old = post_gc.old_count + recent.old_count;
- int64_t live_after_gc_size_new = post_gc.new_size + post_gc.new_external_size;
- int64_t live_after_gc_size_old = post_gc.old_size + post_gc.old_external_size;
- int64_t allocated_since_gc_size_new =
- recent.new_size + recent.new_external_size;
- int64_t allocated_since_gc_size_old =
- recent.old_size + recent.old_external_size;
- int64_t bytes_current = live_after_gc_size_new + live_after_gc_size_old +
- allocated_since_gc_size_new +
- allocated_since_gc_size_old;
- if (internal) {
- {
- JSONArray new_stats(obj, "_new");
- new_stats.AddValue(pre_gc.new_count);
- new_stats.AddValue(pre_gc.new_size + pre_gc.new_external_size);
- new_stats.AddValue(post_gc.new_count);
- new_stats.AddValue64(live_after_gc_size_new);
- new_stats.AddValue(recent.new_count);
- new_stats.AddValue64(allocated_since_gc_size_new);
- new_stats.AddValue64(accumulated_new);
- new_stats.AddValue64(accumulated_new_size);
- }
- {
- JSONArray old_stats(obj, "_old");
- old_stats.AddValue(pre_gc.old_count);
- old_stats.AddValue(pre_gc.old_size + pre_gc.old_external_size);
- old_stats.AddValue(post_gc.old_count);
- old_stats.AddValue64(live_after_gc_size_old);
- old_stats.AddValue(recent.old_count);
- old_stats.AddValue64(allocated_since_gc_size_old);
- old_stats.AddValue64(accumulated_old);
- old_stats.AddValue64(accumulated_old_size);
- }
- obj->AddProperty("_promotedInstances", promoted_count);
- obj->AddProperty("_promotedBytes", promoted_size);
- }
- obj->AddProperty64("instancesAccumulated", accumulated_new + accumulated_old);
- obj->AddProperty64("accumulatedSize",
- accumulated_new_size + accumulated_old_size);
- obj->AddProperty64("instancesCurrent", instances_new + instances_old);
- obj->AddProperty64("bytesCurrent", bytes_current);
-}
-
-void SharedClassTable::UpdateAllocatedOldGC(intptr_t cid, intptr_t size) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- ASSERT(stats != NULL);
- ASSERT(size != 0);
- stats->recent.AddOldGC(size);
-}
-
-void SharedClassTable::UpdateAllocatedExternalNew(intptr_t cid, intptr_t size) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- ASSERT(stats != NULL);
- stats->recent.AddNewExternal(size);
-}
-
-void SharedClassTable::UpdateAllocatedExternalOld(intptr_t cid, intptr_t size) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- ASSERT(stats != NULL);
- stats->recent.AddOldExternal(size);
-}
-
bool SharedClassTable::ShouldUpdateSizeForClassId(intptr_t cid) {
return !RawObject::IsVariableSizeClassId(cid);
}
-ClassHeapStats* ClassTable::StatsWithUpdatedSize(intptr_t cid) {
- if (!HasValidClassAt(cid) || cid == kFreeListElement ||
- cid == kForwardingCorpse || cid == kSmiCid) {
- return NULL;
- }
- Class& cls = Class::Handle(At(cid));
- if (!(cls.is_finalized() || cls.is_prefinalized())) {
- // Not finalized.
- return NULL;
- }
- return shared_class_table_->StatsWithUpdatedSize(cid, cls.instance_size());
-}
-
-ClassHeapStats* SharedClassTable::StatsWithUpdatedSize(intptr_t cid,
- intptr_t size) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- if (ShouldUpdateSizeForClassId(cid)) {
- stats->UpdateSize(size);
- }
- stats->Verify();
- return stats;
-}
-
-void SharedClassTable::ResetCountersOld() {
- for (intptr_t i = 0; i < top_; i++) {
- class_heap_stats_table_[i].ResetAtOldGC();
- }
-}
-
-void SharedClassTable::ResetCountersNew() {
- for (intptr_t i = 0; i < top_; i++) {
- class_heap_stats_table_[i].ResetAtNewGC();
- }
-}
-
-void SharedClassTable::UpdatePromoted() {
- for (intptr_t i = 0; i < top_; i++) {
- class_heap_stats_table_[i].UpdatePromotedAfterNewGC();
- }
-}
-
intptr_t SharedClassTable::ClassOffsetFor(intptr_t cid) {
- return cid * sizeof(ClassHeapStats); // NOLINT
+ return cid * sizeof(uint8_t); // NOLINT
}
-intptr_t SharedClassTable::NewSpaceCounterOffsetFor(intptr_t cid) {
- const intptr_t class_offset = ClassOffsetFor(cid);
- const intptr_t count_field_offset =
- ClassHeapStats::allocated_since_gc_new_space_offset();
- return class_offset + count_field_offset;
-}
-
-intptr_t SharedClassTable::StateOffsetFor(intptr_t cid) {
- return ClassOffsetFor(cid) + ClassHeapStats::state_offset();
-}
-
-intptr_t SharedClassTable::NewSpaceSizeOffsetFor(intptr_t cid) {
- const uword class_offset = ClassOffsetFor(cid);
- const uword size_field_offset =
- ClassHeapStats::allocated_size_since_gc_new_space_offset();
- return class_offset + size_field_offset;
-}
void ClassTable::AllocationProfilePrintJSON(JSONStream* stream, bool internal) {
if (!FLAG_support_service) {
@@ -656,69 +419,50 @@
{ heap->PrintMemoryUsageJSON(&memory); }
}
+ Thread* thread = Thread::Current();
+ CountObjectsVisitor visitor(thread, NumCids());
+ {
+ HeapIterationScope iter(thread);
+ iter.IterateObjects(&visitor);
+ isolate->VisitWeakPersistentHandles(&visitor);
+ }
+
{
JSONArray arr(&obj, "members");
Class& cls = Class::Handle();
- for (intptr_t i = 1; i < top_; i++) {
- const ClassHeapStats* stats = StatsWithUpdatedSize(i);
- if (stats != NULL) {
- JSONObject obj(&arr);
- cls = At(i);
- stats->PrintToJSONObject(cls, &obj, internal);
+ for (intptr_t i = 3; i < top_; i++) {
+ if (!HasValidClassAt(i)) continue;
+
+ cls = At(i);
+ if (cls.IsNull()) continue;
+
+ JSONObject obj(&arr);
+ obj.AddProperty("type", "ClassHeapStats");
+ obj.AddProperty("class", cls);
+ intptr_t count = visitor.new_count_[i] + visitor.old_count_[i];
+ intptr_t size = visitor.new_size_[i] + visitor.old_size_[i];
+ obj.AddProperty64("instancesAccumulated", count);
+ obj.AddProperty64("accumulatedSize", size);
+ obj.AddProperty64("instancesCurrent", count);
+ obj.AddProperty64("bytesCurrent", size);
+
+ if (internal) {
+ {
+ JSONArray new_stats(&obj, "_new");
+ new_stats.AddValue(visitor.new_count_[i]);
+ new_stats.AddValue(visitor.new_size_[i]);
+ new_stats.AddValue(visitor.new_external_size_[i]);
+ }
+ {
+ JSONArray old_stats(&obj, "_old");
+ old_stats.AddValue(visitor.old_count_[i]);
+ old_stats.AddValue(visitor.old_size_[i]);
+ old_stats.AddValue(visitor.old_external_size_[i]);
+ }
}
}
}
}
-
-void SharedClassTable::ResetAllocationAccumulators() {
- for (intptr_t i = 1; i < top_; i++) {
- if (HasValidClassAt(i)) {
- const intptr_t size = table_[i];
- ClassHeapStats* stats = StatsWithUpdatedSize(i, size);
- if (stats != NULL) {
- stats->ResetAccumulator();
- }
- }
- }
-}
-
-void SharedClassTable::UpdateLiveOld(intptr_t cid,
- intptr_t size,
- intptr_t count) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- ASSERT(stats != NULL);
- ASSERT(size >= 0);
- ASSERT(count >= 0);
- stats->post_gc.AddOld(size, count);
-}
-
-void SharedClassTable::UpdateLiveNew(intptr_t cid, intptr_t size) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- ASSERT(stats != NULL);
- ASSERT(size >= 0);
- stats->post_gc.AddNew(size);
-}
-
-void SharedClassTable::UpdateLiveNewGC(intptr_t cid, intptr_t size) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- ASSERT(stats != NULL);
- ASSERT(size >= 0);
- stats->post_gc.AddNewGC(size);
-}
-
-void SharedClassTable::UpdateLiveOldExternal(intptr_t cid, intptr_t size) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- ASSERT(stats != NULL);
- ASSERT(size >= 0);
- stats->post_gc.AddOldExternal(size);
-}
-
-void SharedClassTable::UpdateLiveNewExternal(intptr_t cid, intptr_t size) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- ASSERT(stats != NULL);
- ASSERT(size >= 0);
- stats->post_gc.AddNewExternal(size);
-}
#endif // !PRODUCT
} // namespace dart
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 5edf9c4..fb13d2e 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -15,10 +15,11 @@
namespace dart {
class Class;
-class ClassStats;
class ClassTable;
class Isolate;
class IsolateGroup;
+class IsolateGroupReloadContext;
+class IsolateReloadContext;
class JSONArray;
class JSONObject;
class JSONStream;
@@ -27,164 +28,6 @@
class ObjectPointerVisitor;
class RawClass;
-class ClassAndSize {
- public:
- ClassAndSize() : class_(NULL), size_(0) {}
- explicit ClassAndSize(RawClass* clazz);
- ClassAndSize(RawClass* clazz, intptr_t size) : class_(clazz), size_(size) {}
- RawClass* get_raw_class() const { return class_; }
- intptr_t size() const { return size_; }
-
- private:
- RawClass* class_;
- intptr_t size_;
-
- friend class ClassTable;
- friend class IsolateReloadContext; // For VisitObjectPointers.
-};
-
-#ifndef PRODUCT
-template <typename T>
-class AllocStats {
- public:
- RelaxedAtomic<T> new_count;
- RelaxedAtomic<T> new_size;
- RelaxedAtomic<T> new_external_size;
- RelaxedAtomic<T> old_count;
- RelaxedAtomic<T> old_size;
- RelaxedAtomic<T> old_external_size;
-
- void ResetNew() {
- new_count = 0;
- new_size = 0;
- new_external_size = 0;
- old_external_size = 0;
- }
-
- void AddNew(T size) {
- new_count.fetch_add(1);
- new_size.fetch_add(size);
- }
-
- void AddNewGC(T size) {
- new_count.fetch_add(1);
- new_size.fetch_add(size);
- }
-
- void AddNewExternal(T size) { new_external_size.fetch_add(size); }
-
- void ResetOld() {
- old_count = 0;
- old_size = 0;
- old_external_size = 0;
- new_external_size = 0;
- }
-
- void AddOld(T size, T count = 1) {
- old_count.fetch_add(count);
- old_size.fetch_add(size);
- }
-
- void AddOldGC(T size, T count = 1) {
- old_count.fetch_add(count);
- old_size.fetch_add(size);
- }
-
- void AddOldExternal(T size) { old_external_size.fetch_add(size); }
-
- void Reset() {
- ResetNew();
- ResetOld();
- }
-
- // For classes with fixed instance size we do not emit code to update
- // the size statistics. Update them by calling this method.
- void UpdateSize(intptr_t instance_size) {
- ASSERT(instance_size > 0);
- old_size = old_count * instance_size;
- new_size = new_count * instance_size;
- }
-
- void Verify() {
- ASSERT(new_count >= 0);
- ASSERT(new_size >= 0);
- ASSERT(new_external_size >= 0);
- ASSERT(old_count >= 0);
- ASSERT(old_size >= 0);
- ASSERT(old_external_size >= 0);
- }
-};
-
-class ClassHeapStats {
- public:
- // Snapshot before GC.
- AllocStats<intptr_t> pre_gc;
- // Live after GC.
- AllocStats<intptr_t> post_gc;
- // Allocations since the last GC.
- AllocStats<intptr_t> recent;
- // Accumulated (across GC) allocations .
- AllocStats<int64_t> accumulated;
- // Snapshot of recent at the time of the last reset.
- AllocStats<intptr_t> last_reset;
- // Promoted from new to old by last new GC.
- intptr_t promoted_count;
- intptr_t promoted_size;
-
- static intptr_t allocated_since_gc_new_space_offset() {
- return OFFSET_OF(ClassHeapStats, recent) +
- OFFSET_OF(AllocStats<intptr_t>, new_count);
- }
- static intptr_t allocated_since_gc_old_space_offset() {
- return OFFSET_OF(ClassHeapStats, recent) +
- OFFSET_OF(AllocStats<intptr_t>, old_count);
- }
- static intptr_t allocated_size_since_gc_new_space_offset() {
- return OFFSET_OF(ClassHeapStats, recent) +
- OFFSET_OF(AllocStats<intptr_t>, new_size);
- }
- static intptr_t allocated_size_since_gc_old_space_offset() {
- return OFFSET_OF(ClassHeapStats, recent) +
- OFFSET_OF(AllocStats<intptr_t>, old_size);
- }
- static intptr_t state_offset() { return OFFSET_OF(ClassHeapStats, state_); }
- static intptr_t TraceAllocationMask() { return (1 << kTraceAllocationBit); }
-
- void Initialize();
- void ResetAtNewGC();
- void ResetAtOldGC();
- void ResetAccumulator();
- void UpdatePromotedAfterNewGC();
- void UpdateSize(intptr_t instance_size);
-#ifndef PRODUCT
- void PrintToJSONObject(const Class& cls,
- JSONObject* obj,
- bool internal) const;
-#endif
- void Verify();
-
- bool trace_allocation() const { return TraceAllocationBit::decode(state_); }
-
- void set_trace_allocation(bool trace_allocation) {
- state_ = TraceAllocationBit::update(trace_allocation, state_);
- }
-
- private:
- enum StateBits {
- kTraceAllocationBit = 0,
- };
-
- class TraceAllocationBit
- : public BitField<intptr_t, bool, kTraceAllocationBit, 1> {};
-
- // Recent old at start of last new GC (used to compute promoted_*).
- intptr_t old_pre_new_gc_count_;
- intptr_t old_pre_new_gc_size_;
- intptr_t state_;
- intptr_t align_; // Make SIMARM and ARM agree on the size of ClassHeapStats.
-};
-#endif // !PRODUCT
-
// Registry of all known classes and their sizes.
//
// The GC will only need the information in this shared class table to scan
@@ -225,44 +68,60 @@
top_ = num_cids;
}
- // Called whenever a old GC occurs.
- void ResetCountersOld();
- // Called whenever a new GC occurs.
- void ResetCountersNew();
- // Called immediately after a new GC.
- void UpdatePromoted();
-
#if !defined(PRODUCT)
- // Called whenever a class is allocated in the runtime.
- void UpdateAllocatedNew(intptr_t cid, intptr_t size) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- ASSERT(stats != NULL);
- ASSERT(size != 0);
- stats->recent.AddNew(size);
- }
- void UpdateAllocatedOld(intptr_t cid, intptr_t size) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- ASSERT(stats != NULL);
- ASSERT(size != 0);
- stats->recent.AddOld(size);
- }
- void UpdateAllocatedOldGC(intptr_t cid, intptr_t size);
- void UpdateAllocatedExternalNew(intptr_t cid, intptr_t size);
- void UpdateAllocatedExternalOld(intptr_t cid, intptr_t size);
-
- void ResetAllocationAccumulators();
-
void SetTraceAllocationFor(intptr_t cid, bool trace) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- stats->set_trace_allocation(trace);
+ ASSERT(cid > 0);
+ ASSERT(cid < top_);
+ trace_allocation_table_[cid] = trace ? 1 : 0;
}
bool TraceAllocationFor(intptr_t cid) {
- ClassHeapStats* stats = PreliminaryStatsAt(cid);
- return stats->trace_allocation();
+ ASSERT(cid > 0);
+ ASSERT(cid < top_);
+ return trace_allocation_table_[cid] != 0;
+ }
+#endif // !defined(PRODUCT)
+
+ void CopyBeforeHotReload(intptr_t** copy, intptr_t* copy_num_cids) {
+ // The [IsolateGroupReloadContext] will need to maintain a copy of the old
+ // class table until instances have been morphed.
+ const intptr_t num_cids = NumCids();
+ const intptr_t bytes = sizeof(intptr_t) * num_cids;
+ auto size_table = static_cast<intptr_t*>(malloc(bytes));
+ memmove(size_table, table_, sizeof(intptr_t) * num_cids);
+ *copy_num_cids = num_cids;
+ *copy = size_table;
}
- ClassHeapStats* StatsWithUpdatedSize(intptr_t cid, intptr_t size);
-#endif // !defined(PRODUCT)
+ void ResetBeforeHotReload() {
+ // The [IsolateReloadContext] is now source-of-truth for GC.
+ memset(table_, 0, sizeof(intptr_t) * top_);
+ }
+
+ void ResetAfterHotReload(intptr_t* old_table,
+ intptr_t num_old_cids,
+ bool is_rollback) {
+ // The [IsolateReloadContext] is no longer source-of-truth for GC after we
+ // return, so we restore size information for all classes.
+ if (is_rollback) {
+ SetNumCids(num_old_cids);
+ memmove(table_, old_table, sizeof(intptr_t) * num_old_cids);
+ }
+
+ // Can't free this table immediately as another thread (e.g., concurrent
+ // marker or sweeper) may be between loading the table pointer and loading
+ // the table element. The table will be freed at the next major GC or
+ // isolate shutdown.
+ AddOldTable(old_table);
+ }
+
+ // Deallocates table copies. Do not call during concurrent access to table.
+ void FreeOldTables();
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ bool IsReloading() const { return reload_context_ != nullptr; }
+
+ IsolateGroupReloadContext* reload_context() { return reload_context_; }
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
// Returns the newly allocated cid.
//
@@ -273,27 +132,16 @@
void Remap(intptr_t* old_to_new_cids);
- void FreeOldTables();
-
// Used by the generated code.
#ifndef PRODUCT
static intptr_t class_heap_stats_table_offset() {
- return OFFSET_OF(SharedClassTable, class_heap_stats_table_);
+ return OFFSET_OF(SharedClassTable, trace_allocation_table_);
}
#endif
// Used by the generated code.
static intptr_t ClassOffsetFor(intptr_t cid);
- // Used by the generated code.
- static intptr_t NewSpaceCounterOffsetFor(intptr_t cid);
-
- // Used by the generated code.
- static intptr_t StateOffsetFor(intptr_t cid);
-
- // Used by the generated code.
- static intptr_t NewSpaceSizeOffsetFor(intptr_t cid);
-
static const int kInitialCapacity = 512;
static const int kCapacityIncrement = 256;
@@ -303,27 +151,15 @@
friend class MarkingWeakVisitor;
friend class Scavenger;
friend class ScavengerWeakVisitor;
- friend class ClassHeapStatsTestHelper;
- friend class HeapTestsHelper;
static bool ShouldUpdateSizeForClassId(intptr_t cid);
#ifndef PRODUCT
- // May not have updated size for variable size classes.
- ClassHeapStats* PreliminaryStatsAt(intptr_t cid) {
- ASSERT(cid > 0);
- ASSERT(cid < top_);
- return &class_heap_stats_table_[cid];
- }
- void UpdateLiveOld(intptr_t cid, intptr_t size, intptr_t count = 1);
- void UpdateLiveNew(intptr_t cid, intptr_t size);
- void UpdateLiveNewGC(intptr_t cid, intptr_t size);
- void UpdateLiveOldExternal(intptr_t cid, intptr_t size);
- void UpdateLiveNewExternal(intptr_t cid, intptr_t size);
-
- ClassHeapStats* class_heap_stats_table_ = nullptr;
+ uint8_t* trace_allocation_table_ = nullptr;
#endif // !PRODUCT
+ void AddOldTable(intptr_t* old_table);
+
void Grow(intptr_t new_capacity);
intptr_t top_;
@@ -333,6 +169,8 @@
intptr_t* table_; // Maps the cid to the instance size.
MallocGrowableArray<intptr_t*>* old_tables_;
+ IsolateGroupReloadContext* reload_context_ = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(SharedClassTable);
};
@@ -347,44 +185,33 @@
SharedClassTable* shared_class_table() const { return shared_class_table_; }
- void CopyBeforeHotReload(ClassAndSize** copy, intptr_t* copy_num_cids) {
+ void CopyBeforeHotReload(RawClass*** copy, intptr_t* copy_num_cids) {
// The [IsolateReloadContext] will need to maintain a copy of the old class
// table until instances have been morphed.
const intptr_t num_cids = NumCids();
- const intptr_t bytes = sizeof(ClassAndSize) * num_cids;
- auto class_and_size = static_cast<ClassAndSize*>(malloc(bytes));
- for (intptr_t i = 0; i < num_cids; ++i) {
- class_and_size[i] =
- ClassAndSize(table_[i], shared_class_table_->table_[i]);
- }
+ const intptr_t bytes = sizeof(RawClass*) * num_cids;
+ auto class_table = static_cast<RawClass**>(malloc(bytes));
+ memmove(class_table, table_, sizeof(RawClass*) * num_cids);
*copy_num_cids = num_cids;
- *copy = class_and_size;
+ *copy = class_table;
}
void ResetBeforeHotReload() {
- // The [IsolateReloadContext] is now source-of-truth for GC.
- //
- // Though we cannot clear out the class pointers, because a hot-reload
+ // We cannot clear out the class pointers, because a hot-reload
// contains only a diff: If e.g. a class included in the hot-reload has a
// super class not included in the diff, it will look up in this class table
// to find the super class (e.g. `cls.SuperClass` will cause us to come
// here).
- for (intptr_t i = 0; i < top_; ++i) {
- shared_class_table_->table_[i] = 0;
- }
}
- void ResetAfterHotReload(ClassAndSize* old_table,
+ void ResetAfterHotReload(RawClass** old_table,
intptr_t num_old_cids,
bool is_rollback) {
// The [IsolateReloadContext] is no longer source-of-truth for GC after we
// return, so we restore size information for all classes.
if (is_rollback) {
SetNumCids(num_old_cids);
- for (intptr_t i = 0; i < num_old_cids; ++i) {
- shared_class_table_->table_[i] = old_table[i].size_;
- table_[i] = old_table[i].class_;
- }
+ memmove(table_, old_table, sizeof(RawClass*) * num_old_cids);
} else {
CopySizesFromClassObjects();
}
@@ -458,20 +285,17 @@
struct ArrayLayout {
static intptr_t elements_start_offset() { return 0; }
- static constexpr intptr_t kElementSize = sizeof(ClassHeapStats);
+ static constexpr intptr_t kElementSize = sizeof(uint8_t);
};
#endif
#ifndef PRODUCT
- ClassHeapStats* StatsWithUpdatedSize(intptr_t cid);
-
void AllocationProfilePrintJSON(JSONStream* stream, bool internal);
void PrintToJSONObject(JSONObject* object);
#endif // !PRODUCT
- void AddOldTable(ClassAndSize* old_table);
// Deallocates table copies. Do not call during concurrent access to table.
void FreeOldTables();
@@ -480,19 +304,19 @@
friend class MarkingWeakVisitor;
friend class Scavenger;
friend class ScavengerWeakVisitor;
- friend class ClassHeapStatsTestHelper;
- friend class HeapTestsHelper;
static const int kInitialCapacity = SharedClassTable::kInitialCapacity;
static const int kCapacityIncrement = SharedClassTable::kCapacityIncrement;
+ void AddOldTable(RawClass** old_table);
+
void Grow(intptr_t index);
intptr_t top_;
intptr_t capacity_;
- // Copy-on-write is used for table_, with old copies stored in old_tables_.
+ // Copy-on-write is used for table_, with old copies stored in
+ // old_class_tables_.
RawClass** table_;
- MallocGrowableArray<ClassAndSize*>* old_tables_;
MallocGrowableArray<RawClass**>* old_class_tables_;
SharedClassTable* shared_class_table_;
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 6796fb5..1027fe6 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -9,9 +9,12 @@
#include "vm/bss_relocs.h"
#include "vm/class_id.h"
#include "vm/code_observers.h"
+#include "vm/compiler/assembler/disassembler.h"
#include "vm/compiler/backend/code_statistics.h"
+#include "vm/compiler/backend/il_printer.h"
#include "vm/compiler/relocation.h"
#include "vm/dart.h"
+#include "vm/flag_list.h"
#include "vm/heap/heap.h"
#include "vm/image_snapshot.h"
#include "vm/native_entry.h"
@@ -1373,11 +1376,7 @@
s->Push(code->ptr()->owner_);
s->Push(code->ptr()->exception_handlers_);
s->Push(code->ptr()->pc_descriptors_);
-#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
- s->Push(code->ptr()->catch_entry_.catch_entry_moves_maps_);
-#else
- s->Push(code->ptr()->catch_entry_.variables_);
-#endif
+ s->Push(code->ptr()->catch_entry_);
s->Push(code->ptr()->compressed_stackmaps_);
if (!FLAG_dwarf_stack_traces) {
s->Push(code->ptr()->inlined_id_to_function_);
@@ -1387,7 +1386,12 @@
s->Push(code->ptr()->deopt_info_array_);
s->Push(code->ptr()->static_calls_target_table_);
}
- NOT_IN_PRODUCT(s->Push(code->ptr()->return_address_metadata_));
+#if !defined(PRODUCT)
+ s->Push(code->ptr()->return_address_metadata_);
+ if (FLAG_code_comments) {
+ s->Push(code->ptr()->comments_);
+ }
+#endif
}
void WriteAlloc(Serializer* s) {
@@ -1431,11 +1435,7 @@
WriteField(code, owner_);
WriteField(code, exception_handlers_);
WriteField(code, pc_descriptors_);
-#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
- WriteField(code, catch_entry_.catch_entry_moves_maps_);
-#else
- WriteField(code, catch_entry_.variables_);
-#endif
+ WriteField(code, catch_entry_);
WriteField(code, compressed_stackmaps_);
if (FLAG_dwarf_stack_traces) {
WriteFieldValue(inlined_id_to_function_, Array::null());
@@ -1448,8 +1448,12 @@
WriteField(code, deopt_info_array_);
WriteField(code, static_calls_target_table_);
}
- NOT_IN_PRODUCT(WriteField(code, return_address_metadata_));
-
+#if !defined(PRODUCT)
+ WriteField(code, return_address_metadata_);
+ if (FLAG_code_comments) {
+ WriteField(code, comments_);
+ }
+#endif
s->Write<int32_t>(code->ptr()->state_bits_);
}
}
@@ -1510,13 +1514,7 @@
RawInstructions* instr = d->ReadInstructions();
- code->ptr()->entry_point_ = Instructions::EntryPoint(instr);
- code->ptr()->monomorphic_entry_point_ =
- Instructions::MonomorphicEntryPoint(instr);
- code->ptr()->unchecked_entry_point_ =
- Instructions::UncheckedEntryPoint(instr);
- code->ptr()->monomorphic_unchecked_entry_point_ =
- Instructions::MonomorphicUncheckedEntryPoint(instr);
+ Code::InitializeCachedEntryPointsFrom(code, instr);
NOT_IN_PRECOMPILED(code->ptr()->active_instructions_ = instr);
code->ptr()->instructions_ = instr;
@@ -1524,11 +1522,7 @@
if (d->kind() == Snapshot::kFullJIT) {
RawInstructions* instr = d->ReadInstructions();
code->ptr()->active_instructions_ = instr;
- code->ptr()->entry_point_ = Instructions::EntryPoint(instr);
- code->ptr()->monomorphic_entry_point_ =
- Instructions::MonomorphicEntryPoint(instr);
- code->ptr()->unchecked_entry_point_ =
- Instructions::UncheckedEntryPoint(instr);
+ Code::InitializeCachedEntryPointsFrom(code, instr);
}
#endif // !DART_PRECOMPILED_RUNTIME
@@ -1539,13 +1533,7 @@
reinterpret_cast<RawExceptionHandlers*>(d->ReadRef());
code->ptr()->pc_descriptors_ =
reinterpret_cast<RawPcDescriptors*>(d->ReadRef());
-#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
- code->ptr()->catch_entry_.catch_entry_moves_maps_ =
- reinterpret_cast<RawTypedData*>(d->ReadRef());
-#else
- code->ptr()->catch_entry_.variables_ =
- reinterpret_cast<RawSmi*>(d->ReadRef());
-#endif
+ code->ptr()->catch_entry_ = d->ReadRef();
code->ptr()->compressed_stackmaps_ =
reinterpret_cast<RawCompressedStackMaps*>(d->ReadRef());
code->ptr()->inlined_id_to_function_ =
@@ -1565,7 +1553,9 @@
#if !defined(PRODUCT)
code->ptr()->return_address_metadata_ = d->ReadRef();
code->ptr()->var_descriptors_ = LocalVarDescriptors::null();
- code->ptr()->comments_ = Array::null();
+ code->ptr()->comments_ = FLAG_code_comments
+ ? reinterpret_cast<RawArray*>(d->ReadRef())
+ : Array::null();
code->ptr()->compile_timestamp_ = 0;
#endif
@@ -1573,13 +1563,31 @@
}
}
-#if !(defined(DART_PRECOMPILED_RUNTIME) || defined(PRODUCT))
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
- if (!CodeObservers::AreActive()) return;
+#if !defined(PRODUCT)
+ if (!CodeObservers::AreActive() && !FLAG_support_disassembler) return;
+#endif
Code& code = Code::Handle(zone);
+ Object& owner = Object::Handle(zone);
for (intptr_t id = start_index_; id < stop_index_; id++) {
code ^= refs.At(id);
- Code::NotifyCodeObservers(code, code.is_optimized());
+#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(PRODUCT)
+ if (CodeObservers::AreActive()) {
+ Code::NotifyCodeObservers(code, code.is_optimized());
+ }
+#endif
+ owner = code.owner();
+ if (owner.IsFunction()) {
+ if ((FLAG_disassemble ||
+ (code.is_optimized() && FLAG_disassemble_optimized)) &&
+ FlowGraphPrinter::ShouldPrint(Function::Cast(owner))) {
+ Disassembler::DisassembleCode(Function::Cast(owner), code,
+ code.is_optimized());
+ }
+ } else if (FLAG_disassemble_stubs) {
+ Disassembler::DisassembleStub(code.Name(), code);
+ }
}
}
#endif // !DART_PRECOMPILED_RUNTIME
diff --git a/runtime/vm/code_comments.cc b/runtime/vm/code_comments.cc
index b4a8e03..74f8458 100644
--- a/runtime/vm/code_comments.cc
+++ b/runtime/vm/code_comments.cc
@@ -6,7 +6,9 @@
namespace dart {
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(PRODUCT)
+#if !defined(DART_PRECOMPILED_RUNTIME) && \
+ (!defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER))
+
const Code::Comments& CreateCommentsFrom(compiler::Assembler* assembler) {
const auto& comments = assembler->comments();
Code::Comments& result = Code::Comments::New(comments.length());
@@ -18,6 +20,8 @@
return result;
}
-#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(PRODUCT)
+
+#endif // !defined(DART_PRECOMPILED_RUNTIME) && \
+ // (!defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER))
} // namespace dart
diff --git a/runtime/vm/code_comments.h b/runtime/vm/code_comments.h
index d7d1480..9c86524 100644
--- a/runtime/vm/code_comments.h
+++ b/runtime/vm/code_comments.h
@@ -11,7 +11,8 @@
namespace dart {
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(PRODUCT)
+#if !defined(DART_PRECOMPILED_RUNTIME) && \
+ (!defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER))
class CodeCommentsWrapper final : public CodeComments {
public:
@@ -36,7 +37,8 @@
const Code::Comments& CreateCommentsFrom(compiler::Assembler* assembler);
-#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(PRODUCT)
+#endif // !defined(DART_PRECOMPILED_RUNTIME) && \
+ // (!defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER))
} // namespace dart
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index ee5662a..2ec7c2e 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -13,19 +13,26 @@
intptr_t pc_offset,
intptr_t deopt_id,
TokenPosition token_pos,
- intptr_t try_index) {
+ intptr_t try_index,
+ intptr_t yield_index) {
+ // yield index 0 is reserved for normal entry.
+ RELEASE_ASSERT(yield_index != 0);
+
ASSERT((kind == RawPcDescriptors::kRuntimeCall) ||
(kind == RawPcDescriptors::kBSSRelocation) ||
- (kind == RawPcDescriptors::kOther) || (deopt_id != DeoptId::kNone));
+ (kind == RawPcDescriptors::kOther) ||
+ (yield_index != RawPcDescriptors::kInvalidYieldIndex) ||
+ (deopt_id != DeoptId::kNone));
- // When precompiling, we only use pc descriptors for exceptions and
- // relocations.
+ // When precompiling, we only use pc descriptors for exceptions,
+ // relocations and yield indices.
if (!FLAG_precompiled_mode || try_index != -1 ||
+ yield_index != RawPcDescriptors::kInvalidYieldIndex ||
kind == RawPcDescriptors::kBSSRelocation) {
- int32_t merged_kind_try =
- RawPcDescriptors::MergedKindTry::Encode(kind, try_index);
+ const int32_t kind_and_metadata =
+ RawPcDescriptors::KindAndMetadata::Encode(kind, try_index, yield_index);
- PcDescriptors::EncodeInteger(&encoded_data_, merged_kind_try);
+ PcDescriptors::EncodeInteger(&encoded_data_, kind_and_metadata);
PcDescriptors::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset);
prev_pc_offset = pc_offset;
@@ -47,7 +54,8 @@
}
// Encode unsigned integer |value| in LEB128 format and store into |data|.
-static void EncodeLEB128(GrowableArray<uint8_t>* data, uintptr_t value) {
+void CompressedStackMapsBuilder::EncodeLEB128(GrowableArray<uint8_t>* data,
+ uintptr_t value) {
while (true) {
uint8_t part = value & 0x7f;
value >>= 7;
@@ -74,19 +82,20 @@
RawCompressedStackMaps* CompressedStackMapsBuilder::Finalize() const {
if (encoded_bytes_.length() == 0) return CompressedStackMaps::null();
- return CompressedStackMaps::New(encoded_bytes_);
+ return CompressedStackMaps::NewInlined(encoded_bytes_);
}
-// Decode unsigned integer in LEB128 format from |data| and update |byte_index|.
-static uintptr_t DecodeLEB128(const uint8_t* data,
- const intptr_t data_length,
- intptr_t* byte_index) {
- ASSERT(*byte_index < data_length);
+// Decode unsigned integer in LEB128 format from the payload of |maps| and
+// update |byte_index|.
+uintptr_t CompressedStackMapsIterator::DecodeLEB128(
+ const CompressedStackMaps& maps,
+ uintptr_t* byte_index) {
uword shift = 0;
uintptr_t value = 0;
uint8_t part = 0;
do {
- part = data[(*byte_index)++];
+ ASSERT(*byte_index < maps.payload_size());
+ part = maps.PayloadByte((*byte_index)++);
value |= static_cast<uintptr_t>(part & 0x7f) << shift;
shift += 7;
} while ((part & 0x80) != 0);
@@ -97,51 +106,85 @@
bool CompressedStackMapsIterator::MoveNext() {
// Empty CompressedStackMaps are represented as null values.
if (maps_.IsNull() || next_offset_ >= maps_.payload_size()) return false;
- intptr_t offset = next_offset_;
+ uintptr_t offset = next_offset_;
- // We decode three LEB128 encoded integers after this, so there should be
- // at least three bytes remaining in the payload.
- ASSERT(offset <= maps_.payload_size() - 3);
- auto const pc_delta =
- DecodeLEB128(maps_.Payload(), maps_.payload_size(), &offset);
- ASSERT(pc_delta <= kIntptrMax);
-
- ASSERT(offset <= maps_.payload_size() - 2);
- auto const spill_slot_bit_count =
- DecodeLEB128(maps_.Payload(), maps_.payload_size(), &offset);
- ASSERT(spill_slot_bit_count <= kIntptrMax);
-
- ASSERT(offset <= maps_.payload_size() - 1);
- auto const non_spill_slot_bit_count =
- DecodeLEB128(maps_.Payload(), maps_.payload_size(), &offset);
- ASSERT(non_spill_slot_bit_count <= kIntptrMax);
-
- const auto stackmap_bits = spill_slot_bit_count + non_spill_slot_bit_count;
- const intptr_t stackmap_size =
- Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
- const intptr_t space_remaining = maps_.payload_size() - offset;
- if (stackmap_size > space_remaining) return false;
-
- // Now that the current entry has been completely decoded without errors, set
- // the fields appropriately.
+ auto const pc_delta = DecodeLEB128(maps_, &offset);
ASSERT(pc_delta <= (kMaxUint32 - current_pc_offset_));
current_pc_offset_ += pc_delta;
- current_spill_slot_bit_count_ = spill_slot_bit_count;
- current_non_spill_slot_bit_count_ = non_spill_slot_bit_count;
- current_bits_offset_ = offset;
- next_offset_ = offset + stackmap_size;
+ // Table-using CSMs have a table offset after the PC offset delta, whereas
+ // the post-delta part of inlined entries has the same information as
+ // global table entries.
+ if (maps_.UsesGlobalTable()) {
+ current_global_table_offset_ = DecodeLEB128(maps_, &offset);
+ ASSERT(current_global_table_offset_ < bits_container_.payload_size());
+
+ // Since generally we only use entries in the GC and the GC only needs
+ // the rest of the entry information if the PC offset matches, we lazily
+ // load and cache the information stored in the global object when it is
+ // actually requested.
+ current_spill_slot_bit_count_ = -1;
+ current_non_spill_slot_bit_count_ = -1;
+ current_bits_offset_ = -1;
+ } else {
+ current_spill_slot_bit_count_ = DecodeLEB128(maps_, &offset);
+ ASSERT(current_spill_slot_bit_count_ >= 0);
+
+ current_non_spill_slot_bit_count_ = DecodeLEB128(maps_, &offset);
+ ASSERT(current_non_spill_slot_bit_count_ >= 0);
+
+ const auto stackmap_bits =
+ current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
+ const uintptr_t stackmap_size =
+ Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
+ ASSERT(stackmap_size <= (maps_.payload_size() - offset));
+
+ current_bits_offset_ = offset;
+ offset += stackmap_size;
+ }
+
+ next_offset_ = offset;
return true;
}
-bool CompressedStackMapsIterator::IsObject(intptr_t bit_index) const {
- ASSERT(HasLoadedEntry());
- ASSERT(bit_index >= 0 && bit_index < length());
+intptr_t CompressedStackMapsIterator::Length() {
+ EnsureFullyLoadedEntry();
+ return current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
+}
+intptr_t CompressedStackMapsIterator::SpillSlotBitCount() {
+ EnsureFullyLoadedEntry();
+ return current_spill_slot_bit_count_;
+}
+
+bool CompressedStackMapsIterator::IsObject(intptr_t bit_index) {
+ EnsureFullyLoadedEntry();
+ ASSERT(!bits_container_.IsNull());
+ ASSERT(bit_index >= 0 && bit_index < Length());
const intptr_t byte_index = bit_index >> kBitsPerByteLog2;
const intptr_t bit_remainder = bit_index & (kBitsPerByte - 1);
uint8_t byte_mask = 1U << bit_remainder;
- uint8_t byte = maps_.Payload()[current_bits_offset_ + byte_index];
- return (byte & byte_mask) != 0;
+ const intptr_t byte_offset = current_bits_offset_ + byte_index;
+ return (bits_container_.PayloadByte(byte_offset) & byte_mask) != 0;
+}
+
+void CompressedStackMapsIterator::LazyLoadGlobalTableEntry() {
+ ASSERT(maps_.UsesGlobalTable() && bits_container_.IsGlobalTable());
+ ASSERT(HasLoadedEntry());
+ ASSERT(current_global_table_offset_ < bits_container_.payload_size());
+
+ uintptr_t offset = current_global_table_offset_;
+ current_spill_slot_bit_count_ = DecodeLEB128(bits_container_, &offset);
+ ASSERT(current_spill_slot_bit_count_ >= 0);
+
+ current_non_spill_slot_bit_count_ = DecodeLEB128(bits_container_, &offset);
+ ASSERT(current_non_spill_slot_bit_count_ >= 0);
+
+ const auto stackmap_bits = Length();
+ const uintptr_t stackmap_size =
+ Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
+ ASSERT(stackmap_size <= (bits_container_.payload_size() - offset));
+
+ current_bits_offset_ = offset;
}
RawExceptionHandlers* ExceptionHandlerList::FinalizeExceptionHandlers(
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index 0706189..31aa55c 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -30,7 +30,8 @@
intptr_t pc_offset,
intptr_t deopt_id,
TokenPosition token_pos,
- intptr_t try_index);
+ intptr_t try_index,
+ intptr_t yield_index);
RawPcDescriptors* FinalizePcDescriptors(uword entry_point);
@@ -48,6 +49,8 @@
public:
CompressedStackMapsBuilder() : encoded_bytes_() {}
+ static void EncodeLEB128(GrowableArray<uint8_t>* data, uintptr_t value);
+
void AddEntry(intptr_t pc_offset,
BitmapBuilder* bitmap,
intptr_t spill_slot_bit_count);
@@ -64,8 +67,16 @@
public:
// We use the null value to represent CompressedStackMaps with no
// entries, so the constructor allows them.
+ CompressedStackMapsIterator(const CompressedStackMaps& maps,
+ const CompressedStackMaps& global_table)
+ : maps_(maps),
+ bits_container_(maps_.UsesGlobalTable() ? global_table : maps_) {
+ ASSERT(!maps_.IsGlobalTable());
+ ASSERT(!maps_.UsesGlobalTable() || bits_container_.IsGlobalTable());
+ }
+
explicit CompressedStackMapsIterator(const CompressedStackMaps& maps)
- : maps_(maps) {}
+ : CompressedStackMapsIterator(maps, CompressedStackMaps::Handle()) {}
// Loads the next entry from [maps_], if any. If [maps_] is the null
// value, this always returns false.
@@ -91,25 +102,38 @@
ASSERT(HasLoadedEntry());
return current_pc_offset_;
}
- intptr_t length() const {
+ // We lazily load and cache information from the global table if the
+ // CSM uses it, so these methods cannot be const.
+ intptr_t Length();
+ intptr_t SpillSlotBitCount();
+ bool IsObject(intptr_t bit_offset);
+
+ void EnsureFullyLoadedEntry() {
ASSERT(HasLoadedEntry());
- return current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
+ if (current_spill_slot_bit_count_ < 0) {
+ LazyLoadGlobalTableEntry();
+ }
+ ASSERT(current_spill_slot_bit_count_ >= 0);
}
- intptr_t spill_slot_bit_count() const {
- ASSERT(HasLoadedEntry());
- return current_spill_slot_bit_count_;
- }
- bool IsObject(intptr_t bit_offset) const;
private:
+ static uintptr_t DecodeLEB128(const CompressedStackMaps& data,
+ uintptr_t* byte_index);
bool HasLoadedEntry() const { return next_offset_ > 0; }
+ void LazyLoadGlobalTableEntry();
const CompressedStackMaps& maps_;
- intptr_t next_offset_ = 0;
+ const CompressedStackMaps& bits_container_;
+
+ uintptr_t next_offset_ = 0;
uint32_t current_pc_offset_ = 0;
+ // Only used when looking up non-PC information in the global table.
+ uintptr_t current_global_table_offset_ = 0;
intptr_t current_spill_slot_bit_count_ = -1;
intptr_t current_non_spill_slot_bit_count_ = -1;
intptr_t current_bits_offset_ = -1;
+
+ friend class StackMapEntry;
};
class ExceptionHandlerList : public ZoneAllocated {
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index d959adff..8d5a376 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -143,7 +143,7 @@
for (intptr_t i = 0; i < num_token_positions; i++) {
descriptors->AddDescriptor(RawPcDescriptors::kRuntimeCall, 0, 0,
- TokenPosition(token_positions[i]), 0);
+ TokenPosition(token_positions[i]), 0, 1);
}
const PcDescriptors& finalized_descriptors =
diff --git a/runtime/vm/code_observers.h b/runtime/vm/code_observers.h
index 5494b58..c76f5f5 100644
--- a/runtime/vm/code_observers.h
+++ b/runtime/vm/code_observers.h
@@ -12,9 +12,7 @@
namespace dart {
-#ifndef PRODUCT
-
-class Mutex;
+#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
// An abstract representation of comments associated with the given code
// object. We assume that comments are sorted by PCOffset.
@@ -28,6 +26,10 @@
virtual const char* CommentAt(intptr_t index) const = 0;
};
+#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+
+#if !defined(PRODUCT)
+
// Object observing code creation events. Used by external profilers and
// debuggers to map address ranges to function names.
class CodeObserver {
@@ -53,6 +55,8 @@
DISALLOW_COPY_AND_ASSIGN(CodeObserver);
};
+class Mutex;
+
class CodeObservers : public AllStatic {
public:
static void Init();
@@ -82,7 +86,7 @@
static CodeObserver** observers_;
};
-#endif // !PRODUCT
+#endif // !defined(PRODUCT)
} // namespace dart
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 65afe80..adb3aa1 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -828,8 +828,7 @@
// Check if the single target is a polymorphic target, if it is,
// we don't have one target.
const Function& target = targets.FirstTarget();
- const bool polymorphic_target = MethodRecognizer::PolymorphicTarget(target);
- has_one_target = !polymorphic_target;
+ has_one_target = !target.is_polymorphic_target();
}
if (has_one_target) {
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index ef81ad9f..109732d 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -1842,7 +1842,6 @@
script.set_compile_time_constants(Array::null_array());
script.set_line_starts(null_typed_data);
script.set_debug_positions(Array::null_array());
- script.set_yield_positions(Array::null_array());
script.set_kernel_program_info(null_info);
script.set_source(String::null_string());
}
@@ -1895,16 +1894,6 @@
constants = cls.constants();
ASSERT(constants.Length() == 0);
-#if !defined(PRODUCT)
- intptr_t instances =
- class_table->StatsWithUpdatedSize(cid)->post_gc.new_count +
- class_table->StatsWithUpdatedSize(cid)->post_gc.old_count;
- if (instances != 0) {
- FATAL2("Want to drop class %s, but it has %" Pd " instances\n",
- cls.ToCString(), instances);
- }
-#endif
-
dropped_class_count_++;
if (FLAG_trace_precompiler) {
THR_Print("Dropping class %" Pd " %s\n", cid, cls.ToCString());
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index b83a772..51b28bd 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -120,16 +120,12 @@
__ cmp(R1, Operand(IP)); \
__ b(normal_ir_body, CS); \
\
- /* Successfully allocated the object(s), now update top to point to */ \
- /* next object start and initialize the object. */ \
- NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R4, cid)); \
__ str(R1, Address(THR, target::Thread::top_offset())); \
__ AddImmediate(R0, kHeapObjectTag); \
/* Initialize the tags. */ \
/* R0: new object start as a tagged pointer. */ \
/* R1: new object end address. */ \
/* R2: allocation size. */ \
- /* R4: allocation stats address */ \
{ \
__ CompareImmediate(R2, target::RawObject::kSizeTagMaxSizeTag); \
__ mov(R3, \
@@ -150,7 +146,6 @@
/* R0: new object start as a tagged pointer. */ \
/* R1: new object end address. */ \
/* R2: allocation size. */ \
- /* R4: allocation stats address. */ \
__ ldr(R3, Address(SP, kArrayLengthStackOffset)); /* Array length. */ \
__ StoreIntoObjectNoBarrier( \
R0, FieldAddress(R0, target::TypedDataBase::length_offset()), R3); \
@@ -159,7 +154,6 @@
/* R1: new object end address. */ \
/* R2: allocation size. */ \
/* R3: iterator which initially points to the start of the variable */ \
- /* R4: allocation stats address */ \
/* R8, R9: zero. */ \
/* data area to be initialized. */ \
__ LoadImmediate(R8, 0); \
@@ -175,7 +169,6 @@
__ b(&init_loop, CC); \
__ str(R8, Address(R3, -2 * target::kWordSize), HI); \
\
- NOT_IN_PRODUCT(__ IncrementAllocationStatsWithSize(R4, R2)); \
__ Ret(); \
__ Bind(normal_ir_body);
@@ -1977,7 +1970,6 @@
// Successfully allocated the object(s), now update top to point to
// next object start and initialize the object.
- NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R4, cid));
__ str(R1, Address(THR, target::Thread::top_offset()));
__ AddImmediate(R0, kHeapObjectTag);
@@ -1985,7 +1977,6 @@
// R0: new object start as a tagged pointer.
// R1: new object end address.
// R2: allocation size.
- // R4: allocation stats address.
{
const intptr_t shift = target::RawObject::kTagBitsSizeTagPos -
target::ObjectAlignment::kObjectAlignmentLog2;
@@ -2011,7 +2002,6 @@
__ StoreIntoObjectNoBarrier(
R0, FieldAddress(R0, target::String::hash_offset()), TMP);
- NOT_IN_PRODUCT(__ IncrementAllocationStatsWithSize(R4, R2));
__ b(ok);
}
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 2ae8fb3..e8d13e7 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -144,7 +144,6 @@
/* next object start and initialize the object. */ \
__ str(R1, Address(THR, target::Thread::top_offset())); \
__ AddImmediate(R0, kHeapObjectTag); \
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R2)); \
/* Initialize the tags. */ \
/* R0: new object start as a tagged pointer. */ \
/* R1: new object end address. */ \
@@ -2047,7 +2046,6 @@
// next object start and initialize the object.
__ str(R1, Address(THR, target::Thread::top_offset()));
__ AddImmediate(R0, kHeapObjectTag);
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R2));
// Initialize the tags.
// R0: new object start as a tagged pointer.
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index d53462a..b681720 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -128,7 +128,6 @@
/* next object start and initialize the object. */ \
__ movl(Address(THR, target::Thread::top_offset()), EBX); \
__ addl(EAX, Immediate(kHeapObjectTag)); \
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, EDI, ECX)); \
\
/* Initialize the tags. */ \
/* EAX: new object start as a tagged pointer. */ \
@@ -1999,8 +1998,6 @@
__ movl(Address(THR, target::Thread::top_offset()), EBX);
__ addl(EAX, Immediate(kHeapObjectTag));
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, EDI, ECX));
-
// Initialize the tags.
// EAX: new object start as a tagged pointer.
// EBX: new object end address.
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 02ec2c2..d8586e1 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -130,7 +130,6 @@
/* next object start and initialize the object. */ \
__ movq(Address(THR, target::Thread::top_offset()), RCX); \
__ addq(RAX, Immediate(kHeapObjectTag)); \
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, RDI)); \
/* Initialize the tags. */ \
/* RAX: new object start as a tagged pointer. */ \
/* RCX: new object end address. */ \
@@ -2029,7 +2028,6 @@
// next object start and initialize the object.
__ movq(Address(THR, target::Thread::top_offset()), RCX);
__ addq(RAX, Immediate(kHeapObjectTag));
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, RDI));
// Initialize the tags.
// RAX: new object start as a tagged pointer.
diff --git a/runtime/vm/compiler/assembler/assembler.cc b/runtime/vm/compiler/assembler/assembler.cc
index 6cc1a58..9dfdf2e 100644
--- a/runtime/vm/compiler/assembler/assembler.cc
+++ b/runtime/vm/compiler/assembler/assembler.cc
@@ -20,10 +20,6 @@
false,
"Verify instructions offset in code object."
"NOTE: This breaks the profiler.");
-DEFINE_FLAG(bool,
- code_comments,
- false,
- "Include comments into code and disassembly");
#if defined(TARGET_ARCH_ARM)
DEFINE_FLAG(bool, use_far_branches, false, "Enable far branches for ARM.");
#endif
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index b573250..1a5ee3c 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3497,9 +3497,8 @@
void Assembler::MaybeTraceAllocation(Register stats_addr_reg, Label* trace) {
ASSERT(stats_addr_reg != kNoRegister);
ASSERT(stats_addr_reg != TMP);
- const uword state_offset = target::ClassHeapStats::state_offset();
- ldr(TMP, Address(stats_addr_reg, state_offset));
- tst(TMP, Operand(target::ClassHeapStats::TraceAllocationMask()));
+ ldrb(TMP, Address(stats_addr_reg, 0));
+ cmp(TMP, Operand(0));
b(trace, NE);
}
@@ -3520,37 +3519,6 @@
ldr(dest, Address(dest, table_offset));
AddImmediate(dest, class_offset);
}
-
-void Assembler::IncrementAllocationStats(Register stats_addr_reg,
- intptr_t cid) {
- ASSERT(stats_addr_reg != kNoRegister);
- ASSERT(stats_addr_reg != TMP);
- ASSERT(cid > 0);
- const uword count_field_offset =
- target::ClassHeapStats::allocated_since_gc_new_space_offset();
- const Address& count_address = Address(stats_addr_reg, count_field_offset);
- ldr(TMP, count_address);
- AddImmediate(TMP, 1);
- str(TMP, count_address);
-}
-
-void Assembler::IncrementAllocationStatsWithSize(Register stats_addr_reg,
- Register size_reg) {
- ASSERT(stats_addr_reg != kNoRegister);
- ASSERT(stats_addr_reg != TMP);
- const uword count_field_offset =
- target::ClassHeapStats::allocated_since_gc_new_space_offset();
- const uword size_field_offset =
- target::ClassHeapStats::allocated_size_since_gc_new_space_offset();
- const Address& count_address = Address(stats_addr_reg, count_field_offset);
- const Address& size_address = Address(stats_addr_reg, size_field_offset);
- ldr(TMP, count_address);
- AddImmediate(TMP, 1);
- str(TMP, count_address);
- ldr(TMP, size_address);
- add(TMP, TMP, Operand(size_reg));
- str(TMP, size_address);
-}
#endif // !PRODUCT
void Assembler::TryAllocate(const Class& cls,
@@ -3592,8 +3560,6 @@
target::MakeTagWordForNewSpaceObject(cid, instance_size);
LoadImmediate(IP, tags);
str(IP, FieldAddress(instance_reg, target::Object::tags_offset()));
-
- NOT_IN_PRODUCT(IncrementAllocationStats(temp_reg, cid));
} else {
b(failure);
}
@@ -3638,9 +3604,6 @@
LoadImmediate(temp2, tags);
str(temp2,
FieldAddress(instance, target::Object::tags_offset())); // Store tags.
-
- NOT_IN_PRODUCT(LoadImmediate(temp2, instance_size));
- NOT_IN_PRODUCT(IncrementAllocationStatsWithSize(temp1, temp2));
} else {
b(failure);
}
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index cd26332..2e9f016 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -1092,9 +1092,6 @@
// allocation stats. These are separate assembler macros so we can
// avoid a dependent load too nearby the load of the table address.
void LoadAllocationStatsAddress(Register dest, intptr_t cid);
- void IncrementAllocationStats(Register stats_addr, intptr_t cid);
- void IncrementAllocationStatsWithSize(Register stats_addr_reg,
- Register size_reg);
Address ElementAddressForIntIndex(bool is_load,
bool is_external,
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index e8de187..eeaab46 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -475,7 +475,9 @@
bool is_unique) {
ASSERT(IsOriginalObject(object));
word offset = 0;
- if (target::CanLoadFromThread(object, &offset)) {
+ if (IsSameObject(compiler::NullObject(), object)) {
+ mov(dst, NULL_REG);
+ } else if (target::CanLoadFromThread(object, &offset)) {
ldr(dst, Address(THR, offset));
} else if (CanLoadFromObjectPool(object)) {
const int32_t offset = target::ObjectPool::element_offset(
@@ -499,7 +501,9 @@
void Assembler::CompareObject(Register reg, const Object& object) {
ASSERT(IsOriginalObject(object));
word offset = 0;
- if (target::CanLoadFromThread(object, &offset)) {
+ if (IsSameObject(compiler::NullObject(), object)) {
+ CompareRegisters(reg, NULL_REG);
+ } else if (target::CanLoadFromThread(object, &offset)) {
ldr(TMP, Address(THR, offset));
CompareRegisters(reg, TMP);
} else if (CanLoadFromObjectPool(object)) {
@@ -1083,8 +1087,12 @@
ASSERT(IsOriginalObject(value));
ASSERT(IsNotTemporaryScopedHandle(value));
// No store buffer update.
- LoadObject(TMP2, value);
- str(TMP2, dest);
+ if (IsSameObject(compiler::NullObject(), value)) {
+ str(NULL_REG, dest);
+ } else {
+ LoadObject(TMP2, value);
+ str(TMP2, dest);
+ }
}
void Assembler::StoreIntoObjectOffsetNoBarrier(Register object,
@@ -1182,6 +1190,12 @@
CheckCodePointer();
}
+void Assembler::RestorePinnedRegisters() {
+ ldr(BARRIER_MASK,
+ compiler::Address(THR, target::Thread::write_barrier_mask_offset()));
+ ldr(NULL_REG, compiler::Address(THR, target::Thread::object_null_offset()));
+}
+
void Assembler::CheckCodePointer() {
#ifdef DEBUG
if (!FLAG_check_code_pointer) {
@@ -1572,62 +1586,14 @@
target::ClassTable::shared_class_table_offset();
const intptr_t table_offset =
target::SharedClassTable::class_heap_stats_table_offset();
- const intptr_t state_offset = target::ClassTable::StateOffsetFor(cid);
+ const intptr_t class_offset = target::ClassTable::ClassOffsetFor(cid);
LoadIsolate(temp_reg);
ldr(temp_reg, Address(temp_reg, shared_table_offset));
ldr(temp_reg, Address(temp_reg, table_offset));
- AddImmediate(temp_reg, state_offset);
- ldr(temp_reg, Address(temp_reg, 0));
- tsti(temp_reg, Immediate(target::ClassHeapStats::TraceAllocationMask()));
- b(trace, NE);
-}
-
-void Assembler::UpdateAllocationStats(intptr_t cid) {
- ASSERT(cid > 0);
-
- const intptr_t shared_table_offset =
- target::Isolate::class_table_offset() +
- target::ClassTable::shared_class_table_offset();
- const intptr_t table_offset =
- target::SharedClassTable::class_heap_stats_table_offset();
- const intptr_t counter_offset =
- target::ClassTable::NewSpaceCounterOffsetFor(cid);
-
- LoadIsolate(TMP2);
- ldr(TMP2, Address(TMP2, shared_table_offset));
- ldr(TMP, Address(TMP2, table_offset));
- AddImmediate(TMP2, TMP, counter_offset);
- ldr(TMP, Address(TMP2, 0));
- AddImmediate(TMP, 1);
- str(TMP, Address(TMP2, 0));
-}
-
-void Assembler::UpdateAllocationStatsWithSize(intptr_t cid, Register size_reg) {
- ASSERT(cid > 0);
-
- const intptr_t shared_table_offset =
- target::Isolate::class_table_offset() +
- target::ClassTable::shared_class_table_offset();
- const intptr_t table_offset =
- target::SharedClassTable::class_heap_stats_table_offset();
-
- const uword class_offset = target::ClassTable::ClassOffsetFor(cid);
- const uword count_field_offset =
- target::ClassHeapStats::allocated_since_gc_new_space_offset();
- const uword size_field_offset =
- target::ClassHeapStats::allocated_size_since_gc_new_space_offset();
-
- LoadIsolate(TMP2);
- ldr(TMP2, Address(TMP2, shared_table_offset));
- ldr(TMP, Address(TMP2, table_offset));
- AddImmediate(TMP2, TMP, class_offset);
- ldr(TMP, Address(TMP2, count_field_offset));
- AddImmediate(TMP, 1);
- str(TMP, Address(TMP2, count_field_offset));
- ldr(TMP, Address(TMP2, size_field_offset));
- add(TMP, TMP, Operand(size_reg));
- str(TMP, Address(TMP2, size_field_offset));
+ AddImmediate(temp_reg, class_offset);
+ ldr(temp_reg, Address(temp_reg, 0), kUnsignedByte);
+ cbnz(trace, temp_reg);
}
#endif // !PRODUCT
@@ -1663,8 +1629,6 @@
// next object start and store the class in the class field of object.
str(top_reg, Address(THR, target::Thread::top_offset()));
- NOT_IN_PRODUCT(UpdateAllocationStats(cid));
-
const uint32_t tags =
target::MakeTagWordForNewSpaceObject(cid, instance_size);
// Extends the 32 bit tags with zeros, which is the uninitialized
@@ -1710,7 +1674,6 @@
str(end_address, Address(THR, target::Thread::top_offset()));
add(instance, instance, Operand(kHeapObjectTag));
NOT_IN_PRODUCT(LoadImmediate(temp2, instance_size));
- NOT_IN_PRODUCT(UpdateAllocationStatsWithSize(cid, temp2));
// Initialize the tags.
// instance: new object start as a tagged pointer.
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 6b1805c..719b520 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1515,8 +1515,12 @@
uint32_t offset);
void PushObject(const Object& object) {
- LoadObject(TMP, object);
- Push(TMP);
+ if (IsSameObject(compiler::NullObject(), object)) {
+ Push(NULL_REG);
+ } else {
+ LoadObject(TMP, object);
+ Push(TMP);
+ }
}
void PushImmediate(int64_t immediate) {
LoadImmediate(TMP, immediate);
@@ -1556,6 +1560,10 @@
void CheckCodePointer();
void RestoreCodePointer();
+ // Restores the values of the registers that are blocked to cache some values
+ // e.g. BARRIER_MASK and NULL_REG.
+ void RestorePinnedRegisters();
+
void EnterDartFrame(intptr_t frame_size, Register new_pp = kNoRegister);
void EnterOsrFrame(intptr_t extra_size, Register new_pp = kNoRegister);
void LeaveDartFrame(RestorePP restore_pp = kRestoreCallerPP);
@@ -1573,10 +1581,6 @@
void MonomorphicCheckedEntryAOT();
void BranchOnMonomorphicCheckedEntryJIT(Label* label);
- void UpdateAllocationStats(intptr_t cid);
-
- void UpdateAllocationStatsWithSize(intptr_t cid, Register size_reg);
-
// If allocation tracing for |cid| is enabled, will jump to |trace| label,
// which will allocate in the runtime where tracing occurs.
void MaybeTraceAllocation(intptr_t cid, Register temp_reg, Label* trace);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64_test.cc b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
index 13a69a8..310e20e 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
@@ -2398,15 +2398,18 @@
__ Push(CODE_REG);
__ Push(THR);
__ Push(BARRIER_MASK);
+ __ Push(NULL_REG);
__ TagAndPushPP();
__ ldr(CODE_REG, Address(R0, VMHandles::kOffsetOfRawPtrInHandle));
__ mov(THR, R1);
__ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
+ __ ldr(NULL_REG, Address(THR, Thread::object_null_offset()));
__ LoadPoolPointer(PP);
}
static void LeaveTestFrame(Assembler* assembler) {
__ PopAndUntagPP();
+ __ Pop(NULL_REG);
__ Pop(BARRIER_MASK);
__ Pop(THR);
__ Pop(CODE_REG);
@@ -2481,6 +2484,39 @@
EXPECT_EQ(Object::null(), test->InvokeWithCodeAndThread<RawObject*>());
}
+// PushObject null.
+ASSEMBLER_TEST_GENERATE(PushObjectNull, assembler) {
+ __ SetupDartSP();
+ EnterTestFrame(assembler);
+ __ PushObject(Object::null_object());
+ __ Pop(R0);
+ LeaveTestFrame(assembler);
+ __ RestoreCSP();
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(PushObjectNull, test) {
+ EXPECT_EQ(Object::null(), test->InvokeWithCodeAndThread<RawObject*>());
+}
+
+// CompareObject null.
+ASSEMBLER_TEST_GENERATE(CompareObjectNull, assembler) {
+ __ SetupDartSP();
+ EnterTestFrame(assembler);
+ __ LoadObject(R0, Object::bool_true());
+ __ LoadObject(R1, Object::bool_false());
+ __ ldr(R2, Address(THR, Thread::object_null_offset()));
+ __ CompareObject(R2, Object::null_object());
+ __ csel(R0, R0, R1, EQ);
+ LeaveTestFrame(assembler);
+ __ RestoreCSP();
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(CompareObjectNull, test) {
+ EXPECT_EQ(Bool::True().raw(), test->InvokeWithCodeAndThread<RawObject*>());
+}
+
ASSEMBLER_TEST_GENERATE(LoadObjectTrue, assembler) {
__ SetupDartSP();
EnterTestFrame(assembler);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 63cab25..0dcc1d4 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2409,56 +2409,17 @@
target::ClassTable::shared_class_table_offset();
const intptr_t table_offset =
target::SharedClassTable::class_heap_stats_table_offset();
- const intptr_t state_offset = target::ClassTable::StateOffsetFor(cid);
+ const intptr_t class_offset = target::ClassTable::ClassOffsetFor(cid);
ASSERT(temp_reg != kNoRegister);
LoadIsolate(temp_reg);
movl(temp_reg, Address(temp_reg, shared_table_offset));
movl(temp_reg, Address(temp_reg, table_offset));
- state_address = Address(temp_reg, state_offset);
- testb(state_address,
- Immediate(target::ClassHeapStats::TraceAllocationMask()));
+ cmpb(Address(temp_reg, class_offset), Immediate(0));
// We are tracing for this class, jump to the trace label which will use
// the allocation stub.
j(NOT_ZERO, trace, near_jump);
}
-
-void Assembler::UpdateAllocationStats(intptr_t cid, Register temp_reg) {
- ASSERT(cid > 0);
- const intptr_t shared_table_offset =
- target::Isolate::class_table_offset() +
- target::ClassTable::shared_class_table_offset();
- const intptr_t table_offset =
- target::SharedClassTable::class_heap_stats_table_offset();
- const intptr_t counter_offset =
- target::ClassTable::NewSpaceCounterOffsetFor(cid);
-
- ASSERT(temp_reg != kNoRegister);
- LoadIsolate(temp_reg);
- movl(temp_reg, Address(temp_reg, shared_table_offset));
- movl(temp_reg, Address(temp_reg, table_offset));
- incl(Address(temp_reg, counter_offset));
-}
-
-void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
- Register size_reg,
- Register temp_reg) {
- ASSERT(cid > 0);
- ASSERT(cid < kNumPredefinedCids);
- UpdateAllocationStats(cid, temp_reg);
- intptr_t size_offset = target::ClassTable::NewSpaceSizeOffsetFor(cid);
- addl(Address(temp_reg, size_offset), size_reg);
-}
-
-void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
- intptr_t size_in_bytes,
- Register temp_reg) {
- ASSERT(cid > 0);
- ASSERT(cid < kNumPredefinedCids);
- UpdateAllocationStats(cid, temp_reg);
- intptr_t size_offset = target::ClassTable::NewSpaceSizeOffsetFor(cid);
- addl(Address(temp_reg, size_offset), Immediate(size_in_bytes));
-}
#endif // !PRODUCT
void Assembler::TryAllocate(const Class& cls,
@@ -2484,7 +2445,6 @@
// Successfully allocated the object, now update top to point to
// next object start and store the class in the class field of object.
movl(Address(THR, target::Thread::top_offset()), instance_reg);
- NOT_IN_PRODUCT(UpdateAllocationStats(cid, temp_reg));
ASSERT(instance_size >= kHeapObjectTag);
subl(instance_reg, Immediate(instance_size - kHeapObjectTag));
const uint32_t tags =
@@ -2527,7 +2487,6 @@
// next object start and initialize the object.
movl(Address(THR, target::Thread::top_offset()), end_address);
addl(instance, Immediate(kHeapObjectTag));
- NOT_IN_PRODUCT(UpdateAllocationStatsWithSize(cid, instance_size, temp_reg));
// Initialize the tags.
const uint32_t tags =
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index e4e86c1..d8fca975 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -810,15 +810,6 @@
Label* trace,
bool near_jump);
- void UpdateAllocationStats(intptr_t cid, Register temp_reg);
-
- void UpdateAllocationStatsWithSize(intptr_t cid,
- Register size_reg,
- Register temp_reg);
- void UpdateAllocationStatsWithSize(intptr_t cid,
- intptr_t instance_size,
- Register temp_reg);
-
// Inlined allocation of an instance of class 'cls', code has no runtime
// calls. Jump to 'failure' if the instance cannot be allocated here.
// Allocated instance is returned in 'instance_reg'.
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index c9e1299..9556a10 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1873,54 +1873,17 @@
target::ClassTable::shared_class_table_offset();
const intptr_t table_offset =
target::SharedClassTable::class_heap_stats_table_offset();
- const intptr_t state_offset = target::ClassTable::StateOffsetFor(cid);
+ const intptr_t class_offset = target::ClassTable::ClassOffsetFor(cid);
Register temp_reg = TMP;
LoadIsolate(temp_reg);
movq(temp_reg, Address(temp_reg, shared_table_offset));
movq(temp_reg, Address(temp_reg, table_offset));
- testb(Address(temp_reg, state_offset),
- Immediate(target::ClassHeapStats::TraceAllocationMask()));
+ cmpb(Address(temp_reg, class_offset), Immediate(0));
// We are tracing for this class, jump to the trace label which will use
// the allocation stub.
j(NOT_ZERO, trace, near_jump);
}
-
-void Assembler::UpdateAllocationStats(intptr_t cid) {
- ASSERT(cid > 0);
- const intptr_t shared_table_offset =
- target::Isolate::class_table_offset() +
- target::ClassTable::shared_class_table_offset();
- const intptr_t table_offset =
- target::SharedClassTable::class_heap_stats_table_offset();
- const intptr_t counter_offset =
- target::ClassTable::NewSpaceCounterOffsetFor(cid);
-
- Register temp_reg = TMP;
- LoadIsolate(temp_reg);
- movq(temp_reg, Address(temp_reg, shared_table_offset));
- movq(temp_reg, Address(temp_reg, table_offset));
- incq(Address(temp_reg, counter_offset));
-}
-
-void Assembler::UpdateAllocationStatsWithSize(intptr_t cid, Register size_reg) {
- ASSERT(cid > 0);
- ASSERT(cid < kNumPredefinedCids);
- UpdateAllocationStats(cid);
- Register temp_reg = TMP;
- intptr_t size_offset = target::ClassTable::NewSpaceSizeOffsetFor(cid);
- addq(Address(temp_reg, size_offset), size_reg);
-}
-
-void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
- intptr_t size_in_bytes) {
- ASSERT(cid > 0);
- ASSERT(cid < kNumPredefinedCids);
- UpdateAllocationStats(cid);
- Register temp_reg = TMP;
- intptr_t size_offset = target::ClassTable::NewSpaceSizeOffsetFor(cid);
- addq(Address(temp_reg, size_offset), Immediate(size_in_bytes));
-}
#endif // !PRODUCT
void Assembler::TryAllocate(const Class& cls,
@@ -1945,7 +1908,6 @@
// Successfully allocated the object, now update top to point to
// next object start and store the class in the class field of object.
movq(Address(THR, target::Thread::top_offset()), instance_reg);
- NOT_IN_PRODUCT(UpdateAllocationStats(cid));
ASSERT(instance_size >= kHeapObjectTag);
AddImmediate(instance_reg, Immediate(kHeapObjectTag - instance_size));
const uint32_t tags =
@@ -1989,7 +1951,6 @@
// next object start and initialize the object.
movq(Address(THR, target::Thread::top_offset()), end_address);
addq(instance, Immediate(kHeapObjectTag));
- NOT_IN_PRODUCT(UpdateAllocationStatsWithSize(cid, instance_size));
// Initialize the tags.
// instance: new object start as a tagged pointer.
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 0c4a5e6..af51403 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -894,11 +894,6 @@
void MonomorphicCheckedEntryAOT();
void BranchOnMonomorphicCheckedEntryJIT(Label* label);
- void UpdateAllocationStats(intptr_t cid);
-
- void UpdateAllocationStatsWithSize(intptr_t cid, Register size_reg);
- void UpdateAllocationStatsWithSize(intptr_t cid, intptr_t instance_size);
-
// If allocation tracing for |cid| is enabled, will jump to |trace| label,
// which will allocate in the runtime where tracing occurs.
void MaybeTraceAllocation(intptr_t cid, Label* trace, bool near_jump);
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index b74310c..1c68c6d 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -240,12 +240,18 @@
ASSERT(code.pointer_offsets_length() == 0);
#endif
- const ObjectPool& object_pool =
- ObjectPool::Handle(zone, code.GetObjectPool());
- if (!object_pool.IsNull()) {
- object_pool.DebugPrint();
+ if (FLAG_use_bare_instructions) {
+ THR_Print("(No object pool for bare instructions.)\n");
+ } else {
+ const ObjectPool& object_pool =
+ ObjectPool::Handle(zone, code.GetObjectPool());
+ if (!object_pool.IsNull()) {
+ object_pool.DebugPrint();
+ }
}
+ code.DumpSourcePositions(/*relative_addresses=*/FLAG_disassemble_relative);
+
THR_Print("PC Descriptors for function '%s' {\n", function_fullname);
PcDescriptors::PrintHeaderString();
const PcDescriptors& descriptors =
@@ -258,23 +264,25 @@
#if !defined(DART_PRECOMPILED_RUNTIME)
const Array& deopt_table = Array::Handle(zone, code.deopt_info_array());
- intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table);
- if (deopt_table_length > 0) {
- THR_Print("DeoptInfo: {\n");
- Smi& offset = Smi::Handle(zone);
- TypedData& info = TypedData::Handle(zone);
- Smi& reason_and_flags = Smi::Handle(zone);
- for (intptr_t i = 0; i < deopt_table_length; ++i) {
- DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason_and_flags);
- const intptr_t reason =
- DeoptTable::ReasonField::decode(reason_and_flags.Value());
- ASSERT((0 <= reason) && (reason < ICData::kDeoptNumReasons));
- THR_Print(
- "%4" Pd ": 0x%" Px " %s (%s)\n", i, base + offset.Value(),
- DeoptInfo::ToCString(deopt_table, info),
- DeoptReasonToCString(static_cast<ICData::DeoptReasonId>(reason)));
+ if (!deopt_table.IsNull()) {
+ intptr_t deopt_table_length = DeoptTable::GetLength(deopt_table);
+ if (deopt_table_length > 0) {
+ THR_Print("DeoptInfo: {\n");
+ Smi& offset = Smi::Handle(zone);
+ TypedData& info = TypedData::Handle(zone);
+ Smi& reason_and_flags = Smi::Handle(zone);
+ for (intptr_t i = 0; i < deopt_table_length; ++i) {
+ DeoptTable::GetEntry(deopt_table, i, &offset, &info, &reason_and_flags);
+ const intptr_t reason =
+ DeoptTable::ReasonField::decode(reason_and_flags.Value());
+ ASSERT((0 <= reason) && (reason < ICData::kDeoptNumReasons));
+ THR_Print(
+ "%4" Pd ": 0x%" Px " %s (%s)\n", i, base + offset.Value(),
+ DeoptInfo::ToCString(deopt_table, info),
+ DeoptReasonToCString(static_cast<ICData::DeoptReasonId>(reason)));
+ }
+ THR_Print("}\n");
}
- THR_Print("}\n");
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
@@ -343,6 +351,9 @@
THR_Print("}\n");
}
+#if defined(DART_PRECOMPILED_RUNTIME)
+ THR_Print("(Cannot show static call target functions in AOT runtime.)\n");
+#else
{
THR_Print("Static call target functions {\n");
const auto& table = Array::Handle(zone, code.static_calls_target_table());
@@ -393,8 +404,9 @@
}
}
}
+ THR_Print("}\n");
}
- THR_Print("}\n");
+#endif // defined(DART_PRECOMPILED_RUNTIME)
if (optimized && FLAG_trace_inlining_intervals) {
code.DumpInlineIntervals();
@@ -411,6 +423,20 @@
DisassembleCodeHelper(function_fullname, code, optimized);
}
+void Disassembler::DisassembleStub(const char* name, const Code& code) {
+ LogBlock lb;
+ THR_Print("Code for stub '%s': {\n", name);
+ DisassembleToStdout formatter;
+ code.Disassemble(&formatter);
+ THR_Print("}\n");
+ const ObjectPool& object_pool = ObjectPool::Handle(code.object_pool());
+ if (FLAG_use_bare_instructions) {
+ THR_Print("(No object pool for bare instructions.)\n");
+ } else if (!object_pool.IsNull()) {
+ object_pool.DebugPrint();
+ }
+}
+
#else // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
void Disassembler::DisassembleCode(const Function& function,
diff --git a/runtime/vm/compiler/assembler/disassembler.h b/runtime/vm/compiler/assembler/disassembler.h
index e210686..861051d 100644
--- a/runtime/vm/compiler/assembler/disassembler.h
+++ b/runtime/vm/compiler/assembler/disassembler.h
@@ -184,6 +184,8 @@
const Code& code,
bool optimized);
+ static void DisassembleStub(const char* name, const Code& code);
+
private:
static void DisassembleCodeHelper(const char* function_fullname,
const Code& code,
diff --git a/runtime/vm/compiler/assembler/disassembler_arm64.cc b/runtime/vm/compiler/assembler/disassembler_arm64.cc
index 7ed5a44..0a75a17 100644
--- a/runtime/vm/compiler/assembler/disassembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/disassembler_arm64.cc
@@ -86,7 +86,7 @@
static const char* reg_names[kNumberOfCpuRegisters] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
"r11", "r12", "r13", "r14", "r15", "ip0", "ip1", "r18", "sp", "r20", "r21",
- "r22", "r23", "r24", "r25", "thr", "pp", "ctx", "fp", "lr", "r31",
+ "nr", "r23", "r24", "r25", "thr", "pp", "ctx", "fp", "lr", "r31",
};
// Print the register name according to the active name converter.
diff --git a/runtime/vm/compiler/backend/bce_test.cc b/runtime/vm/compiler/backend/bce_test.cc
index 2bef2ba..44bc798 100644
--- a/runtime/vm/compiler/backend/bce_test.cc
+++ b/runtime/vm/compiler/backend/bce_test.cc
@@ -83,8 +83,7 @@
return l[0];
}
main() {
- var l = new Float64List(1);
- foo(l);
+ foo(new Float64List(1));
}
)";
TestScriptJIT(kScriptChars, 1, 1);
@@ -98,14 +97,13 @@
return l[1] + l[0];
}
main() {
- var l = new Float64List(2);
- foo(l);
+ foo(new Float64List(2));
}
)";
TestScriptJIT(kScriptChars, 2, 1);
}
-ISOLATE_UNIT_TEST_CASE(BCESimpleLoop) {
+ISOLATE_UNIT_TEST_CASE(BCESimpleLoops) {
const char* kScriptChars =
R"(
import 'dart:typed_data';
@@ -113,13 +111,34 @@
for (int i = 0; i < l.length; i++) {
l[i] = 0;
}
+ for (int i = 10; i <= l.length - 5; i++) {
+ l[i] = 1;
+ }
}
main() {
- var l = new Float64List(100);
- foo(l);
+ foo(new Float64List(100));
}
)";
- TestScriptJIT(kScriptChars, 1, 0);
+ TestScriptJIT(kScriptChars, 2, 0);
+}
+
+ISOLATE_UNIT_TEST_CASE(BCESimpleLoopsDown) {
+ const char* kScriptChars =
+ R"(
+ import 'dart:typed_data';
+ foo(Float64List l) {
+ for (int i = l.length - 1; i >= 0; i--) {
+ l[i] = 0;
+ }
+ for (int i = l.length - 5; i >= 10; i--) {
+ l[i] = 1;
+ }
+ }
+ main() {
+ foo(new Float64List(100));
+ }
+ )";
+ TestScriptJIT(kScriptChars, 2, 0);
}
ISOLATE_UNIT_TEST_CASE(BCEModulo) {
@@ -136,6 +155,143 @@
TestScriptJIT(kScriptChars, 2, 0);
}
-// TODO(ajcbik): add more tests
+ISOLATE_UNIT_TEST_CASE(BCELowerTriangular) {
+ const char* kScriptChars =
+ R"(
+ import 'dart:typed_data';
+ foo(Float64List l) {
+ for (int i = 0; i < l.length; i++) {
+ for (int j = 0; j <= i; j++) {
+ l[i] += l[j];
+ }
+ }
+ }
+ main() {
+ foo(new Float64List(100));
+ }
+ )";
+ TestScriptJIT(kScriptChars, 2, 0);
+}
+
+ISOLATE_UNIT_TEST_CASE(BCEUpperTriangular) {
+ const char* kScriptChars =
+ R"(
+ import 'dart:typed_data';
+ foo(Float64List l) {
+ for (int i = 0; i < l.length; i++) {
+ for (int j = i; j < l.length; j++) {
+ l[i] += l[j];
+ }
+ }
+ }
+ main() {
+ foo(new Float64List(100));
+ }
+ )";
+ TestScriptJIT(kScriptChars, 2, 0);
+}
+
+ISOLATE_UNIT_TEST_CASE(BCETriangularDown) {
+ const char* kScriptChars =
+ R"(
+ import 'dart:typed_data';
+ foo(Float64List l) {
+ for (int i = l.length - 1; i >= 0; i--) {
+ for (int j = i; j >= 0; j--) {
+ l[i] += l[j];
+ }
+ }
+ }
+ main() {
+ foo(new Float64List(100));
+ }
+ )";
+ TestScriptJIT(kScriptChars, 2, 0);
+}
+
+ISOLATE_UNIT_TEST_CASE(BCENamedLength) {
+ const char* kScriptChars =
+ R"(
+ import 'dart:typed_data';
+ Int8List foo(int count) {
+ var x = new Int8List(count);
+ for (int i = 0; i < count; i++) {
+ x[i] = 0;
+ }
+ return x;
+ }
+ main() {
+ foo(100);
+ }
+ )";
+ TestScriptJIT(kScriptChars, 1, 0);
+}
+
+ISOLATE_UNIT_TEST_CASE(BCEBubbleSort) {
+ const char* kScriptChars =
+ R"(
+ import 'dart:typed_data';
+ foo(Float64List a) {
+ int len = a.length;
+ for (int i = len - 2; i >= 0; i--) {
+ for (int j = 0; j <= i; j++) {
+ var c = a[j];
+ var n = a[j + 1];
+ if (c > n) {
+ a[j] = n;
+ a[j + 1] = c;
+ }
+ }
+ }
+ }
+ main() {
+ foo(new Float64List(100));
+ }
+ )";
+ TestScriptJIT(kScriptChars, 2, 0);
+}
+
+ISOLATE_UNIT_TEST_CASE(BCEArithmeticWrapAround) {
+ const char* kScriptChars =
+ R"(
+ import 'dart:typed_data';
+ const kMax = 0x7fffffffffffffff;
+ foo(Float64List a) {
+ for (int i = kMax - 10; i < kMax; i++) {
+ for (int j = i + 10; j < a.length; j++) {
+ // Don't be fooled: j in [-minint, len).
+ a[j] = 1;
+ }
+ }
+ }
+ main() {
+ try {
+ foo(new Float64List(100));
+ } catch (e) {
+ }
+ }
+ )";
+ TestScriptJIT(kScriptChars, 1, 1);
+}
+
+ISOLATE_UNIT_TEST_CASE(BCEListNamedAndPlainLength) {
+ const char* kScriptChars =
+ R"(
+ List<int> foo(int count) {
+ var x = new List<int>(count);
+ for (int i = 0; i < count; i++) {
+ x[i] = 0;
+ }
+ for (int i = 0; i < x.length; i++) {
+ x[i] = 0;
+ }
+ return x;
+ }
+ main() {
+ foo(100);
+ }
+ )";
+ TestScriptJIT(kScriptChars, 2, 0);
+}
} // namespace dart
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 0defd40..5459507 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -445,7 +445,7 @@
}
void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) {
- const auto kind = MethodRecognizer::RecognizeKind(instr->function());
+ const auto kind = instr->function().recognized_kind();
switch (kind) {
case MethodRecognizer::kOneByteString_equality:
case MethodRecognizer::kTwoByteString_equality: {
@@ -837,9 +837,9 @@
const Instance& instance = Instance::Cast(value);
if (instr->instantiator_type_arguments()->BindsToConstantNull() &&
instr->function_type_arguments()->BindsToConstantNull()) {
- bool is_instance =
- instance.IsInstanceOf(checked_type, Object::null_type_arguments(),
- Object::null_type_arguments());
+ bool is_instance = instance.IsInstanceOf(
+ NNBDMode::kLegacy, checked_type, Object::null_type_arguments(),
+ Object::null_type_arguments());
SetValue(instr, Bool::Get(is_instance));
return;
}
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 0c83b55..9f49f44 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -951,8 +951,6 @@
}
}
- const intptr_t var_length =
- IsCompiledForOsr() ? osr_variable_count() : variable_count();
while (!worklist.is_empty()) {
BlockEntryInstr* current = worklist.RemoveLast();
// Ensure a phi for each block in the dominance frontier of current.
@@ -960,10 +958,10 @@
!it.Done(); it.Advance()) {
int index = it.Current();
if (has_already[index] < var_index) {
- BlockEntryInstr* block = preorder[index];
- ASSERT(block->IsJoinEntry());
- PhiInstr* phi =
- block->AsJoinEntry()->InsertPhi(var_index, var_length);
+ JoinEntryInstr* join = preorder[index]->AsJoinEntry();
+ ASSERT(join != nullptr);
+ PhiInstr* phi = join->InsertPhi(
+ var_index, variable_count() + join->stack_depth());
if (always_live) {
phi->mark_alive();
live_phis->Add(phi);
@@ -971,7 +969,7 @@
has_already[index] = var_index;
if (work[index] < var_index) {
work[index] = var_index;
- worklist.Add(block);
+ worklist.Add(join);
}
}
}
@@ -984,6 +982,18 @@
constant_dead_ = GetConstant(Symbols::OptimizedOut());
}
+void FlowGraph::AddSyntheticPhis(BlockEntryInstr* block) {
+ ASSERT(IsCompiledForOsr());
+ if (auto join = block->AsJoinEntry()) {
+ const intptr_t local_phi_count = variable_count() + join->stack_depth();
+ for (intptr_t i = variable_count(); i < local_phi_count; ++i) {
+ if (join->phis() == nullptr || (*join->phis())[i] == nullptr) {
+ join->InsertPhi(i, local_phi_count)->mark_alive();
+ }
+ }
+ }
+}
+
void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis,
VariableLivenessAnalysis* variable_liveness,
ZoneGrowableArray<Definition*>* inlining_parameters) {
@@ -1007,17 +1017,14 @@
: entry->SuccessorCount() == 1);
}
- // For OSR on a non-empty stack, insert synthetic phis on the joining entry.
+ // For OSR on a non-empty stack, insert synthetic phis on every joining entry.
// These phis are synthetic since they are not driven by live variable
// analysis, but merely serve the purpose of merging stack slots from
// parameters and other predecessors at the block in which OSR occurred.
if (IsCompiledForOsr()) {
- JoinEntryInstr* join =
- entry->osr_entry()->last_instruction()->SuccessorAt(0)->AsJoinEntry();
- ASSERT(join != nullptr);
- const intptr_t parameter_count = osr_variable_count();
- for (intptr_t i = variable_count(); i < parameter_count; i++) {
- join->InsertPhi(i, parameter_count)->mark_alive();
+ AddSyntheticPhis(entry->osr_entry()->last_instruction()->SuccessorAt(0));
+ for (intptr_t i = 0, n = entry->dominated_blocks().length(); i < n; ++i) {
+ AddSyntheticPhis(entry->dominated_blocks()[i]);
}
}
@@ -1168,10 +1175,9 @@
// 1. Process phis first.
if (auto join = block_entry->AsJoinEntry()) {
if (join->phis() != nullptr) {
- const intptr_t var_length =
- IsCompiledForOsr() ? osr_variable_count() : variable_count();
- ASSERT(join->phis()->length() == var_length);
- for (intptr_t i = 0; i < var_length; ++i) {
+ const intptr_t local_phi_count = variable_count() + join->stack_depth();
+ ASSERT(join->phis()->length() == local_phi_count);
+ for (intptr_t i = 0; i < local_phi_count; ++i) {
PhiInstr* phi = (*join->phis())[i];
if (phi != nullptr) {
(*env)[i] = phi;
diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h
index bbba0f1..3622a5c 100644
--- a/runtime/vm/compiler/backend/flow_graph.h
+++ b/runtime/vm/compiler/backend/flow_graph.h
@@ -429,6 +429,8 @@
GrowableArray<intptr_t>* parent,
GrowableArray<intptr_t>* label);
+ void AddSyntheticPhis(BlockEntryInstr* block);
+
void Rename(GrowableArray<PhiInstr*>* live_phis,
VariableLivenessAnalysis* variable_liveness,
ZoneGrowableArray<Definition*>* inlining_parameters);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index e1bce80..68f33f5 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -60,7 +60,6 @@
"The scale of invocation count, by size of the function.");
DEFINE_FLAG(bool, source_lines, false, "Emit source line as assembly comment.");
-DECLARE_FLAG(bool, code_comments);
DECLARE_FLAG(charp, deoptimize_filter);
DECLARE_FLAG(bool, intrinsify);
DECLARE_FLAG(int, regexp_optimization_counter_threshold);
@@ -492,6 +491,12 @@
}
}
+void FlowGraphCompiler::EmitYieldPositionMetadata(TokenPosition token_pos,
+ intptr_t yield_index) {
+ AddDescriptor(RawPcDescriptors::kOther, assembler()->CodeSize(),
+ DeoptId::kNone, token_pos, CurrentTryIndex(), yield_index);
+}
+
void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) {
if (!is_optimizing()) {
if (instr->CanBecomeDeoptimizationTarget() && !instr->IsGoto()) {
@@ -732,12 +737,13 @@
intptr_t pc_offset,
intptr_t deopt_id,
TokenPosition token_pos,
- intptr_t try_index) {
+ intptr_t try_index,
+ intptr_t yield_index) {
code_source_map_builder_->NoteDescriptor(kind, pc_offset, token_pos);
// Don't emit deopt-descriptors in AOT mode.
if (FLAG_precompiled_mode && (kind == RawPcDescriptors::kDeopt)) return;
pc_descriptors_list_->AddDescriptor(kind, pc_offset, deopt_id, token_pos,
- try_index);
+ try_index, yield_index);
}
// Uses current pc position and try-index.
@@ -1117,12 +1123,14 @@
void FlowGraphCompiler::FinalizeCatchEntryMovesMap(const Code& code) {
#if defined(DART_PRECOMPILER)
- TypedData& maps = TypedData::Handle(
- catch_entry_moves_maps_builder_->FinalizeCatchEntryMovesMap());
- code.set_catch_entry_moves_maps(maps);
-#else
- code.set_variables(Smi::Handle(Smi::New(flow_graph().variable_count())));
+ if (FLAG_precompiled_mode) {
+ TypedData& maps = TypedData::Handle(
+ catch_entry_moves_maps_builder_->FinalizeCatchEntryMovesMap());
+ code.set_catch_entry_moves_maps(maps);
+ return;
+ }
#endif
+ code.set_num_variables(flow_graph().variable_count());
}
void FlowGraphCompiler::FinalizeStaticCallTargetsTable(const Code& code) {
@@ -2262,7 +2270,7 @@
// caller side!
const Type& int_type = Type::Handle(zone(), Type::IntType());
bool is_non_smi = false;
- if (int_type.IsSubtypeOf(dst_type, Heap::kOld)) {
+ if (int_type.IsSubtypeOf(NNBDMode::kLegacy, dst_type, Heap::kOld)) {
__ BranchIfSmi(instance_reg, done);
is_non_smi = true;
}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 86374da..13c0cfe 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -681,6 +681,8 @@
LocationSummary* locs,
Environment* env = nullptr);
+ void EmitYieldPositionMetadata(TokenPosition token_pos, intptr_t yield_index);
+
void EmitComment(Instruction* instr);
// Returns stack size (number of variables on stack for unoptimized
@@ -716,11 +718,13 @@
void AddCurrentDescriptor(RawPcDescriptors::Kind kind,
intptr_t deopt_id,
TokenPosition token_pos);
- void AddDescriptor(RawPcDescriptors::Kind kind,
- intptr_t pc_offset,
- intptr_t deopt_id,
- TokenPosition token_pos,
- intptr_t try_index);
+ void AddDescriptor(
+ RawPcDescriptors::Kind kind,
+ intptr_t pc_offset,
+ intptr_t deopt_id,
+ TokenPosition token_pos,
+ intptr_t try_index,
+ intptr_t yield_index = RawPcDescriptors::kInvalidYieldIndex);
void AddNullCheck(intptr_t pc_offset,
TokenPosition token_pos,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 7143db9..c681c1b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -278,7 +278,8 @@
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = R0;
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
- const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
+ const bool smi_is_ok =
+ smi_type.IsSubtypeOf(NNBDMode::kLegacy, type, Heap::kOld);
__ tst(kInstanceReg, compiler::Operand(kSmiTagMask));
if (smi_is_ok) {
// Fast case for type = FutureOr<int/num/top-type>.
@@ -314,7 +315,7 @@
ASSERT(tp_argument.HasTypeClass());
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
- if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
+ if (object_type.IsSubtypeOf(NNBDMode::kLegacy, tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@@ -364,7 +365,8 @@
__ tst(kInstanceReg, compiler::Operand(kSmiTagMask));
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
- if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type_class,
+ if (Class::IsSubtypeOf(NNBDMode::kLegacy, smi_class,
+ Object::null_type_arguments(), type_class,
Object::null_type_arguments(), Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ b(is_instance_lbl, EQ);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 980cc1e..f5b6813 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -269,7 +269,8 @@
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = R0;
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
- const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
+ const bool smi_is_ok =
+ smi_type.IsSubtypeOf(NNBDMode::kLegacy, type, Heap::kOld);
// Fast case for type = FutureOr<int/num/top-type>.
__ BranchIfSmi(kInstanceReg,
smi_is_ok ? is_instance_lbl : is_not_instance_lbl);
@@ -301,7 +302,7 @@
if (tp_argument.IsType()) {
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
- if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
+ if (object_type.IsSubtypeOf(NNBDMode::kLegacy, tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@@ -349,7 +350,8 @@
const Register kInstanceReg = R0;
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
- if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type_class,
+ if (Class::IsSubtypeOf(NNBDMode::kLegacy, smi_class,
+ Object::null_type_arguments(), type_class,
Object::null_type_arguments(), Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ BranchIfSmi(kInstanceReg, is_instance_lbl);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index b73de08..ff849d8 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -258,7 +258,8 @@
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = EAX;
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
- const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
+ const bool smi_is_ok =
+ smi_type.IsSubtypeOf(NNBDMode::kLegacy, type, Heap::kOld);
__ testl(kInstanceReg, compiler::Immediate(kSmiTagMask));
if (smi_is_ok) {
// Fast case for type = FutureOr<int/num/top-type>.
@@ -293,7 +294,7 @@
if (tp_argument.IsType()) {
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
- if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
+ if (object_type.IsSubtypeOf(NNBDMode::kLegacy, tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@@ -341,7 +342,8 @@
__ testl(kInstanceReg, compiler::Immediate(kSmiTagMask));
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
- if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type_class,
+ if (Class::IsSubtypeOf(NNBDMode::kLegacy, smi_class,
+ Object::null_type_arguments(), type_class,
Object::null_type_arguments(), Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ j(ZERO, is_instance_lbl);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 59af52e..1937d593 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -274,7 +274,8 @@
ASSERT(type_class.NumTypeArguments() > 0);
const Register kInstanceReg = RAX;
const Type& smi_type = Type::Handle(zone(), Type::SmiType());
- const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
+ const bool smi_is_ok =
+ smi_type.IsSubtypeOf(NNBDMode::kLegacy, type, Heap::kOld);
__ testq(kInstanceReg, compiler::Immediate(kSmiTagMask));
if (smi_is_ok) {
// Fast case for type = FutureOr<int/num/top-type>.
@@ -311,7 +312,7 @@
ASSERT(tp_argument.HasTypeClass());
// Check if type argument is dynamic, Object, or void.
const Type& object_type = Type::Handle(zone(), Type::ObjectType());
- if (object_type.IsSubtypeOf(tp_argument, Heap::kOld)) {
+ if (object_type.IsSubtypeOf(NNBDMode::kLegacy, tp_argument, Heap::kOld)) {
// Instance class test only necessary.
return GenerateSubtype1TestCacheLookup(
token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
@@ -364,7 +365,8 @@
__ testq(kInstanceReg, compiler::Immediate(kSmiTagMask));
// If instance is Smi, check directly.
const Class& smi_class = Class::Handle(zone(), Smi::Class());
- if (Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type_class,
+ if (Class::IsSubtypeOf(NNBDMode::kLegacy, smi_class,
+ Object::null_type_arguments(), type_class,
Object::null_type_arguments(), Heap::kOld)) {
// Fast case for type = int/num/top-type.
__ j(ZERO, is_instance_lbl);
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 35c221b..06000ae 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -218,7 +218,8 @@
test_succeeded = false;
} else if (use_subtype_test) {
cls_type = cls.RareType();
- test_succeeded = cls_type.IsSubtypeOf(dst_type, Heap::kNew);
+ test_succeeded =
+ cls_type.IsSubtypeOf(NNBDMode::kLegacy, dst_type, Heap::kNew);
} else {
while (!cls.IsObjectClass()) {
if (cls.raw() == klass.raw()) {
@@ -542,6 +543,16 @@
}
}
+bool Definition::IsArrayLength(Definition* def) {
+ if (def != nullptr) {
+ if (auto load = def->OriginalDefinitionIgnoreBoxingAndConstraints()
+ ->AsLoadField()) {
+ return load->IsImmutableLengthLoad();
+ }
+ }
+ return false;
+}
+
const ICData* Instruction::GetICData(
const ZoneGrowableArray<const ICData*>& ic_data_array) const {
// The deopt_id can be outside the range of the IC data array for
@@ -1004,9 +1015,9 @@
AbstractType& sub_type = AbstractType::Handle(Z, sub_type_.raw());
AbstractType& super_type = AbstractType::Handle(Z, super_type_.raw());
- if (AbstractType::InstantiateAndTestSubtype(&sub_type, &super_type,
- instantiator_type_args,
- function_type_args)) {
+ if (AbstractType::InstantiateAndTestSubtype(
+ NNBDMode::kLegacy, &sub_type, &super_type, instantiator_type_args,
+ function_type_args)) {
return NULL;
}
}
@@ -2645,7 +2656,7 @@
}
bool LoadFieldInstr::IsTypedDataViewFactory(const Function& function) {
- auto kind = MethodRecognizer::RecognizeKind(function);
+ auto kind = function.recognized_kind();
switch (kind) {
case MethodRecognizer::kTypedData_ByteDataView_factory:
case MethodRecognizer::kTypedData_Int8ArrayView_factory:
@@ -2930,9 +2941,9 @@
if ((instantiator_type_args != nullptr) && (function_type_args != nullptr)) {
AbstractType& new_dst_type = AbstractType::Handle(
- Z,
- dst_type().InstantiateFrom(*instantiator_type_args, *function_type_args,
- kAllFree, nullptr, Heap::kOld));
+ Z, dst_type().InstantiateFrom(
+ NNBDMode::kLegacy, *instantiator_type_args, *function_type_args,
+ kAllFree, nullptr, Heap::kOld));
if (new_dst_type.IsNull()) {
// Failed instantiation in dead code.
return this;
@@ -3242,7 +3253,8 @@
}
// Note that type 'Number' is a subtype of itself.
return compile_type.IsTopType() || compile_type.IsTypeParameter() ||
- compile_type.IsSubtypeOf(Type::Handle(Type::Number()), Heap::kOld);
+ compile_type.IsSubtypeOf(NNBDMode::kLegacy,
+ Type::Handle(Type::Number()), Heap::kOld);
}
// Returns a replacement for a strict comparison and signals if the result has
@@ -3734,7 +3746,7 @@
int lower_limit_cid = (idx == 0) ? -1 : targets[idx - 1].cid_end;
auto target_info = targets.TargetAt(idx);
const Function& target = *target_info->target;
- if (MethodRecognizer::PolymorphicTarget(target)) continue;
+ if (target.is_polymorphic_target()) continue;
for (int i = target_info->cid_start - 1; i > lower_limit_cid; i--) {
bool class_is_abstract = false;
if (FlowGraphCompiler::LookupMethodFor(i, name, args_desc, &fn,
@@ -3758,7 +3770,7 @@
(idx == length - 1) ? max_cid : targets[idx + 1].cid_start;
auto target_info = targets.TargetAt(idx);
const Function& target = *target_info->target;
- if (MethodRecognizer::PolymorphicTarget(target)) continue;
+ if (target.is_polymorphic_target()) continue;
// The code below makes attempt to avoid spreading class-id range
// into a suffix that consists purely of abstract classes to
// shorten the range.
@@ -3809,7 +3821,7 @@
const Function& target = *TargetAt(dest)->target;
if (TargetAt(dest)->cid_end + 1 >= TargetAt(src)->cid_start &&
target.raw() == TargetAt(src)->target->raw() &&
- !MethodRecognizer::PolymorphicTarget(target)) {
+ !target.is_polymorphic_target()) {
TargetAt(dest)->cid_end = TargetAt(src)->cid_end;
TargetAt(dest)->count += TargetAt(src)->count;
TargetAt(dest)->exactness = StaticTypeExactnessState::NotTracking();
@@ -4384,8 +4396,7 @@
bool CallTargets::HasSingleRecognizedTarget() const {
if (!HasSingleTarget()) return false;
- return MethodRecognizer::RecognizeKind(FirstTarget()) !=
- MethodRecognizer::kUnknown;
+ return FirstTarget().recognized_kind() != MethodRecognizer::kUnknown;
}
bool CallTargets::HasSingleTarget() const {
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index fc95490..b2d8e7c 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -2225,6 +2225,9 @@
// boxing/unboxing and constraint instructions.
Definition* OriginalDefinitionIgnoreBoxingAndConstraints();
+ // Helper method to determine if definition denotes an array length.
+ static bool IsArrayLength(Definition* def);
+
virtual Definition* AsDefinition() { return this; }
virtual const Definition* AsDefinition() const { return this; }
@@ -2677,8 +2680,15 @@
class ReturnInstr : public TemplateInstruction<1, NoThrow> {
public:
- ReturnInstr(TokenPosition token_pos, Value* value, intptr_t deopt_id)
- : TemplateInstruction(deopt_id), token_pos_(token_pos) {
+ // The [yield_index], if provided, will cause the instruction to emit extra
+ // yield_index -> pc offset into the [PcDescriptors].
+ ReturnInstr(TokenPosition token_pos,
+ Value* value,
+ intptr_t deopt_id,
+ intptr_t yield_index = RawPcDescriptors::kInvalidYieldIndex)
+ : TemplateInstruction(deopt_id),
+ token_pos_(token_pos),
+ yield_index_(yield_index) {
SetInputAt(0, value);
}
@@ -2686,6 +2696,7 @@
virtual TokenPosition token_pos() const { return token_pos_; }
Value* value() const { return inputs_[0]; }
+ intptr_t yield_index() const { return yield_index_; }
virtual bool CanBecomeDeoptimizationTarget() const {
// Return instruction might turn into a Goto instruction after inlining.
@@ -2697,8 +2708,17 @@
virtual bool HasUnknownSideEffects() const { return false; }
+ virtual bool AttributesEqual(Instruction* other) const {
+ auto other_return = other->AsReturn();
+ return token_pos() == other_return->token_pos() &&
+ yield_index() == other_return->yield_index();
+ }
+
+ PRINT_OPERANDS_TO_SUPPORT
+
private:
const TokenPosition token_pos_;
+ const intptr_t yield_index_;
DISALLOW_COPY_AND_ASSIGN(ReturnInstr);
};
@@ -7899,7 +7919,7 @@
// Returns true if the bounds check can be eliminated without
// changing the semantics (viz. 0 <= index < length).
- bool IsRedundant();
+ bool IsRedundant(bool use_loops = false);
// Give a name to the location/input indices.
enum { kLengthPos = 0, kIndexPos = 1 };
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 9515797..a21248b 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -139,6 +139,9 @@
__ Bind(&stack_ok);
#endif
ASSERT(__ constant_pool_allowed());
+ if (yield_index() != RawPcDescriptors::kInvalidYieldIndex) {
+ compiler->EmitYieldPositionMetadata(token_pos(), yield_index());
+ }
__ LeaveDartFrameAndReturn(); // Disallows constant pool use.
// This ReturnInstr may be emitted out of order by the optimizer. The next
// block may be a target expecting a properly set constant pool pointer.
@@ -963,19 +966,9 @@
entry = reinterpret_cast<uword>(native_c_function());
if (is_bootstrap_native()) {
stub = &StubCode::CallBootstrapNative();
-#if defined(USING_SIMULATOR)
- entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
-#endif
} else if (is_auto_scope()) {
- // In the case of non bootstrap native methods the CallNativeCFunction
- // stub generates the redirection address when running under the simulator
- // and hence we do not change 'entry' here.
stub = &StubCode::CallAutoScopeNative();
} else {
- // In the case of non bootstrap native methods the CallNativeCFunction
- // stub generates the redirection address when running under the simulator
- // and hence we do not change 'entry' here.
stub = &StubCode::CallNoScopeNative();
}
}
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index b83bf31..5f4adbd 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -138,6 +138,9 @@
__ Bind(&stack_ok);
#endif
ASSERT(__ constant_pool_allowed());
+ if (yield_index() != RawPcDescriptors::kInvalidYieldIndex) {
+ compiler->EmitYieldPositionMetadata(token_pos(), yield_index());
+ }
__ LeaveDartFrame(); // Disallows constant pool use.
__ ret();
// This ReturnInstr may be emitted out of order by the optimizer. The next
@@ -842,19 +845,9 @@
entry = reinterpret_cast<uword>(native_c_function());
if (is_bootstrap_native()) {
stub = &StubCode::CallBootstrapNative();
-#if defined(USING_SIMULATOR)
- entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
-#endif
} else if (is_auto_scope()) {
- // In the case of non bootstrap native methods the CallNativeCFunction
- // stub generates the redirection address when running under the simulator
- // and hence we do not change 'entry' here.
stub = &StubCode::CallAutoScopeNative();
} else {
- // In the case of non bootstrap native methods the CallNativeCFunction
- // stub generates the redirection address when running under the simulator
- // and hence we do not change 'entry' here.
stub = &StubCode::CallNoScopeNative();
}
}
@@ -947,10 +940,8 @@
__ blr(TMP);
}
- // Refresh write barrier mask.
- __ ldr(BARRIER_MASK,
- compiler::Address(
- THR, compiler::target::Thread::write_barrier_mask_offset()));
+ // Refresh pinned registers values (inc. write barrier mask and null object).
+ __ RestorePinnedRegisters();
// Although PP is a callee-saved register, it may have been moved by the GC.
__ LeaveDartFrame(compiler::kRestoreCallerPP);
@@ -1109,10 +1100,8 @@
// Now that we have THR, we can set CSP.
__ SetupCSPFromThread(THR);
- // Refresh write barrier mask.
- __ ldr(BARRIER_MASK,
- compiler::Address(
- THR, compiler::target::Thread::write_barrier_mask_offset()));
+ // Refresh pinned registers values (inc. write barrier mask and null object).
+ __ RestorePinnedRegisters();
// Save the current VMTag on the stack.
__ LoadFromOffset(R0, THR, compiler::target::Thread::vm_tag_offset());
diff --git a/runtime/vm/compiler/backend/il_deserializer.cc b/runtime/vm/compiler/backend/il_deserializer.cc
index 47d515a..c035dd6 100644
--- a/runtime/vm/compiler/backend/il_deserializer.cc
+++ b/runtime/vm/compiler/backend/il_deserializer.cc
@@ -1848,7 +1848,9 @@
}
// Guaranteed not to re-enter ParseType.
if (!ParseClass(cls_sexp, &type_class_)) return false;
- *out = Type::New(type_class_, *type_args_ptr, token_pos, Heap::kOld);
+ const Nullability nullability =
+ type_class_.IsNullClass() ? Nullability::kNullable : Nullability::kLegacy;
+ *out = Type::New(type_class_, *type_args_ptr, token_pos, nullability);
auto& type = Type::Cast(*out);
if (auto const sig_sexp = list->ExtraLookupValue("signature")) {
auto& function = Function::Handle(zone());
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 7af91ad..43cc2c5 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -133,6 +133,9 @@
__ int3();
__ Bind(&done);
#endif
+ if (yield_index() != RawPcDescriptors::kInvalidYieldIndex) {
+ compiler->EmitYieldPositionMetadata(token_pos(), yield_index());
+ }
__ LeaveFrame();
__ ret();
}
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 527cc9e..e2153dc 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -2,8 +2,6 @@
// 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.
-#if !defined(DART_PRECOMPILED_RUNTIME)
-
#include "vm/compiler/backend/il_printer.h"
#include "vm/compiler/backend/il.h"
@@ -15,18 +13,11 @@
#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
-DEFINE_FLAG(bool,
- display_sorted_ic_data,
- false,
- "Calls display a unary, sorted-by count form of ICData");
-DEFINE_FLAG(bool, print_environments, false, "Print SSA environments.");
DEFINE_FLAG(charp,
print_flow_graph_filter,
NULL,
"Print only IR of functions with matching names");
-DECLARE_FLAG(bool, trace_inlining_intervals);
-
// Checks whether function's name matches the given filter, which is
// a comma-separated list of strings.
bool FlowGraphPrinter::PassesFilter(const char* filter,
@@ -74,6 +65,16 @@
return PassesFilter(FLAG_print_flow_graph_filter, function);
}
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
+DEFINE_FLAG(bool,
+ display_sorted_ic_data,
+ false,
+ "Calls display a unary, sorted-by count form of ICData");
+DEFINE_FLAG(bool, print_environments, false, "Print SSA environments.");
+
+DECLARE_FLAG(bool, trace_inlining_intervals);
+
void FlowGraphPrinter::PrintGraph(const char* phase, FlowGraph* flow_graph) {
LogBlock lb;
THR_Print("*** BEGIN CFG\n%s\n", phase);
@@ -1060,6 +1061,13 @@
BlockEntryWithInitialDefs::PrintInitialDefinitionsTo(f);
}
+void ReturnInstr::PrintOperandsTo(BufferFormatter* f) const {
+ Instruction::PrintOperandsTo(f);
+ if (yield_index() != RawPcDescriptors::kInvalidYieldIndex) {
+ f->Print(", yield_index = %" Pd "", yield_index());
+ }
+}
+
void NativeReturnInstr::PrintOperandsTo(BufferFormatter* f) const {
value()->PrintTo(f);
}
@@ -1181,8 +1189,12 @@
return Thread::Current()->zone()->MakeCopyOfString(buffer);
}
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+
#else // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
const char* Instruction::ToCString() const {
return DebugName();
}
@@ -1219,8 +1231,8 @@
return false;
}
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+
#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
} // namespace dart
-
-#endif // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index b736c05..a0b64fb 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -134,6 +134,9 @@
__ Bind(&done);
#endif
ASSERT(__ constant_pool_allowed());
+ if (yield_index() != RawPcDescriptors::kInvalidYieldIndex) {
+ compiler->EmitYieldPositionMetadata(token_pos(), yield_index());
+ }
__ LeaveDartFrame(); // Disallows constant pool use.
__ ret();
// This ReturnInstr may be emitted out of order by the optimizer. The next
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 52e3cac..d06b9a1 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -1673,7 +1673,7 @@
bool PolymorphicInliner::CheckInlinedDuplicate(const Function& target) {
for (intptr_t i = 0; i < inlined_variants_.length(); ++i) {
if ((target.raw() == inlined_variants_.TargetAt(i)->target->raw()) &&
- !MethodRecognizer::PolymorphicTarget(target)) {
+ !target.is_polymorphic_target()) {
// The call target is shared with a previous inlined variant. Share
// the graph. This requires a join block at the entry, and edge-split
// form requires a target for each branch.
@@ -1805,8 +1805,7 @@
// The empty Object constructor is the only case where the inlined body is
// empty and there is no result.
ASSERT((last != nullptr && result != nullptr) ||
- MethodRecognizer::RecognizeKind(target) ==
- MethodRecognizer::kObjectConstructor);
+ (target.recognized_kind() == MethodRecognizer::kObjectConstructor));
graph_entry->set_normal_entry(entry);
// Create a graph fragment.
redefinition->InsertAfter(entry);
@@ -3321,11 +3320,10 @@
// The empty Object constructor is the only case where the inlined body is
// empty and there is no result.
ASSERT((last != nullptr && result != nullptr) ||
- MethodRecognizer::RecognizeKind(target) ==
- MethodRecognizer::kObjectConstructor);
+ (target.recognized_kind() == MethodRecognizer::kObjectConstructor));
// Determine if inlining instance methods needs a check.
FlowGraph::ToCheck check = FlowGraph::ToCheck::kNoCheck;
- if (MethodRecognizer::PolymorphicTarget(target)) {
+ if (target.is_polymorphic_target()) {
check = FlowGraph::ToCheck::kCheckCid;
} else {
check = flow_graph->CheckForInstanceCall(call, target.kind());
@@ -3409,8 +3407,8 @@
// The empty Object constructor is the only case where the inlined body is
// empty and there is no result.
ASSERT((last != nullptr && result != nullptr) ||
- MethodRecognizer::RecognizeKind(call->function()) ==
- MethodRecognizer::kObjectConstructor);
+ (call->function().recognized_kind() ==
+ MethodRecognizer::kObjectConstructor));
// Remove the original push arguments.
for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
PushArgumentInstr* push = call->PushArgumentAt(i);
@@ -3687,7 +3685,7 @@
FlowGraphInliner::ExactnessInfo* exactness) {
const bool can_speculate = policy->IsAllowedForInlining(call->deopt_id());
- const MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(target);
+ const MethodRecognizer::Kind kind = target.recognized_kind();
switch (kind) {
// Recognized [] operators.
case MethodRecognizer::kImmutableArrayGetIndexed:
diff --git a/runtime/vm/compiler/backend/loops.cc b/runtime/vm/compiler/backend/loops.cc
index 8c046a6..b8edbc0 100644
--- a/runtime/vm/compiler/backend/loops.cc
+++ b/runtime/vm/compiler/backend/loops.cc
@@ -69,6 +69,7 @@
// Transfer methods. Compute how induction of the operands, if any,
// tranfers over the operation performed by the given definition.
InductionVar* TransferPhi(LoopInfo* loop, Definition* def, intptr_t idx = -1);
+ InductionVar* TransferDef(LoopInfo* loop, Definition* def);
InductionVar* TransferBinary(LoopInfo* loop, Definition* def);
InductionVar* TransferUnary(LoopInfo* loop, Definition* def);
@@ -132,6 +133,81 @@
return false;
}
+// Helper method to determine if a non-strict (inclusive) bound on
+// a unit stride linear induction can be made strict (exclusive)
+// without arithmetic wrap-around complications.
+static bool CanBeMadeExclusive(LoopInfo* loop,
+ InductionVar* x,
+ Instruction* branch,
+ bool is_lower) {
+ InductionVar* min = nullptr;
+ InductionVar* max = nullptr;
+ if (x->CanComputeBounds(loop, branch, &min, &max)) {
+ int64_t end = 0;
+ if (is_lower) {
+ if (InductionVar::IsConstant(min, &end)) {
+ return kMinInt64 < end;
+ }
+ } else if (InductionVar::IsConstant(max, &end)) {
+ return end < kMaxInt64;
+ } else if (InductionVar::IsInvariant(max) && max->mult() == 1 &&
+ Definition::IsArrayLength(max->def())) {
+ return max->offset() < 0; // a.length - C, C > 0
+ }
+ }
+ return false;
+}
+
+// Helper method to adjust a range [lower_bound,upper_bound] into the
+// range [lower_bound+lower_bound_offset,upper_bound+upper_bound+offset]
+// without arithmetic wrap-around complications. On entry, we know that
+// lower_bound <= upper_bound is enforced by an actual comparison in the
+// code (so that even if lower_bound > upper_bound, the loop is not taken).
+// This method ensures the resulting range has the same property by
+// very conservatively testing if everything stays between constants
+// or a properly offset array length.
+static bool SafelyAdjust(Zone* zone,
+ InductionVar* lower_bound,
+ int64_t lower_bound_offset,
+ InductionVar* upper_bound,
+ int64_t upper_bound_offset,
+ InductionVar** min,
+ InductionVar** max) {
+ bool success = false;
+ int64_t lval = 0;
+ int64_t uval = 0;
+ if (InductionVar::IsConstant(lower_bound, &lval)) {
+ const int64_t l = lval + lower_bound_offset;
+ if (InductionVar::IsConstant(upper_bound, &uval)) {
+ // Make sure a proper new range [l,u] results. Even if bounds
+ // were subject to arithmetic wrap-around, we preserve the
+ // property that the minimum is in l and the maximum in u.
+ const int64_t u = uval + upper_bound_offset;
+ success = (l <= u);
+ } else if (InductionVar::IsInvariant(upper_bound) &&
+ upper_bound->mult() == 1 &&
+ Definition::IsArrayLength(upper_bound->def())) {
+ // No arithmetic wrap-around on the lower bound, and a properly
+ // non-positive offset on an array length, which is always >= 0.
+ const int64_t c = upper_bound->offset() + upper_bound_offset;
+ success = ((lower_bound_offset >= 0 && lval <= l) ||
+ (lower_bound_offset < 0 && lval > l)) &&
+ (c <= 0);
+ }
+ }
+ if (success) {
+ *min = (lower_bound_offset == 0)
+ ? lower_bound
+ : new (zone) InductionVar(lval + lower_bound_offset);
+ *max = (upper_bound_offset == 0)
+ ? upper_bound
+ : new (zone)
+ InductionVar(upper_bound->offset() + upper_bound_offset,
+ upper_bound->mult(), upper_bound->def());
+ }
+ return success;
+}
+
void InductionVarAnalysis::VisitHierarchy(LoopInfo* loop) {
for (; loop != nullptr; loop = loop->next_) {
VisitLoop(loop);
@@ -252,15 +328,8 @@
}
} else if (def->IsPhi()) {
induc = TransferPhi(loop, def);
- } else if (def->IsBinaryIntegerOp()) {
- induc = TransferBinary(loop, def);
- } else if (def->IsUnaryIntegerOp()) {
- induc = TransferUnary(loop, def);
} else {
- Definition* orig = def->OriginalDefinitionIgnoreBoxingAndConstraints();
- if (orig != def) {
- induc = Lookup(loop, orig); // pass-through
- }
+ induc = TransferDef(loop, def);
}
// Successfully classified?
if (induc != nullptr) {
@@ -373,15 +442,12 @@
} else {
continue;
}
- // Safe, strict comparison for looping condition? Note that
- // we reject symbolic bounds in non-strict looping conditions
- // like i <= U as upperbound or i >= L as lowerbound since this
- // could loop forever when U is kMaxInt64 or L is kMinInt64 under
- // Dart's 64-bit wrap-around arithmetic. Non-unit strides could
- // overshoot the bound with a wrap-around.
- //
- // TODO(ajcbik): accept more conditions when safe
- //
+ // Can we find a strict (exclusive) comparison for the looping condition?
+ // Note that we reject symbolic bounds in non-strict (inclusive) looping
+ // conditions like i <= U as upperbound or i >= L as lowerbound since this
+ // could loop forever when U is kMaxInt64 or L is kMinInt64 under Dart's
+ // 64-bit arithmetic wrap-around. Non-unit strides could overshoot the
+ // bound due to aritmetic wrap-around.
switch (cmp) {
case Token::kLT:
// Accept i < U (i++).
@@ -392,21 +458,21 @@
if (stride == -1) break;
continue;
case Token::kLTE: {
- // Accept i <= C (i++) as i < C + 1.
- int64_t end = 0;
- if (stride == 1 && InductionVar::IsConstant(y, &end) &&
- end < kMaxInt64) {
- y = new (zone_) InductionVar(end + 1);
+ // Accept i <= U (i++) as i < U + 1
+ // only when U != MaxInt is certain.
+ if (stride == 1 &&
+ CanBeMadeExclusive(loop, y, branch, /*is_lower=*/false)) {
+ y = Add(y, new (zone_) InductionVar(1));
break;
}
continue;
}
case Token::kGTE: {
- // Accept i >= C (i--) as i > C - 1.
- int64_t end = 0;
- if (stride == -1 && InductionVar::IsConstant(y, &end) &&
- kMinInt64 < end) {
- y = new (zone_) InductionVar(end - 1);
+ // Accept i >= L (i--) as i > L - 1
+ // only when L != MinInt is certain.
+ if (stride == -1 &&
+ CanBeMadeExclusive(loop, y, branch, /*is_lower=*/true)) {
+ y = Sub(y, new (zone_) InductionVar(1));
break;
}
continue;
@@ -427,9 +493,10 @@
default:
continue;
}
- // We found a safe limit on the induction variable. Note that depending
- // on the intended use of this information, clients should still test
- // dominance on the test and the initial value of the induction variable.
+ // We found a strict upper or lower bound on a unit stride linear
+ // induction. Note that depending on the intended use of this
+ // information, clients should still test dominance on the test
+ // and the initial value of the induction variable.
x->bounds_.Add(InductionVar::Bound(branch, y));
// Record control induction.
if (branch == loop->header_->last_instruction()) {
@@ -457,6 +524,33 @@
return induc;
}
+InductionVar* InductionVarAnalysis::TransferDef(LoopInfo* loop,
+ Definition* def) {
+ if (def->IsBinaryIntegerOp()) {
+ return TransferBinary(loop, def);
+ } else if (def->IsUnaryIntegerOp()) {
+ return TransferUnary(loop, def);
+ } else {
+ // Note that induction analysis does not really need the second
+ // argument of a bound check, since it will just pass-through the
+ // index. However, we do a lookup on the, most likely loop-invariant,
+ // length anyway, to make sure it is stored in the induction
+ // environment for later lookup during BCE.
+ if (auto check = def->AsCheckBoundBase()) {
+ Definition* len = check->length()
+ ->definition()
+ ->OriginalDefinitionIgnoreBoxingAndConstraints();
+ Lookup(loop, len); // pre-store likely invariant length
+ }
+ // Proceed with regular pass-through.
+ Definition* orig = def->OriginalDefinitionIgnoreBoxingAndConstraints();
+ if (orig != def) {
+ return Lookup(loop, orig); // pass-through
+ }
+ }
+ return nullptr;
+}
+
InductionVar* InductionVarAnalysis::TransferBinary(LoopInfo* loop,
Definition* def) {
InductionVar* x = Lookup(loop, def->InputAt(0)->definition());
@@ -605,7 +699,12 @@
induc = new (zone_) InductionVar(val);
loop->AddInduction(def, induc);
} else if (!loop->Contains(def->GetBlock())) {
- induc = new (zone_) InductionVar(0, 1, def);
+ // Look "under the hood" of invariant definitions to expose
+ // more details on common constructs like "length - 1".
+ induc = TransferDef(loop, def);
+ if (induc == nullptr) {
+ induc = new (zone_) InductionVar(0, 1, def);
+ }
loop->AddInduction(def, induc);
}
}
@@ -734,6 +833,116 @@
return nullptr;
}
+bool InductionVar::CanComputeDifferenceWith(const InductionVar* other,
+ int64_t* diff) const {
+ if (IsInvariant(this) && IsInvariant(other)) {
+ if (def_ == other->def_ && mult_ == other->mult_) {
+ *diff = other->offset_ - offset_;
+ return true;
+ }
+ } else if (IsLinear(this) && IsLinear(other)) {
+ return next_->IsEqual(other->next_) &&
+ initial_->CanComputeDifferenceWith(other->initial_, diff);
+ }
+ // TODO(ajcbik): examine other induction kinds too?
+ return false;
+}
+
+bool InductionVar::CanComputeBoundsImpl(LoopInfo* loop,
+ Instruction* pos,
+ InductionVar** min,
+ InductionVar** max) {
+ // Refine symbolic part of an invariant with outward induction.
+ if (IsInvariant(this)) {
+ if (mult_ == 1 && def_ != nullptr) {
+ for (loop = loop->outer(); loop != nullptr; loop = loop->outer()) {
+ InductionVar* induc = loop->LookupInduction(def_);
+ InductionVar* i_min = nullptr;
+ InductionVar* i_max = nullptr;
+ // Accept i+C with i in [L,U] as [L+C,U+C] when this adjustment
+ // does not have arithmetic wrap-around complications.
+ if (IsInduction(induc) &&
+ induc->CanComputeBounds(loop, pos, &i_min, &i_max)) {
+ Zone* z = Thread::Current()->zone();
+ return SafelyAdjust(z, i_min, offset_, i_max, offset_, min, max);
+ }
+ }
+ }
+ // Otherwise invariant itself suffices.
+ *min = *max = this;
+ return true;
+ }
+ // Refine unit stride induction with lower and upper bound.
+ // for (int i = L; i < U; i++)
+ // j = i+C in [L+C,U+C-1]
+ int64_t stride = 0;
+ int64_t off = 0;
+ if (IsLinear(this, &stride) && Utils::Abs(stride) == 1 &&
+ CanComputeDifferenceWith(loop->control(), &off)) {
+ // Find ranges on both L and U first (and not just minimum
+ // of L and maximum of U) to avoid arithmetic wrap-around
+ // complications such as the one shown below.
+ // for (int i = 0; i < maxint - 10; i++)
+ // for (int j = i + 20; j < 100; j++)
+ // j in [minint, 99] and not in [20, 100]
+ InductionVar* l_min = nullptr;
+ InductionVar* l_max = nullptr;
+ if (initial_->CanComputeBounds(loop, pos, &l_min, &l_max)) {
+ // Find extreme using a control bound for which the branch dominates
+ // the given position (to make sure it really is under its control).
+ // Then refine with anything that dominates that branch.
+ for (auto bound : loop->control()->bounds()) {
+ if (pos->IsDominatedBy(bound.branch_)) {
+ InductionVar* u_min = nullptr;
+ InductionVar* u_max = nullptr;
+ if (bound.limit_->CanComputeBounds(loop, bound.branch_, &u_min,
+ &u_max)) {
+ Zone* z = Thread::Current()->zone();
+ return stride > 0 ? SafelyAdjust(z, l_min, 0, u_max, -stride - off,
+ min, max)
+ : SafelyAdjust(z, u_min, -stride - off, l_max, 0,
+ min, max);
+ }
+ }
+ }
+ }
+ }
+ // Failure. TODO(ajcbik): examine other kinds of induction too?
+ return false;
+}
+
+// Driver method to compute bounds with per-loop memoization.
+bool InductionVar::CanComputeBounds(LoopInfo* loop,
+ Instruction* pos,
+ InductionVar** min,
+ InductionVar** max) {
+ // Consult cache first.
+ LoopInfo::MemoKV::Pair* pair1 = loop->memo_cache_.Lookup(this);
+ if (pair1 != nullptr) {
+ LoopInfo::MemoVal::PosKV::Pair* pair2 = pair1->value->memo_.Lookup(pos);
+ if (pair2 != nullptr) {
+ *min = pair2->value.first;
+ *max = pair2->value.second;
+ return true;
+ }
+ }
+ // Compute and cache.
+ if (CanComputeBoundsImpl(loop, pos, min, max)) {
+ ASSERT(*min != nullptr && *max != nullptr);
+ LoopInfo::MemoVal* memo = nullptr;
+ if (pair1 != nullptr) {
+ memo = pair1->value;
+ } else {
+ memo = new LoopInfo::MemoVal();
+ loop->memo_cache_.Insert(LoopInfo::MemoKV::Pair(this, memo));
+ }
+ memo->memo_.Insert(
+ LoopInfo::MemoVal::PosKV::Pair(pos, std::make_pair(*min, *max)));
+ return true;
+ }
+ return false;
+}
+
const char* InductionVar::ToCString() const {
char buffer[1024];
BufferFormatter f(buffer, sizeof(buffer));
@@ -765,6 +974,7 @@
blocks_(blocks),
back_edges_(),
induction_(),
+ memo_cache_(),
limit_(nullptr),
control_(nullptr),
outer_(nullptr),
@@ -850,6 +1060,7 @@
void LoopInfo::ResetInduction() {
induction_.Clear();
+ memo_cache_.Clear();
}
void LoopInfo::AddInduction(Definition* def, InductionVar* induc) {
@@ -866,6 +1077,43 @@
return nullptr;
}
+// Checks if an index is in range of a given length:
+// for (int i = initial; i <= length - C; i++) {
+// .... a[i] .... // initial >= 0 and C > 0:
+// }
+bool LoopInfo::IsInRange(Instruction* pos, Value* index, Value* length) {
+ InductionVar* induc = LookupInduction(
+ index->definition()->OriginalDefinitionIgnoreBoxingAndConstraints());
+ InductionVar* len = LookupInduction(
+ length->definition()->OriginalDefinitionIgnoreBoxingAndConstraints());
+ if (induc != nullptr && len != nullptr) {
+ // First, try the most common case. A simple induction directly
+ // bounded by [c>=0,length-C>=0) for the length we are looking for.
+ int64_t stride = 0;
+ int64_t val = 0;
+ int64_t diff = 0;
+ if (InductionVar::IsLinear(induc, &stride) && stride == 1 &&
+ InductionVar::IsConstant(induc->initial(), &val) && 0 <= val) {
+ for (auto bound : induc->bounds()) {
+ if (pos->IsDominatedBy(bound.branch_) &&
+ len->CanComputeDifferenceWith(bound.limit_, &diff) && diff <= 0) {
+ return true;
+ }
+ }
+ }
+ // If that fails, try to compute bounds using more outer loops.
+ // Since array lengths >= 0, the conditions used during this
+ // process avoid arithmetic wrap-around complications.
+ InductionVar* min = nullptr;
+ InductionVar* max = nullptr;
+ if (induc->CanComputeBounds(this, pos, &min, &max)) {
+ return InductionVar::IsConstant(min, &val) && 0 <= val &&
+ len->CanComputeDifferenceWith(max, &diff) && diff < 0;
+ }
+ }
+ return false;
+}
+
const char* LoopInfo::ToCString() const {
char buffer[1024];
BufferFormatter f(buffer, sizeof(buffer));
@@ -928,7 +1176,7 @@
}
}
-void LoopHierarchy::Print(LoopInfo* loop) {
+void LoopHierarchy::Print(LoopInfo* loop) const {
for (; loop != nullptr; loop = loop->next_) {
THR_Print("%s {", loop->ToCString());
for (BitVector::Iterator it(loop->blocks_); !it.Done(); it.Advance()) {
diff --git a/runtime/vm/compiler/backend/loops.h b/runtime/vm/compiler/backend/loops.h
index 215d26f..79f0e90 100644
--- a/runtime/vm/compiler/backend/loops.h
+++ b/runtime/vm/compiler/backend/loops.h
@@ -5,6 +5,8 @@
#ifndef RUNTIME_VM_COMPILER_BACKEND_LOOPS_H_
#define RUNTIME_VM_COMPILER_BACKEND_LOOPS_H_
+#include <utility>
+
#include "vm/allocation.h"
#include "vm/compiler/backend/il.h"
@@ -31,7 +33,7 @@
kPeriodic,
};
- // Strict bound on unit stride linear induction:
+ // Strict (exclusive) upper or lower bound on unit stride linear induction:
// i < U (i++)
// i > L (i--)
struct Bound {
@@ -42,14 +44,14 @@
// Constructor for an invariant.
InductionVar(int64_t offset, int64_t mult, Definition* def)
- : kind_(kInvariant), offset_(offset), mult_(mult), def_(def) {}
+ : kind_(kInvariant), offset_(offset), mult_(mult), def_(def), bounds_() {}
// Constructor for a constant.
explicit InductionVar(int64_t offset) : InductionVar(offset, 0, nullptr) {}
// Constructor for an induction.
InductionVar(Kind kind, InductionVar* initial, InductionVar* next)
- : kind_(kind), initial_(initial), next_(next) {
+ : kind_(kind), initial_(initial), next_(next), bounds_() {
ASSERT(IsInvariant(initial));
switch (kind) {
case kLinear:
@@ -65,7 +67,7 @@
}
// Returns true if the other induction is structually equivalent.
- bool IsEqual(InductionVar* other) const {
+ bool IsEqual(const InductionVar* other) const {
ASSERT(other != nullptr);
if (kind_ == other->kind_) {
switch (kind_) {
@@ -82,6 +84,19 @@
return false;
}
+ // Returns true if a fixed difference between this and the other induction
+ // can be computed. Sets the output parameter diff on success.
+ bool CanComputeDifferenceWith(const InductionVar* other, int64_t* diff) const;
+
+ // Returns true if this induction in the given loop can be bounded as
+ // min <= this <= max by using bounds of more outer loops. On success
+ // the output parameters min and max are set, which are always loop
+ // invariant expressions inside the given loop.
+ bool CanComputeBounds(LoopInfo* loop,
+ Instruction* pos,
+ InductionVar** min,
+ InductionVar** max);
+
// Getters.
Kind kind() const { return kind_; }
int64_t offset() const {
@@ -110,17 +125,17 @@
const char* ToCString() const;
// Returns true if x is invariant.
- static bool IsInvariant(InductionVar* x) {
+ static bool IsInvariant(const InductionVar* x) {
return x != nullptr && x->kind_ == kInvariant;
}
// Returns true if x is a constant (and invariant).
- static bool IsConstant(InductionVar* x) {
+ static bool IsConstant(const InductionVar* x) {
return x != nullptr && x->kind_ == kInvariant && x->mult_ == 0;
}
// Returns true if x is a constant. Sets the value.
- static bool IsConstant(InductionVar* x, int64_t* c) {
+ static bool IsConstant(const InductionVar* x, int64_t* c) {
if (IsConstant(x)) {
*c = x->offset_;
return true;
@@ -129,12 +144,12 @@
}
// Returns true if x is linear.
- static bool IsLinear(InductionVar* x) {
+ static bool IsLinear(const InductionVar* x) {
return x != nullptr && x->kind_ == kLinear;
}
// Returns true if x is linear with constant stride. Sets the stride.
- static bool IsLinear(InductionVar* x, int64_t* s) {
+ static bool IsLinear(const InductionVar* x, int64_t* s) {
if (IsLinear(x)) {
return IsConstant(x->next_, s);
}
@@ -142,17 +157,17 @@
}
// Returns true if x is wrap-around.
- static bool IsWrapAround(InductionVar* x) {
+ static bool IsWrapAround(const InductionVar* x) {
return x != nullptr && x->kind_ == kWrapAround;
}
// Returns true if x is periodic.
- static bool IsPeriodic(InductionVar* x) {
+ static bool IsPeriodic(const InductionVar* x) {
return x != nullptr && x->kind_ == kPeriodic;
}
// Returns true if x is any induction.
- static bool IsInduction(InductionVar* x) {
+ static bool IsInduction(const InductionVar* x) {
return x != nullptr && x->kind_ != kInvariant;
}
@@ -173,6 +188,11 @@
};
};
+ bool CanComputeBoundsImpl(LoopInfo* loop,
+ Instruction* pos,
+ InductionVar** min,
+ InductionVar** max);
+
// Bounds on induction.
GrowableArray<Bound> bounds_;
@@ -217,6 +237,9 @@
// Looks up induction.
InductionVar* LookupInduction(Definition* def) const;
+ // Tests if index stays in [0,length) range in this loop at given position.
+ bool IsInRange(Instruction* pos, Value* index, Value* length);
+
// Getters.
intptr_t id() const { return id_; }
BlockEntryInstr* header() const { return header_; }
@@ -232,11 +255,24 @@
const char* ToCString() const;
private:
+ friend class InductionVar;
friend class InductionVarAnalysis;
friend class LoopHierarchy;
+ // Mapping from definition to induction.
typedef RawPointerKeyValueTrait<Definition, InductionVar*> InductionKV;
+ // Mapping from induction to mapping from instruction to induction pair.
+ class MemoVal : public ZoneAllocated {
+ public:
+ typedef RawPointerKeyValueTrait<Instruction,
+ std::pair<InductionVar*, InductionVar*>>
+ PosKV;
+ MemoVal() : memo_() {}
+ DirectChainedHashMap<PosKV> memo_;
+ };
+ typedef RawPointerKeyValueTrait<InductionVar, MemoVal*> MemoKV;
+
// Unique id of loop. We use its index in the
// loop header array for this.
const intptr_t id_;
@@ -254,6 +290,10 @@
// Map definition -> induction for this loop.
DirectChainedHashMap<InductionKV> induction_;
+ // A small, per-loop memoization cache, to avoid costly
+ // recomputations while traversing very deeply nested loops.
+ DirectChainedHashMap<MemoKV> memo_cache_;
+
// Constraint on a header phi.
// TODO(ajcbik): very specific to smi range analysis,
// should we really store it here?
@@ -290,7 +330,7 @@
private:
void Build();
- void Print(LoopInfo* loop);
+ void Print(LoopInfo* loop) const;
ZoneGrowableArray<BlockEntryInstr*>* headers_;
const GrowableArray<BlockEntryInstr*>& preorder_;
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 09d8b41..0178cbd 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -970,14 +970,22 @@
return nullptr;
}
- // Reconstruct invariant (phi-init is always already in the graph).
+ // Reconstruct invariant.
Definition* GenerateInvariant(InductionVar* induc) {
+ Definition* res = nullptr;
if (induc->mult() == 0) {
- return flow_graph_->GetConstant(
- Smi::ZoneHandle(Smi::New(induc->offset())));
+ res =
+ flow_graph_->GetConstant(Smi::ZoneHandle(Smi::New(induc->offset())));
+ } else {
+ res = induc->def();
+ if (induc->mult() != 1) {
+ res = MakeBinaryOp(Token::kMUL, res, induc->mult());
+ }
+ if (induc->offset() != 0) {
+ res = MakeBinaryOp(Token::kADD, res, induc->offset());
+ }
}
- ASSERT(induc->offset() == 0 && induc->mult() == 1);
- return induc->def();
+ return res;
}
// Construct symbolic bound for a value at the given point:
@@ -1337,7 +1345,7 @@
!function.ProhibitsBoundsCheckGeneralization();
BoundsCheckGeneralizer generalizer(this, flow_graph_);
for (CheckBoundBase* check : bounds_checks_) {
- if (check->IsRedundant()) {
+ if (check->IsRedundant(/*use_loops=*/true)) {
check->ReplaceUsesWith(check->index()->definition());
check->RemoveFromGraph();
} else if (try_generalization) {
@@ -2215,14 +2223,6 @@
RangeBoundary::FromConstant((static_cast<uint64_t>(1) << bitsize) - 1);
}
-static bool IsArrayLength(Definition* defn) {
- if (defn == NULL) {
- return false;
- }
- LoadFieldInstr* load = UnwrapConstraint(defn)->AsLoadField();
- return (load != NULL) && load->IsImmutableLengthLoad();
-}
-
void Range::Add(const Range* left_range,
const Range* right_range,
RangeBoundary* result_min,
@@ -2233,11 +2233,11 @@
ASSERT(result_min != NULL);
ASSERT(result_max != NULL);
- RangeBoundary left_min = IsArrayLength(left_defn)
+ RangeBoundary left_min = Definition::IsArrayLength(left_defn)
? RangeBoundary::FromDefinition(left_defn)
: left_range->min();
- RangeBoundary left_max = IsArrayLength(left_defn)
+ RangeBoundary left_max = Definition::IsArrayLength(left_defn)
? RangeBoundary::FromDefinition(left_defn)
: left_range->max();
@@ -2263,11 +2263,11 @@
ASSERT(result_min != NULL);
ASSERT(result_max != NULL);
- RangeBoundary left_min = IsArrayLength(left_defn)
+ RangeBoundary left_min = Definition::IsArrayLength(left_defn)
? RangeBoundary::FromDefinition(left_defn)
: left_range->min();
- RangeBoundary left_max = IsArrayLength(left_defn)
+ RangeBoundary left_max = Definition::IsArrayLength(left_defn)
? RangeBoundary::FromDefinition(left_defn)
: left_range->max();
@@ -3015,59 +3015,17 @@
return false;
}
-// Check if range boundary and invariant limit are the same boundary.
-static bool IsSameBound(const RangeBoundary& a, InductionVar* b) {
- ASSERT(InductionVar::IsInvariant(b));
- if (a.IsSymbol()) {
- // Check for exactly the same symbol as length.
- return a.symbol() == b->def() && b->mult() == 1 &&
- a.offset() == b->offset();
- } else if (a.IsConstant()) {
- // Check for constant in right range 0 < c <= length.
- int64_t c = 0;
- return InductionVar::IsConstant(b, &c) && 0 < c && c <= a.ConstantValue();
- }
- return false;
-}
-
-bool CheckBoundBase::IsRedundant() {
+bool CheckBoundBase::IsRedundant(bool use_loops) {
// First, try to prove redundancy with the results of range analysis.
if (IsRedundantBasedOnRangeInformation(index(), length())) {
return true;
- } else if (previous() == nullptr) {
- return false; // check is not in flow graph yet
+ } else if (!use_loops) {
+ return false;
}
// Next, try to prove redundancy with the results of induction analysis.
- // Under 64-bit wrap-around arithmetic, it is always safe to remove the
- // bounds check from the following loop, if initial >= 0 and the loop
- // exit branch dominates the bounds check:
- //
- // for (int i = initial; i < length; i++)
- // .... a[i] ....
- //
LoopInfo* loop = GetBlock()->loop_info();
if (loop != nullptr) {
- InductionVar* induc = loop->LookupInduction(index()->definition());
- if (induc != nullptr) {
- int64_t stride = 0;
- int64_t initial = 0;
- if (InductionVar::IsLinear(induc, &stride) &&
- InductionVar::IsConstant(induc->initial(), &initial)) {
- if (stride == 1 && initial >= 0) {
- // Deeply trace back the range of the array length.
- RangeBoundary deep_length = RangeBoundary::FromDefinition(
- length()
- ->definition()
- ->OriginalDefinitionIgnoreBoxingAndConstraints());
- for (auto bound : induc->bounds()) {
- if (IsSameBound(deep_length, bound.limit_) &&
- this->IsDominatedBy(bound.branch_)) {
- return true;
- }
- }
- }
- }
- }
+ return loop->IsInRange(this, index(), length());
}
return false;
}
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 8b14388..bd7d94b 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -212,13 +212,22 @@
}
}
- const Slot& slot = SlotCache::Instance(thread).Canonicalize(
- Slot(Kind::kDartField,
- IsImmutableBit::encode(field.is_final() || field.is_const()) |
- IsNullableBit::encode(is_nullable) |
- IsGuardedBit::encode(used_guarded_state),
- nullable_cid, compiler::target::Field::OffsetOf(field), &field,
- &AbstractType::ZoneHandle(zone, field.type())));
+ AbstractType& type = AbstractType::ZoneHandle(zone, field.type());
+
+ if (field.needs_load_guard()) {
+ // Should be kept in sync with LoadStaticFieldInstr::ComputeType.
+ type = Type::DynamicType();
+ nullable_cid = kDynamicCid;
+ is_nullable = true;
+ used_guarded_state = false;
+ }
+
+ const Slot& slot = SlotCache::Instance(thread).Canonicalize(Slot(
+ Kind::kDartField,
+ IsImmutableBit::encode(field.is_final() || field.is_const()) |
+ IsNullableBit::encode(is_nullable) |
+ IsGuardedBit::encode(used_guarded_state),
+ nullable_cid, compiler::target::Field::OffsetOf(field), &field, &type));
// If properties of this slot were based on the guarded state make sure
// to add the field to the list of guarded fields. Note that during background
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index bbf2391..99460c1 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -554,10 +554,12 @@
}
const AbstractType* other_abstract_type = other->ToAbstractType();
- if (abstract_type->IsSubtypeOf(*other_abstract_type, Heap::kOld)) {
+ if (abstract_type->IsSubtypeOf(NNBDMode::kLegacy, *other_abstract_type,
+ Heap::kOld)) {
type_ = other_abstract_type;
return;
- } else if (other_abstract_type->IsSubtypeOf(*abstract_type, Heap::kOld)) {
+ } else if (other_abstract_type->IsSubtypeOf(NNBDMode::kLegacy, *abstract_type,
+ Heap::kOld)) {
return; // Nothing to do.
}
@@ -567,7 +569,8 @@
Class& cls = Class::Handle(abstract_type->type_class());
for (; !cls.IsNull() && !cls.IsGeneric(); cls = cls.SuperClass()) {
type_ = &AbstractType::ZoneHandle(cls.RareType());
- if (other_abstract_type->IsSubtypeOf(*type_, Heap::kOld)) {
+ if (other_abstract_type->IsSubtypeOf(NNBDMode::kLegacy, *type_,
+ Heap::kOld)) {
// Found suitable supertype: keep type_ only.
cid_ = kDynamicCid;
return;
@@ -607,7 +610,8 @@
const AbstractType* new_abstract_type = new_type->ToAbstractType();
CompileType* preferred_type;
- if (old_abstract_type->IsSubtypeOf(*new_abstract_type, Heap::kOld)) {
+ if (old_abstract_type->IsSubtypeOf(NNBDMode::kLegacy, *new_abstract_type,
+ Heap::kOld)) {
// Prefer old type, as it is clearly more specific.
preferred_type = old_type;
} else {
@@ -776,11 +780,7 @@
Isolate* I = Isolate::Current();
const Class& type_class = Class::Handle(I->class_table()->At(cid_));
- if (type_class.NumTypeArguments() > 0) {
- type_ = &AbstractType::ZoneHandle(type_class.RareType());
- } else {
- type_ = &Type::ZoneHandle(Type::NewNonParameterizedType(type_class));
- }
+ type_ = &AbstractType::ZoneHandle(type_class.RareType());
}
return type_;
@@ -818,7 +818,7 @@
return false;
}
- *is_instance = compile_type.IsSubtypeOf(type, Heap::kOld);
+ *is_instance = compile_type.IsSubtypeOf(NNBDMode::kLegacy, type, Heap::kOld);
return *is_instance;
}
@@ -827,7 +827,7 @@
return false;
}
- return ToAbstractType()->IsSubtypeOf(other, Heap::kOld);
+ return ToAbstractType()->IsSubtypeOf(NNBDMode::kLegacy, other, Heap::kOld);
}
void CompileType::PrintTo(BufferFormatter* f) const {
@@ -1375,6 +1375,11 @@
is_nullable = field.is_nullable();
abstract_type = nullptr; // Cid is known, calculate abstract type lazily.
}
+ if (field.needs_load_guard()) {
+ // Should be kept in sync with Slot::Get.
+ DEBUG_ASSERT(Isolate::Current()->HasAttemptedReload());
+ return CompileType::Dynamic();
+ }
return CompileType(is_nullable, cid, abstract_type);
}
diff --git a/runtime/vm/compiler/backend/yield_position_test.cc b/runtime/vm/compiler/backend/yield_position_test.cc
new file mode 100644
index 0000000..7707468
--- /dev/null
+++ b/runtime/vm/compiler/backend/yield_position_test.cc
@@ -0,0 +1,132 @@
+// Copyright (c) 2019, 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.
+
+#include <utility>
+
+#include "vm/compiler/backend/il_test_helper.h"
+#include "vm/compiler/compiler_pass.h"
+#include "vm/object.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+using Pair = std::pair<intptr_t, TokenPosition>;
+using YieldPoints = ZoneGrowableArray<Pair>;
+
+int LowestFirst(const Pair* a, const Pair* b) {
+ return a->first - b->first;
+}
+
+static YieldPoints* GetYieldPointsFromGraph(FlowGraph* flow_graph) {
+ auto array = new (flow_graph->zone()) YieldPoints();
+ const auto& blocks = flow_graph->reverse_postorder();
+ for (auto block : blocks) {
+ ForwardInstructionIterator it(block);
+ while (!it.Done()) {
+ if (auto return_instr = it.Current()->AsReturn()) {
+ if (return_instr->yield_index() !=
+ RawPcDescriptors::kInvalidYieldIndex) {
+ ASSERT(return_instr->yield_index() > 0);
+ array->Add(
+ Pair(return_instr->yield_index(), return_instr->token_pos()));
+ }
+ }
+ it.Advance();
+ }
+ }
+ array->Sort(LowestFirst);
+ return array;
+}
+
+static YieldPoints* GetYieldPointsFromCode(const Code& code) {
+ auto array = new YieldPoints();
+ const auto& pc_descriptor = PcDescriptors::Handle(code.pc_descriptors());
+ PcDescriptors::Iterator it(pc_descriptor, RawPcDescriptors::kOther);
+ while (it.MoveNext()) {
+ if (it.YieldIndex() != RawPcDescriptors::kInvalidYieldIndex) {
+ array->Add(Pair(it.YieldIndex(), it.TokenPos()));
+ }
+ }
+ array->Sort(LowestFirst);
+ return array;
+}
+
+void RunTestInMode(CompilerPass::PipelineMode mode) {
+ const char* kScript =
+ R"(
+ import 'dart:async';
+
+ Future foo() async {
+ print('pos-0');
+ await 0;
+ print('pos-1');
+ await 1;
+ print('pos-2');
+ await 2;
+ }
+ )";
+
+ SetupCoreLibrariesForUnitTest();
+
+ const auto& root_library = Library::Handle(LoadTestScript(kScript));
+ // Ensure the outer function was compiled once, ensuring we have a closure
+ // function for the inner closure.
+ Invoke(root_library, "foo");
+
+ const auto& outer_function =
+ Function::Handle(GetFunction(root_library, "foo"));
+
+ // Grab the inner, lazily created, closure from the object store.
+ const auto& closures = GrowableObjectArray::Handle(
+ Isolate::Current()->object_store()->closure_functions());
+ ASSERT(!closures.IsNull());
+ auto& closure = Object::Handle();
+ for (intptr_t i = 0; i < closures.Length(); ++i) {
+ closure = closures.At(i);
+ if (Function::Cast(closure).parent_function() == outer_function.raw()) {
+ break;
+ }
+ closure = Object::null();
+ }
+ RELEASE_ASSERT(closure.IsFunction());
+ const auto& function = Function::Cast(closure);
+
+ // Ensure we have 3 different return instructions with yield indices attached
+ // to them.
+ TestPipeline pipeline(function, mode);
+ FlowGraph* flow_graph = pipeline.RunPasses({
+ CompilerPass::kComputeSSA,
+ });
+
+ auto validate_indices = [](const YieldPoints& yield_points) {
+ EXPECT_EQ(3, yield_points.length());
+
+ EXPECT_EQ(1, yield_points[0].first);
+ EXPECT_EQ(88, yield_points[0].second.value());
+ EXPECT_EQ(2, yield_points[1].first);
+ EXPECT_EQ(129, yield_points[1].second.value());
+ EXPECT_EQ(3, yield_points[2].first);
+ EXPECT_EQ(170, yield_points[2].second.value());
+ };
+
+ validate_indices(*GetYieldPointsFromGraph(flow_graph));
+
+ // Ensure we have 3 different yield indices attached to the code via pc
+ // descriptors.
+ const auto& error = Error::Handle(
+ Compiler::EnsureUnoptimizedCode(Thread::Current(), function));
+ RELEASE_ASSERT(error.IsNull());
+ const auto& code = Code::Handle(function.CurrentCode());
+ validate_indices(*GetYieldPointsFromCode(code));
+}
+
+ISOLATE_UNIT_TEST_CASE(IRTest_YieldIndexAvailableJIT) {
+ RunTestInMode(CompilerPass::kJIT);
+}
+
+ISOLATE_UNIT_TEST_CASE(IRTest_YieldIndexAvailableAOT) {
+ RunTestInMode(CompilerPass::kAOT);
+}
+
+} // namespace dart
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 9fd7c9d..34c9bc0 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -988,8 +988,7 @@
const Function& target = targets.FirstTarget();
intptr_t receiver_cid = targets.MonomorphicReceiverCid();
- MethodRecognizer::Kind recognized_kind =
- MethodRecognizer::RecognizeKind(target);
+ MethodRecognizer::Kind recognized_kind = target.recognized_kind();
if (CanUnboxDouble() &&
(recognized_kind == MethodRecognizer::kIntegerToDouble)) {
@@ -1108,7 +1107,8 @@
cls.IsNullClass()
? (type_class.IsNullClass() || type_class.IsObjectClass() ||
type_class.IsDynamicClass())
- : Class::IsSubtypeOf(cls, Object::null_type_arguments(), type_class,
+ : Class::IsSubtypeOf(NNBDMode::kLegacy, cls,
+ Object::null_type_arguments(), type_class,
Object::null_type_arguments(), Heap::kOld);
results->Add(cls.id());
results->Add(static_cast<intptr_t>(is_subtype));
@@ -1308,8 +1308,7 @@
if (speculative_policy_->IsAllowedForInlining(call->deopt_id())) {
// Only if speculative inlining is enabled.
- MethodRecognizer::Kind recognized_kind =
- MethodRecognizer::RecognizeKind(call->function());
+ MethodRecognizer::Kind recognized_kind = call->function().recognized_kind();
const CallTargets& targets = call->Targets();
const BinaryFeedback& binary_feedback = call->BinaryFeedback();
@@ -1422,9 +1421,9 @@
if ((*results)[0] != kSmiCid) {
const Class& smi_class = Class::Handle(class_table.At(kSmiCid));
const Class& type_class = Class::Handle(type.type_class());
- const bool smi_is_subtype =
- Class::IsSubtypeOf(smi_class, Object::null_type_arguments(), type_class,
- Object::null_type_arguments(), Heap::kOld);
+ const bool smi_is_subtype = Class::IsSubtypeOf(
+ NNBDMode::kLegacy, smi_class, Object::null_type_arguments(), type_class,
+ Object::null_type_arguments(), Heap::kOld);
results->Add((*results)[results->length() - 2]);
results->Add((*results)[results->length() - 2]);
for (intptr_t i = results->length() - 3; i > 1; --i) {
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index 3324814..6f92238 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -169,5 +169,6 @@
"backend/slot_test.cc",
"backend/type_propagator_test.cc",
"backend/typed_data_aot_test.cc",
+ "backend/yield_position_test.cc",
"cha_test.cc",
]
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 9b216a9..9425b5c 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -186,14 +186,15 @@
return Fragment(branch).closed();
}
-Fragment BaseFlowGraphBuilder::Return(TokenPosition position) {
+Fragment BaseFlowGraphBuilder::Return(TokenPosition position,
+ intptr_t yield_index) {
Fragment instructions;
Value* value = Pop();
ASSERT(stack_ == nullptr);
ReturnInstr* return_instr =
- new (Z) ReturnInstr(position, value, GetNextDeoptId());
+ new (Z) ReturnInstr(position, value, GetNextDeoptId(), yield_index);
if (exit_collector_ != nullptr) exit_collector_->AddExit(return_instr);
instructions <<= return_instr;
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index dc8043b..fe89441 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -267,7 +267,8 @@
bool negate = false);
Fragment BranchIfStrictEqual(TargetEntryInstr** then_entry,
TargetEntryInstr** otherwise_entry);
- Fragment Return(TokenPosition position);
+ Fragment Return(TokenPosition position,
+ intptr_t yield_index = RawPcDescriptors::kInvalidYieldIndex);
Fragment CheckStackOverflow(TokenPosition position,
intptr_t stack_depth,
intptr_t loop_depth);
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 2e8c237..9eb722f 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -842,8 +842,7 @@
const Function& target = Function::Cast(ConstantAt(DecodeOperandD()).value());
const intptr_t argc = DecodeOperandF().value();
- const auto recognized_kind = MethodRecognizer::RecognizeKind(target);
- switch (recognized_kind) {
+ switch (target.recognized_kind()) {
case MethodRecognizer::kFfiAsFunctionInternal:
BuildFfiAsFunction();
return;
@@ -1329,6 +1328,15 @@
field, StoreInstanceFieldInstr::Kind::kInitializing, kNoStoreBarrier);
}
+void BytecodeFlowGraphBuilder::BuildPushUninitializedSentinel() {
+ code_ += B->Constant(Object::sentinel());
+}
+
+void BytecodeFlowGraphBuilder::BuildJumpIfInitialized() {
+ code_ += B->Constant(Object::sentinel());
+ BuildJumpIfStrictCompare(Token::kNE);
+}
+
void BytecodeFlowGraphBuilder::BuildLoadStatic() {
const Constant operand = ConstantAt(DecodeOperandD());
const auto& field = Field::Cast(operand.value());
@@ -1660,7 +1668,15 @@
BuildDebugStepCheck();
LoadStackSlots(1);
ASSERT(code_.is_open());
- code_ += B->Return(position_);
+ intptr_t yield_index = RawPcDescriptors::kInvalidYieldIndex;
+ if (function().IsAsyncClosure() || function().IsAsyncGenClosure()) {
+ if (pc_ == last_yield_point_pc_) {
+ // The return might actually be a yield point, if so we need to attach the
+ // yield index to the return instruction.
+ yield_index = last_yield_point_index_;
+ }
+ }
+ code_ += B->Return(position_, yield_index);
ASSERT(IsStackEmpty());
}
@@ -2010,8 +2026,7 @@
case KernelBytecode::kNativeCall:
case KernelBytecode::kNativeCall_Wide:
- return MethodRecognizer::RecognizeKind(function()) ==
- MethodRecognizer::kListFactory;
+ return function().recognized_kind() == MethodRecognizer::kListFactory;
default:
return false;
@@ -2320,6 +2335,10 @@
while (update_position &&
static_cast<uword>(pc_) >= source_pos_iter.PcOffset()) {
position_ = source_pos_iter.TokenPos();
+ if (source_pos_iter.IsYieldPoint()) {
+ last_yield_point_pc_ = source_pos_iter.PcOffset();
+ ++last_yield_point_index_;
+ }
update_position = source_pos_iter.MoveNext();
}
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h
index 6b1ea18..2500f43 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.h
@@ -224,6 +224,8 @@
intptr_t next_pc_ = -1;
const KBCInstr* bytecode_instr_ = nullptr;
TokenPosition position_;
+ intptr_t last_yield_point_pc_ = 0;
+ intptr_t last_yield_point_index_ = 0;
Fragment code_;
ZoneGrowableArray<LocalVariable*> local_vars_;
ZoneGrowableArray<LocalVariable*> parameters_;
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index cbc4c49..f702f9b 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -502,11 +502,12 @@
closures_->SetAt(closureIndex, closure);
Type& signature_type = Type::Handle(
- Z, ReadFunctionSignature(
- closure, (flags & kHasOptionalPositionalParamsFlag) != 0,
- (flags & kHasOptionalNamedParamsFlag) != 0,
- (flags & kHasTypeParamsFlag) != 0,
- /* has_positional_param_names = */ true, kNonNullable));
+ Z, ReadFunctionSignature(closure,
+ (flags & kHasOptionalPositionalParamsFlag) != 0,
+ (flags & kHasOptionalNamedParamsFlag) != 0,
+ (flags & kHasTypeParamsFlag) != 0,
+ /* has_positional_param_names = */ true,
+ Nullability::kNonNullable));
closure.SetSignatureType(signature_type);
@@ -970,10 +971,12 @@
}
pc_descriptors_list->AddDescriptor(RawPcDescriptors::kOther, start_pc,
DeoptId::kNone,
- TokenPosition::kNoSource, try_index);
+ TokenPosition::kNoSource, try_index,
+ RawPcDescriptors::kInvalidYieldIndex);
pc_descriptors_list->AddDescriptor(RawPcDescriptors::kOther, end_pc,
DeoptId::kNone,
- TokenPosition::kNoSource, try_index);
+ TokenPosition::kNoSource, try_index,
+ RawPcDescriptors::kInvalidYieldIndex);
// The exception handler keeps a zone handle of the types array, rather
// than a raw pointer. Do not share the handle across iterations to avoid
@@ -1019,7 +1022,7 @@
RawTypedData* BytecodeReaderHelper::NativeEntry(const Function& function,
const String& external_name) {
- MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
+ MethodRecognizer::Kind kind = function.recognized_kind();
// This list of recognized methods must be kept in sync with the list of
// methods handled specially by the NativeCall bytecode in the interpreter.
switch (kind) {
@@ -1508,7 +1511,7 @@
const Nullability nullability =
bytecode_component_->GetVersion() >= 24
? static_cast<Nullability>((flags & kNullabilityMask) / kFlagBit4)
- : kLegacy;
+ : Nullability::kLegacy;
return ReadType(tag, nullability);
}
default:
@@ -1669,14 +1672,7 @@
if (!cls.is_declaration_loaded()) {
LoadReferencedClass(cls);
}
- Type& type = Type::Handle(Z, cls.DeclarationType());
- // TODO(regis): Remove this workaround once nullability of Null provided
- // by CFE is always kNullable.
- if (type.IsNullType()) {
- ASSERT(type.IsNullable());
- return type.raw();
- }
- return type.ToNullability(nullability, Heap::kOld);
+ return cls.DeclarationType(nullability);
}
case kTypeParameter: {
Object& parent = Object::Handle(Z, ReadObject());
@@ -1710,9 +1706,9 @@
}
const TypeArguments& type_arguments =
TypeArguments::CheckedHandle(Z, ReadObject());
- const Type& type = Type::Handle(
- Z, Type::New(cls, type_arguments, TokenPosition::kNoSource));
- type.set_nullability(nullability);
+ const Type& type =
+ Type::Handle(Z, Type::New(cls, type_arguments,
+ TokenPosition::kNoSource, nullability));
type.SetIsFinalized();
return type.Canonicalize();
}
@@ -1742,9 +1738,9 @@
pending_recursive_types_->SetLength(id);
pending_recursive_types_ = saved_pending_recursive_types;
- Type& type = Type::Handle(
- Z, Type::New(cls, type_arguments, TokenPosition::kNoSource));
- type.set_nullability(nullability);
+ Type& type =
+ Type::Handle(Z, Type::New(cls, type_arguments,
+ TokenPosition::kNoSource, nullability));
type_ref.set_type(type);
type.SetIsFinalized();
if (id != 0) {
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index ca71934..555d02c 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1539,8 +1539,8 @@
while (!iterate_klass.IsNull()) {
function = iterate_klass.LookupDynamicFunctionAllowPrivate(name);
if (!function.IsNull()) {
- if (function.AreValidArguments(type_args_len, argument_count,
- argument_names,
+ if (function.AreValidArguments(NNBDMode::kLegacy, type_args_len,
+ argument_count, argument_names,
/* error_message = */ NULL)) {
return function;
}
@@ -1572,8 +1572,10 @@
return flow_graph_builder_->LoadLocal(variable);
}
-Fragment StreamingFlowGraphBuilder::Return(TokenPosition position) {
- return flow_graph_builder_->Return(position);
+Fragment StreamingFlowGraphBuilder::Return(TokenPosition position,
+ intptr_t yield_index) {
+ return flow_graph_builder_->Return(position, /*omit_result_type_check=*/false,
+ yield_index);
}
Fragment StreamingFlowGraphBuilder::PushArgument() {
@@ -3112,7 +3114,7 @@
++argument_count;
}
- const auto recognized_kind = MethodRecognizer::RecognizeKind(target);
+ const auto recognized_kind = target.recognized_kind();
if (recognized_kind == MethodRecognizer::kFfiAsFunctionInternal) {
return BuildFfiAsFunctionInternal();
} else if (FLAG_precompiled_mode &&
@@ -3190,8 +3192,8 @@
instructions += BuildArguments(&argument_names, NULL /* arg count */,
NULL /* positional arg count */,
special_case); // read arguments.
- ASSERT(target.AreValidArguments(type_args_len, argument_count, argument_names,
- NULL));
+ ASSERT(target.AreValidArguments(NNBDMode::kLegacy, type_args_len,
+ argument_count, argument_names, NULL));
// Special case identical(x, y) call.
// Note: similar optimization is performed in bytecode flow graph builder -
@@ -3485,7 +3487,8 @@
// special case this situation.
const Type& object_type = Type::Handle(Z, Type::ObjectType());
- if (type.IsInstantiated() && object_type.IsSubtypeOf(type, Heap::kOld)) {
+ if (type.IsInstantiated() &&
+ object_type.IsSubtypeOf(NNBDMode::kLegacy, type, Heap::kOld)) {
// Evaluate the expression on the left but ignore it's result.
instructions += Drop();
@@ -4787,10 +4790,6 @@
ASSERT(flags == kNativeYieldFlags); // Must have been desugared.
- // Collect yield position
- if (record_yield_positions_ != nullptr) {
- record_yield_positions_->Add(Smi::Handle(Z, Smi::New(position.value())));
- }
// Setup yield/continue point:
//
// ...
@@ -4805,7 +4804,8 @@
// BuildGraphOfFunction will create a dispatch that jumps to
// Continuation<:await_jump_var> upon entry to the function.
//
- Fragment instructions = IntConstant(yield_continuations().length() + 1);
+ const intptr_t new_yield_pos = yield_continuations().length() + 1;
+ Fragment instructions = IntConstant(new_yield_pos);
instructions +=
StoreLocal(TokenPosition::kNoSource, scopes()->yield_jump_variable);
instructions += Drop();
@@ -4814,7 +4814,7 @@
StoreLocal(TokenPosition::kNoSource, scopes()->yield_context_variable);
instructions += Drop();
instructions += BuildExpression(); // read expression.
- instructions += Return(position);
+ instructions += Return(position, new_yield_pos);
// Note: DropTempsInstr serves as an anchor instruction. It will not
// be linked into the resulting graph.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index ba3c765..f04298e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -21,11 +21,9 @@
class StreamingFlowGraphBuilder : public KernelReaderHelper {
public:
- StreamingFlowGraphBuilder(
- FlowGraphBuilder* flow_graph_builder,
- const ExternalTypedData& data,
- intptr_t data_program_offset,
- GrowableObjectArray* record_yield_positions = nullptr)
+ StreamingFlowGraphBuilder(FlowGraphBuilder* flow_graph_builder,
+ const ExternalTypedData& data,
+ intptr_t data_program_offset)
: KernelReaderHelper(
flow_graph_builder->zone_,
&flow_graph_builder->translation_helper_,
@@ -43,8 +41,7 @@
inferred_type_metadata_helper_(this),
procedure_attributes_metadata_helper_(this),
call_site_attributes_metadata_helper_(this, &type_translator_),
- closure_owner_(Object::Handle(flow_graph_builder->zone_)),
- record_yield_positions_(record_yield_positions) {}
+ closure_owner_(Object::Handle(flow_graph_builder->zone_)) {}
virtual ~StreamingFlowGraphBuilder() {}
@@ -157,7 +154,8 @@
void InlineBailout(const char* reason);
Fragment DebugStepCheck(TokenPosition position);
Fragment LoadLocal(LocalVariable* variable);
- Fragment Return(TokenPosition position);
+ Fragment Return(TokenPosition position,
+ intptr_t yield_index = RawPcDescriptors::kInvalidYieldIndex);
Fragment PushArgument();
Fragment EvaluateAssertion();
Fragment RethrowException(TokenPosition position, int catch_try_index);
@@ -368,7 +366,6 @@
ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_;
CallSiteAttributesMetadataHelper call_site_attributes_metadata_helper_;
Object& closure_owner_;
- GrowableObjectArray* record_yield_positions_;
friend class KernelLoader;
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index bf79b16..cf6f13d 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -246,7 +246,7 @@
break;
case kTypeParameterType: {
Nullability nullability = ReadNullability();
- BuildHash(nullability);
+ BuildHash(static_cast<uint32_t>(nullability));
ReadUInt(); // read index for parameter.
CalculateOptionalDartTypeFingerprint(); // read bound bound.
break;
@@ -269,7 +269,7 @@
void KernelFingerprintHelper::CalculateInterfaceTypeFingerprint(bool simple) {
Nullability nullability = ReadNullability();
- BuildHash(nullability);
+ BuildHash(static_cast<uint32_t>(nullability));
NameIndex kernel_class = ReadCanonicalNameReference();
ASSERT(H.IsClass(kernel_class));
const String& class_name = H.DartClassName(kernel_class);
@@ -285,7 +285,7 @@
void KernelFingerprintHelper::CalculateFunctionTypeFingerprint(bool simple) {
Nullability nullability = ReadNullability();
- BuildHash(nullability);
+ BuildHash(static_cast<uint32_t>(nullability));
if (!simple) {
CalculateTypeParametersListFingerprint(); // read type_parameters.
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index a3877ad..1426f50 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -40,8 +40,7 @@
bool optimizing,
intptr_t osr_id,
intptr_t first_block_id,
- bool inlining_unchecked_entry,
- GrowableObjectArray* record_yield_positions)
+ bool inlining_unchecked_entry)
: BaseFlowGraphBuilder(parsed_function,
first_block_id - 1,
osr_id,
@@ -69,7 +68,6 @@
catch_block_(NULL) {
const Script& script =
Script::Handle(Z, parsed_function->function().script());
- record_yield_positions_ = record_yield_positions;
H.InitFromScript(script);
}
@@ -411,15 +409,21 @@
}
}
-Fragment FlowGraphBuilder::LoadLateInstanceField(const Field& field,
- LocalVariable* instance) {
+Fragment FlowGraphBuilder::LoadLateField(const Field& field,
+ LocalVariable* instance) {
Fragment instructions;
TargetEntryInstr *is_uninitialized, *is_initialized;
const TokenPosition position = field.token_pos();
+ const bool is_static = field.is_static();
// Check whether the field has been initialized already.
- instructions += LoadLocal(instance);
- instructions += LoadField(field);
+ if (is_static) {
+ instructions += Constant(field);
+ instructions += LoadStaticField();
+ } else {
+ instructions += LoadLocal(instance);
+ instructions += LoadField(field);
+ }
LocalVariable* temp = MakeTemporary();
instructions += LoadLocal(temp);
instructions += Constant(Object::sentinel());
@@ -436,14 +440,18 @@
Function& init_function =
Function::ZoneHandle(Z, field.EnsureInitializerFunction());
Fragment initialize(is_uninitialized);
- initialize += LoadLocal(instance); // For the store.
- initialize += LoadLocal(instance); // For the init call.
- initialize += PushArgument();
- initialize += StaticCall(position, init_function,
- /* argument_count = */ 1, ICData::kStatic);
+ if (is_static) {
+ initialize += StaticCall(position, init_function,
+ /* argument_count = */ 0, ICData::kStatic);
+ } else {
+ initialize += LoadLocal(instance);
+ initialize += PushArgument();
+ initialize += StaticCall(position, init_function,
+ /* argument_count = */ 1, ICData::kStatic);
+ }
initialize += StoreLocal(position, temp);
- initialize += StoreInstanceFieldGuarded(
- field, StoreInstanceFieldInstr::Kind::kInitializing);
+ initialize += Drop();
+ initialize += StoreLateField(field, instance, temp);
initialize += Goto(join);
} else {
// The field has no initializer, so throw a LateInitializationError.
@@ -460,112 +468,6 @@
}
// Now that the field has been initialized, load it.
- instructions = Fragment(instructions.entry, join);
-
- return instructions;
-}
-
-Fragment FlowGraphBuilder::LoadLateStaticField(const Field& field) {
- Fragment instructions;
-
- // Check whether the field has been initialized already.
- TargetEntryInstr *is_uninitialized, *is_initialized;
- const TokenPosition position = field.token_pos();
- instructions += Constant(field);
- instructions += LoadStaticField();
- LocalVariable* temp = MakeTemporary();
- instructions += LoadLocal(temp);
- instructions += Constant(Object::sentinel());
- instructions += BranchIfStrictEqual(&is_uninitialized, &is_initialized);
-
- JoinEntryInstr* join = BuildJoinEntry();
-
- if (field.has_initializer()) {
- // has_nontrivial_initializer is required for EnsureInitializerFunction. The
- // trivial initializer case is treated as a normal field.
- ASSERT(field.has_nontrivial_initializer());
-
- // If the field isn't initialized, call the initializer and set the field.
- Function& init_function =
- Function::ZoneHandle(Z, field.EnsureInitializerFunction());
- Fragment initialize(is_uninitialized);
- initialize += StaticCall(position, init_function,
- /* argument_count = */ 0, ICData::kStatic);
- initialize += StoreLocal(position, temp);
- initialize += StoreStaticField(position, field);
- initialize += Goto(join);
- } else {
- // The field has no initializer, so throw a LateInitializationError.
- Fragment initialize(is_uninitialized);
- initialize += ThrowLateInitializationError(
- position, String::ZoneHandle(Z, field.name()));
- initialize += Goto(join);
- }
-
- {
- // Already initialized, so there's nothing to do.
- Fragment already_initialized(is_initialized);
- already_initialized += Goto(join);
- }
-
- // Now that the field has been initialized, load it.
- instructions = Fragment(instructions.entry, join);
-
- return instructions;
-}
-
-Fragment FlowGraphBuilder::StoreLateInstanceField(const Field& field,
- LocalVariable* instance,
- LocalVariable* setter_value) {
- // Implicit setters for non-final late fields are the same as non-late fields.
- if (!field.is_final()) {
- return StoreInstanceFieldGuarded(field,
- StoreInstanceFieldInstr::Kind::kOther);
- }
-
- // If a late final field has an initializer, the setter always throws. This
- // case is typically caught as a compile error, but there are ways to avoid
- // that error, so we also need this runtime error.
- const TokenPosition position = field.token_pos();
- if (field.has_initializer()) {
- Fragment instructions;
- instructions += Drop();
- instructions += Drop();
- instructions += ThrowLateInitializationError(
- position, String::ZoneHandle(Z, field.name()));
- return instructions;
- }
-
- // Late final fields with no initializer can be written to once.
- Fragment instructions;
- TargetEntryInstr *is_uninitialized, *is_initialized;
-
- // Check whether the field has been initialized already.
- instructions += Drop();
- instructions += LoadField(field);
- instructions += Constant(Object::sentinel());
- instructions += BranchIfStrictEqual(&is_uninitialized, &is_initialized);
-
- JoinEntryInstr* join = BuildJoinEntry();
-
- {
- // If the field isn't initialized, set it to the new value.
- Fragment initialize(is_uninitialized);
- initialize += LoadLocal(instance);
- initialize += LoadLocal(setter_value);
- initialize +=
- StoreInstanceFieldGuarded(field, StoreInstanceFieldInstr::Kind::kOther);
- initialize += Goto(join);
- }
-
- {
- // If the field is already initialized, throw a LateInitializationError.
- Fragment already_initialized(is_initialized);
- already_initialized += ThrowLateInitializationError(
- position, String::ZoneHandle(Z, field.name()));
- already_initialized += Goto(join);
- }
-
return Fragment(instructions.entry, join);
}
@@ -593,6 +495,59 @@
return instructions;
}
+Fragment FlowGraphBuilder::StoreLateField(const Field& field,
+ LocalVariable* instance,
+ LocalVariable* setter_value) {
+ Fragment instructions;
+ TargetEntryInstr *is_uninitialized, *is_initialized;
+ const TokenPosition position = field.token_pos();
+ const bool is_static = field.is_static();
+ const bool is_final = field.is_final();
+
+ if (is_final) {
+ // Check whether the field has been initialized already.
+ if (is_static) {
+ instructions += Constant(field);
+ instructions += LoadStaticField();
+ } else {
+ instructions += LoadLocal(instance);
+ instructions += LoadField(field);
+ }
+ instructions += Constant(Object::sentinel());
+ instructions += BranchIfStrictEqual(&is_uninitialized, &is_initialized);
+ JoinEntryInstr* join = BuildJoinEntry();
+
+ {
+ // If the field isn't initialized, do nothing.
+ Fragment initialize(is_uninitialized);
+ initialize += Goto(join);
+ }
+
+ {
+ // If the field is already initialized, throw a LateInitializationError.
+ Fragment already_initialized(is_initialized);
+ already_initialized += ThrowLateInitializationError(
+ position, String::ZoneHandle(Z, field.name()));
+ already_initialized += Goto(join);
+ }
+
+ instructions = Fragment(instructions.entry, join);
+ }
+
+ if (!is_static) {
+ instructions += LoadLocal(instance);
+ }
+ instructions += LoadLocal(setter_value);
+ if (is_static) {
+ instructions += StoreStaticField(position, field);
+ } else {
+ instructions += StoreInstanceFieldGuarded(
+ field, StoreInstanceFieldInstr::Kind::kInitializing);
+ }
+
+ return instructions;
+}
+
Fragment FlowGraphBuilder::InitInstanceField(const Field& field) {
ASSERT(field.is_instance());
ASSERT(field.needs_load_guard());
@@ -621,7 +576,8 @@
}
Fragment FlowGraphBuilder::Return(TokenPosition position,
- bool omit_result_type_check /* = false */) {
+ bool omit_result_type_check,
+ intptr_t yield_index) {
Fragment instructions;
const Function& function = parsed_function_->function();
@@ -649,7 +605,7 @@
instructions += Drop();
}
- instructions += BaseFlowGraphBuilder::Return(position);
+ instructions += BaseFlowGraphBuilder::Return(position, yield_index);
return instructions;
}
@@ -835,7 +791,7 @@
// TODO(alexmarkov): refactor this - StreamingFlowGraphBuilder should not be
// used for bytecode functions.
StreamingFlowGraphBuilder streaming_flow_graph_builder(
- this, kernel_data, kernel_data_program_offset, record_yield_positions_);
+ this, kernel_data, kernel_data_program_offset);
return streaming_flow_graph_builder.BuildGraph();
}
@@ -863,7 +819,7 @@
bool FlowGraphBuilder::IsRecognizedMethodForFlowGraph(
const Function& function) {
- const MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
+ const MethodRecognizer::Kind kind = function.recognized_kind();
switch (kind) {
case MethodRecognizer::kTypedData_ByteDataView_factory:
@@ -965,7 +921,7 @@
Fragment body(instruction_cursor);
body += CheckStackOverflowInPrologue(function.token_pos());
- const MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
+ const MethodRecognizer::Kind kind = function.recognized_kind();
switch (kind) {
case MethodRecognizer::kTypedData_ByteDataView_factory:
body += BuildTypedDataViewFactoryConstructor(function, kByteDataViewCid);
@@ -2275,8 +2231,7 @@
Function::ZoneHandle(Z, function.parent_function());
const Class& owner = Class::ZoneHandle(Z, parent.Owner());
AbstractType& type = AbstractType::ZoneHandle(Z);
- type = Type::New(owner, TypeArguments::Handle(Z), owner.token_pos(),
- Heap::kOld);
+ type = Type::New(owner, TypeArguments::Handle(Z), owner.token_pos());
type = ClassFinalizer::FinalizeType(owner, type);
body += Constant(type);
} else {
@@ -2674,30 +2629,44 @@
body += CheckAssignable(setter_value->type(), setter_value->name(),
AssertAssignableInstr::kParameterCheck);
}
- if (is_method) {
- if (field.is_late()) {
- body += StoreLateInstanceField(
- field, parsed_function_->ParameterVariable(0), setter_value);
+ if (field.is_late()) {
+ if (is_method) {
+ body += Drop();
+ }
+ body += Drop();
+ if (field.is_final() && field.has_initializer()) {
+ body += ThrowLateInitializationError(
+ field.token_pos(), String::ZoneHandle(Z, field.name()));
} else {
- body += StoreInstanceFieldGuarded(
- field, StoreInstanceFieldInstr::Kind::kOther);
+ body += StoreLateField(
+ field, is_method ? parsed_function_->ParameterVariable(0) : nullptr,
+ setter_value);
}
} else {
- body += StoreStaticField(TokenPosition::kNoSource, field);
+ if (is_method) {
+ body += StoreInstanceFieldGuarded(
+ field, StoreInstanceFieldInstr::Kind::kOther);
+ } else {
+ body += StoreStaticField(TokenPosition::kNoSource, field);
+ }
}
body += NullConstant();
} else if (is_method) {
-#if !defined(PRODUCT)
if (field.needs_load_guard()) {
+#if defined(PRODUCT)
+ UNREACHABLE();
+#else
ASSERT(Isolate::Current()->HasAttemptedReload());
body += LoadLocal(parsed_function_->ParameterVariable(0));
body += InitInstanceField(field);
- // TODO(rmacnak): Type check.
- }
+
+ body += LoadLocal(parsed_function_->ParameterVariable(0));
+ body += LoadField(field);
+ body += CheckAssignable(AbstractType::Handle(Z, field.type()),
+ Symbols::FunctionResult());
#endif
- if (field.is_late() && !field.has_trivial_initializer()) {
- body +=
- LoadLateInstanceField(field, parsed_function_->ParameterVariable(0));
+ } else if (field.is_late() && !field.has_trivial_initializer()) {
+ body += LoadLateField(field, parsed_function_->ParameterVariable(0));
} else {
body += LoadLocal(parsed_function_->ParameterVariable(0));
body += LoadField(field);
@@ -2718,7 +2687,7 @@
// In NNBD mode, static fields act like late fields regardless of whether
// they're marked late. The only behavioural difference is in compile
// errors that are handled by the front end.
- body += LoadLateStaticField(field);
+ body += LoadLateField(field, /* instance = */ nullptr);
} else {
ASSERT(field.has_nontrivial_initializer());
body += Constant(field);
@@ -2726,6 +2695,15 @@
body += Constant(field);
body += LoadStaticField();
}
+ if (field.needs_load_guard()) {
+#if defined(PRODUCT)
+ UNREACHABLE();
+#else
+ ASSERT(Isolate::Current()->HasAttemptedReload());
+ body += CheckAssignable(AbstractType::Handle(Z, field.type()),
+ Symbols::FunctionResult());
+#endif
+ }
}
body += Return(TokenPosition::kNoSource);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 434106f..29893dc 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -56,8 +56,7 @@
bool optimizing,
intptr_t osr_id,
intptr_t first_block_id = 1,
- bool inlining_unchecked_entry = false,
- GrowableObjectArray* record_yield_position = nullptr);
+ bool inlining_unchecked_entry = false);
virtual ~FlowGraphBuilder();
FlowGraph* BuildGraph();
@@ -132,15 +131,16 @@
Fragment RethrowException(TokenPosition position, int catch_try_index);
Fragment LoadLocal(LocalVariable* variable);
- Fragment LoadLateInstanceField(const Field& field, LocalVariable* instance);
- Fragment LoadLateStaticField(const Field& field);
- Fragment StoreLateInstanceField(const Field& field,
- LocalVariable* instance,
- LocalVariable* setter_value);
+ Fragment LoadLateField(const Field& field, LocalVariable* instance);
+ Fragment StoreLateField(const Field& field,
+ LocalVariable* instance,
+ LocalVariable* setter_value);
Fragment InitInstanceField(const Field& field);
Fragment InitStaticField(const Field& field);
Fragment NativeCall(const String* name, const Function* function);
- Fragment Return(TokenPosition position, bool omit_result_type_check = false);
+ Fragment Return(TokenPosition position,
+ bool omit_result_type_check = false,
+ intptr_t yield_index = RawPcDescriptors::kInvalidYieldIndex);
void SetResultTypeForStaticCall(StaticCallInstr* call,
const Function& target,
intptr_t argument_count,
@@ -387,8 +387,6 @@
ActiveClass active_class_;
- GrowableObjectArray* record_yield_positions_;
-
friend class BreakableBlock;
friend class CatchBlock;
friend class ProgramState;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index f02eb50..1886995 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -1966,9 +1966,11 @@
case kDynamicType:
case kVoidType:
case kBottomType:
- case kNeverType:
// those contain nothing.
return;
+ case kNeverType:
+ ReadNullability();
+ return;
case kInterfaceType:
SkipInterfaceType(false);
return;
@@ -2767,12 +2769,12 @@
result_ = Object::void_type().raw();
break;
case kBottomType:
- result_ =
- Class::Handle(Z, I->object_store()->null_class()).DeclarationType();
- // We set the nullability of Null to kNullable, even in legacy mode.
+ result_ = I->object_store()->null_type();
ASSERT(result_.IsNullable());
break;
case kNeverType:
+ helper_->ReadNullability();
+ // Ignore nullability, as Never type is non-nullable.
result_ = Object::never_type().raw();
break;
case kInterfaceType:
@@ -2814,18 +2816,13 @@
if (simple) {
if (finalize_ || klass.is_type_finalized()) {
// Fast path for non-generic types: retrieve or populate the class's only
- // canonical type, which is its declaration type.
- result_ = klass.DeclarationType();
- // TODO(regis): Remove this workaround once nullability of Null provided
- // by CFE is always kNullable.
- if (!result_.IsNullType()) {
- result_ = Type::Cast(result_).ToNullability(nullability, Heap::kOld);
- }
+ // canonical type (as long as only one nullability variant is used), which
+ // is its declaration type.
+ result_ = klass.DeclarationType(nullability);
} else {
// Note that the type argument vector is not yet extended.
- result_ =
- Type::New(klass, Object::null_type_arguments(), klass.token_pos());
- Type::Cast(result_).set_nullability(nullability);
+ result_ = Type::New(klass, Object::null_type_arguments(),
+ klass.token_pos(), nullability);
}
return;
}
@@ -2930,8 +2927,7 @@
finalize_ = finalize;
Type& signature_type =
- Type::ZoneHandle(Z, signature_function.SignatureType());
- signature_type.set_nullability(nullability);
+ Type::ZoneHandle(Z, signature_function.SignatureType(nullability));
if (finalize_) {
signature_type ^=
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 8e1302a..a1d2df1 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -1295,9 +1295,11 @@
case kDynamicType:
case kVoidType:
case kBottomType:
- case kNeverType:
// those contain nothing.
return;
+ case kNeverType:
+ helper_.ReadNullability();
+ return;
case kInterfaceType:
VisitInterfaceType(false);
return;
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 9485474..e0c0d63 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -17,10 +17,10 @@
#include "vm/compiler/compiler_pass.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/cpu.h"
+#include "vm/flag_list.h"
namespace dart {
-DECLARE_FLAG(bool, code_comments);
DECLARE_FLAG(bool, print_flow_graph);
DECLARE_FLAG(bool, print_flow_graph_optimized);
@@ -299,8 +299,8 @@
break;
case kTypedDataInt32ArrayCid:
case kExternalTypedDataInt32ArrayCid:
- // Use same truncating unbox-instruction for int32 and uint32.
- FALL_THROUGH;
+ // Use same truncating unbox-instruction for int32 and uint32.
+ FALL_THROUGH;
case kTypedDataUint32ArrayCid:
case kExternalTypedDataUint32ArrayCid:
// Supports smi and mint, slow-case for bigints.
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index e52a66f..549c396 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -1017,41 +1017,6 @@
}
}
-void Compiler::ComputeYieldPositions(const Function& function) {
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- const Script& script = Script::Handle(zone, function.script());
- Array& yield_position_map = Array::Handle(zone, script.yield_positions());
- if (yield_position_map.IsNull()) {
- yield_position_map = HashTables::New<UnorderedHashMap<SmiTraits>>(4);
- }
- UnorderedHashMap<SmiTraits> function_map(yield_position_map.raw());
- Smi& key = Smi::Handle(zone, Smi::New(function.token_pos().value()));
-
- if (function_map.ContainsKey(key)) {
- ASSERT(function_map.Release().raw() == yield_position_map.raw());
- return;
- }
-
- CompilerState state(thread);
- LongJumpScope jump;
- auto& array = GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
- if (setjmp(*jump.Set()) == 0) {
- ParsedFunction* parsed_function =
- new ParsedFunction(thread, Function::ZoneHandle(zone, function.raw()));
- ZoneGrowableArray<const ICData*>* ic_data_array =
- new ZoneGrowableArray<const ICData*>();
- kernel::FlowGraphBuilder builder(parsed_function, ic_data_array, nullptr,
- /* not inlining */ nullptr, false,
- Compiler::kNoOSRDeoptId, 1, false, &array);
- builder.BuildGraph();
- }
- function_map.UpdateOrInsert(key, array);
- // Release and store back to script
- yield_position_map = function_map.Release().raw();
- script.set_yield_positions(yield_position_map);
-}
-
RawError* Compiler::CompileAllFunctions(const Class& cls) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
@@ -1452,10 +1417,6 @@
UNREACHABLE();
}
-void Compiler::ComputeYieldPositions(const Function& function) {
- UNREACHABLE();
-}
-
RawError* Compiler::CompileAllFunctions(const Class& cls) {
FATAL1("Attempt to compile class %s", cls.ToCString());
return Error::null();
diff --git a/runtime/vm/compiler/jit/compiler.h b/runtime/vm/compiler/jit/compiler.h
index 94e22b7..123e16a 100644
--- a/runtime/vm/compiler/jit/compiler.h
+++ b/runtime/vm/compiler/jit/compiler.h
@@ -108,8 +108,6 @@
// Generates local var descriptors and sets it in 'code'. Do not call if the
// local var descriptor already exists.
static void ComputeLocalVarDescriptors(const Code& code);
- // Collect yield positions for function and store into its script object
- static void ComputeYieldPositions(const Function& function);
// Eagerly compiles all functions in a class.
//
diff --git a/runtime/vm/compiler/jit/jit_call_specializer.cc b/runtime/vm/compiler/jit/jit_call_specializer.cc
index a13bffc..8d6b46c 100644
--- a/runtime/vm/compiler/jit/jit_call_specializer.cc
+++ b/runtime/vm/compiler/jit/jit_call_specializer.cc
@@ -126,9 +126,7 @@
has_one_target = PolymorphicInstanceCallInstr::ComputeRuntimeType(
targets) != Type::null();
} else {
- const bool polymorphic_target =
- MethodRecognizer::PolymorphicTarget(target);
- has_one_target = !polymorphic_target;
+ has_one_target = !target.is_polymorphic_target();
}
}
diff --git a/runtime/vm/compiler/method_recognizer.cc b/runtime/vm/compiler/method_recognizer.cc
index 07f910f..535e332 100644
--- a/runtime/vm/compiler/method_recognizer.cc
+++ b/runtime/vm/compiler/method_recognizer.cc
@@ -10,18 +10,9 @@
namespace dart {
-MethodRecognizer::Kind MethodRecognizer::RecognizeKind(
- const Function& function) {
- return function.recognized_kind();
-}
-
-bool MethodRecognizer::PolymorphicTarget(const Function& function) {
- return function.is_polymorphic_target();
-}
-
intptr_t MethodRecognizer::NumArgsCheckedForStaticCall(
const Function& function) {
- switch (RecognizeKind(function)) {
+ switch (function.recognized_kind()) {
case MethodRecognizer::kDoubleFromInteger:
case MethodRecognizer::kMathMin:
case MethodRecognizer::kMathMax:
@@ -176,14 +167,22 @@
return kIllegalCid;
}
-#define KIND_TO_STRING(class_name, function_name, enum_name, fp) #enum_name,
-static const char* recognized_list_method_name[] = {
- "Unknown", RECOGNIZED_LIST(KIND_TO_STRING)};
-#undef KIND_TO_STRING
+static const struct {
+ const char* const class_name;
+ const char* const function_name;
+ const char* const enum_name;
+ const uint32_t fp;
+} recognized_methods[MethodRecognizer::kNumRecognizedMethods] = {
+ {"", "", "Unknown", 0},
+#define RECOGNIZE_METHOD(class_name, function_name, enum_name, fp) \
+ {"" #class_name, "" #function_name, #enum_name, fp},
+ RECOGNIZED_LIST(RECOGNIZE_METHOD)
+#undef RECOGNIZE_METHOD
+};
const char* MethodRecognizer::KindToCString(Kind kind) {
- if (kind > kUnknown && kind < kNumRecognizedMethods)
- return recognized_list_method_name[kind];
+ if (kind >= kUnknown && kind < kNumRecognizedMethods)
+ return recognized_methods[kind].enum_name;
return "?";
}
@@ -193,18 +192,22 @@
Libraries(&libs);
Function& func = Function::Handle();
-#define SET_RECOGNIZED_KIND(class_name, function_name, enum_name, fp) \
- func = Library::GetFunction(libs, #class_name, #function_name); \
- if (!func.IsNull()) { \
- CHECK_FINGERPRINT3(func, class_name, function_name, enum_name, fp); \
- func.set_recognized_kind(k##enum_name); \
- } else if (!FLAG_precompiled_mode) { \
- OS::PrintErr("Missing %s::%s\n", #class_name, #function_name); \
- UNREACHABLE(); \
+ for (intptr_t i = 1; i < MethodRecognizer::kNumRecognizedMethods; i++) {
+ const MethodRecognizer::Kind kind = static_cast<MethodRecognizer::Kind>(i);
+ func = Library::GetFunction(libs, recognized_methods[i].class_name,
+ recognized_methods[i].function_name);
+ if (!func.IsNull()) {
+ CHECK_FINGERPRINT3(func, recognized_methods[i].class_name,
+ recognized_methods[i].function_name,
+ recognized_methods[i].enum_name,
+ recognized_methods[i].fp);
+ func.set_recognized_kind(kind);
+ } else if (!FLAG_precompiled_mode) {
+ FATAL2("Missing %s::%s\n", recognized_methods[i].class_name,
+ recognized_methods[i].function_name);
+ }
}
- RECOGNIZED_LIST(SET_RECOGNIZED_KIND);
-
#define SET_FUNCTION_BIT(class_name, function_name, dest, fp, setter, value) \
func = Library::GetFunction(libs, #class_name, #function_name); \
if (!func.IsNull()) { \
@@ -236,24 +239,6 @@
libs->Add(&Library::ZoneHandle(Library::AsyncLibrary()));
libs->Add(&Library::ZoneHandle(Library::FfiLibrary()));
}
-
-RawGrowableObjectArray* MethodRecognizer::QueryRecognizedMethods(Zone* zone) {
- const GrowableObjectArray& methods =
- GrowableObjectArray::Handle(zone, GrowableObjectArray::New());
- Function& func = Function::Handle(zone);
-
- GrowableArray<Library*> libs(3);
- Libraries(&libs);
-
-#define ADD_RECOGNIZED_METHOD(class_name, function_name, enum_name, fp) \
- func = Library::GetFunction(libs, #class_name, #function_name); \
- methods.Add(func);
-
- RECOGNIZED_LIST(ADD_RECOGNIZED_METHOD);
-#undef ADD_RECOGNIZED_METHOD
-
- return methods.raw();
-}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
Token::Kind MethodTokenRecognizer::RecognizeTokenKind(const String& name_) {
@@ -315,10 +300,10 @@
{Symbols::k##symbol##Id, cid, fp, #symbol ", " #cid}, // NOLINT
static struct {
- intptr_t symbol_id;
- intptr_t cid;
- uint32_t finger_print;
- const char* name;
+ const intptr_t symbol_id;
+ const intptr_t cid;
+ const uint32_t finger_print;
+ const char* const name;
} factory_recognizer_list[] = {RECOGNIZED_LIST_FACTORY_LIST(RECOGNIZE_FACTORY){
Symbols::kIllegal, -1, 0, NULL}};
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index 74889ff..1cf5d5b 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -34,8 +34,6 @@
kNumRecognizedMethods
};
- static Kind RecognizeKind(const Function& function);
- static bool PolymorphicTarget(const Function& function);
static intptr_t NumArgsCheckedForStaticCall(const Function& function);
// Try to find an annotation of the form
@@ -59,7 +57,6 @@
#if !defined(DART_PRECOMPILED_RUNTIME)
static void InitializeState();
- static RawGrowableObjectArray* QueryRecognizedMethods(Zone* zone);
private:
static void Libraries(GrowableArray<Library*>* libs);
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index f6f7eaa..ef2b206 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -699,6 +699,7 @@
static word call_native_through_safepoint_stub_offset();
static word call_native_through_safepoint_entry_point_offset();
+ static word bootstrap_native_wrapper_entry_point_offset();
static word no_scope_native_wrapper_entry_point_offset();
static word auto_scope_native_wrapper_entry_point_offset();
@@ -764,25 +765,12 @@
static word shared_class_table_offset();
#if !defined(PRODUCT)
static word ClassOffsetFor(intptr_t cid);
- static word StateOffsetFor(intptr_t cid);
- static word NewSpaceCounterOffsetFor(intptr_t cid);
- static word NewSpaceSizeOffsetFor(intptr_t cid);
static word SharedTableOffsetFor();
static word SizeOffsetFor(intptr_t cid, bool is_new);
#endif // !defined(PRODUCT)
static const word kSizeOfClassPairLog2;
};
-#if !defined(PRODUCT)
-class ClassHeapStats : public AllStatic {
- public:
- static word TraceAllocationMask();
- static word state_offset();
- static word allocated_since_gc_new_space_offset();
- static word allocated_size_since_gc_new_space_offset();
-};
-#endif // !defined(PRODUCT)
-
class Instructions : public AllStatic {
public:
static const word kMonomorphicEntryOffsetJIT;
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 4c3564a..6fe7f06 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -77,14 +77,7 @@
static constexpr dart::compiler::target::word
Class_type_arguments_field_offset_in_words_offset = 96;
static constexpr dart::compiler::target::word
- ClassHeapStats_TraceAllocationMask = 1;
-static constexpr dart::compiler::target::word
- ClassHeapStats_allocated_since_gc_new_space_offset = 48;
-static constexpr dart::compiler::target::word
- ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
-static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 160;
-static constexpr dart::compiler::target::word
- ClassTable_shared_class_table_offset = 20;
+ ClassTable_shared_class_table_offset = 16;
static constexpr dart::compiler::target::word ClassTable_table_offset = 8;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
@@ -145,7 +138,7 @@
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 36;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 64;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 60;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
static constexpr dart::compiler::target::word
@@ -193,11 +186,11 @@
static constexpr dart::compiler::target::word String_length_offset = 4;
static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
static constexpr dart::compiler::target::word
- Thread_AllocateArray_entry_point_offset = 292;
+ Thread_AllocateArray_entry_point_offset = 296;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 628;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
632;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+ 636;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 120;
static constexpr dart::compiler::target::word
@@ -205,14 +198,16 @@
static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
88;
static constexpr dart::compiler::target::word
- Thread_auto_scope_native_wrapper_entry_point_offset = 252;
+ Thread_auto_scope_native_wrapper_entry_point_offset = 256;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
static constexpr dart::compiler::target::word Thread_bool_true_offset = 108;
static constexpr dart::compiler::target::word
+ Thread_bootstrap_native_wrapper_entry_point_offset = 248;
+static constexpr dart::compiler::target::word
Thread_call_to_runtime_entry_point_offset = 208;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 140;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 664;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 668;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
236;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 164;
@@ -221,14 +216,14 @@
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
168;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
- 272;
+ 276;
static constexpr dart::compiler::target::word
- Thread_double_negate_address_offset = 268;
+ Thread_double_negate_address_offset = 272;
static constexpr dart::compiler::target::word Thread_end_offset = 64;
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 188;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 648;
+ 652;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 192;
static constexpr dart::compiler::target::word
@@ -240,17 +235,17 @@
static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 124;
static constexpr dart::compiler::target::word
- Thread_float_absolute_address_offset = 284;
+ Thread_float_absolute_address_offset = 288;
static constexpr dart::compiler::target::word
- Thread_float_negate_address_offset = 280;
+ Thread_float_negate_address_offset = 284;
static constexpr dart::compiler::target::word Thread_float_not_address_offset =
- 276;
+ 280;
static constexpr dart::compiler::target::word
- Thread_float_zerow_address_offset = 288;
+ Thread_float_zerow_address_offset = 292;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 636;
+ 640;
static constexpr dart::compiler::target::word
- Thread_interpret_call_entry_point_offset = 256;
+ Thread_interpret_call_entry_point_offset = 260;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_from_bytecode_stub_offset = 136;
static constexpr dart::compiler::target::word
@@ -271,7 +266,7 @@
static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 160;
static constexpr dart::compiler::target::word
- Thread_no_scope_native_wrapper_entry_point_offset = 248;
+ Thread_no_scope_native_wrapper_entry_point_offset = 252;
static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_entry_point_offset = 216;
static constexpr dart::compiler::target::word
@@ -282,12 +277,12 @@
Thread_null_error_shared_without_fpu_regs_stub_offset = 144;
static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
static constexpr dart::compiler::target::word
- Thread_predefined_symbols_address_offset = 260;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 640;
+ Thread_predefined_symbols_address_offset = 264;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 644;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 644;
+ Thread_saved_shadow_call_stack_offset = 648;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 652;
+ 656;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 180;
static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
@@ -318,7 +313,7 @@
Thread_write_barrier_entry_point_offset = 200;
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
48;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 656;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 660;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -344,15 +339,15 @@
static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
0;
-static constexpr dart::compiler::target::word ClassTable_element_size = 168;
+static constexpr dart::compiler::target::word ClassTable_element_size = 1;
static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
4, 12, 8, 16};
static constexpr dart::compiler::target::word
Code_function_entry_point_offset[] = {4, 8};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 592, 596, 600, 604, 608, -1, 612, 616,
- 620, 624, -1, -1, -1, -1, -1, -1};
+ 596, 600, 604, 608, 612, -1, 616, 620,
+ 624, 628, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word Array_header_size = 12;
static constexpr dart::compiler::target::word Context_header_size = 12;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
@@ -438,14 +433,7 @@
static constexpr dart::compiler::target::word
Class_type_arguments_field_offset_in_words_offset = 180;
static constexpr dart::compiler::target::word
- ClassHeapStats_TraceAllocationMask = 1;
-static constexpr dart::compiler::target::word
- ClassHeapStats_allocated_since_gc_new_space_offset = 96;
-static constexpr dart::compiler::target::word
- ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
-static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 272;
-static constexpr dart::compiler::target::word
- ClassTable_shared_class_table_offset = 40;
+ ClassTable_shared_class_table_offset = 32;
static constexpr dart::compiler::target::word ClassTable_table_offset = 16;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
@@ -506,7 +494,7 @@
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 72;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 128;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 120;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
static constexpr dart::compiler::target::word
@@ -554,11 +542,11 @@
static constexpr dart::compiler::target::word String_length_offset = 8;
static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
static constexpr dart::compiler::target::word
- Thread_AllocateArray_entry_point_offset = 568;
+ Thread_AllocateArray_entry_point_offset = 576;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 1256;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
1264;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+ 1272;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 224;
static constexpr dart::compiler::target::word
@@ -566,14 +554,16 @@
static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
176;
static constexpr dart::compiler::target::word
- Thread_auto_scope_native_wrapper_entry_point_offset = 488;
+ Thread_auto_scope_native_wrapper_entry_point_offset = 496;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 208;
static constexpr dart::compiler::target::word Thread_bool_true_offset = 200;
static constexpr dart::compiler::target::word
+ Thread_bootstrap_native_wrapper_entry_point_offset = 480;
+static constexpr dart::compiler::target::word
Thread_call_to_runtime_entry_point_offset = 400;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1328;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1336;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
456;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 312;
@@ -582,14 +572,14 @@
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
320;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
- 528;
+ 536;
static constexpr dart::compiler::target::word
- Thread_double_negate_address_offset = 520;
+ Thread_double_negate_address_offset = 528;
static constexpr dart::compiler::target::word Thread_end_offset = 128;
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 360;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 1296;
+ 1304;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 368;
static constexpr dart::compiler::target::word
@@ -601,17 +591,17 @@
static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 232;
static constexpr dart::compiler::target::word
- Thread_float_absolute_address_offset = 552;
+ Thread_float_absolute_address_offset = 560;
static constexpr dart::compiler::target::word
- Thread_float_negate_address_offset = 544;
+ Thread_float_negate_address_offset = 552;
static constexpr dart::compiler::target::word Thread_float_not_address_offset =
- 536;
+ 544;
static constexpr dart::compiler::target::word
- Thread_float_zerow_address_offset = 560;
+ Thread_float_zerow_address_offset = 568;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 1272;
+ 1280;
static constexpr dart::compiler::target::word
- Thread_interpret_call_entry_point_offset = 496;
+ Thread_interpret_call_entry_point_offset = 504;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_from_bytecode_stub_offset = 256;
static constexpr dart::compiler::target::word
@@ -632,7 +622,7 @@
static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 304;
static constexpr dart::compiler::target::word
- Thread_no_scope_native_wrapper_entry_point_offset = 480;
+ Thread_no_scope_native_wrapper_entry_point_offset = 488;
static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_entry_point_offset = 416;
static constexpr dart::compiler::target::word
@@ -643,12 +633,12 @@
Thread_null_error_shared_without_fpu_regs_stub_offset = 272;
static constexpr dart::compiler::target::word Thread_object_null_offset = 192;
static constexpr dart::compiler::target::word
- Thread_predefined_symbols_address_offset = 504;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1280;
+ Thread_predefined_symbols_address_offset = 512;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1288;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 1288;
+ Thread_saved_shadow_call_stack_offset = 1296;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 1304;
+ 1312;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 344;
static constexpr dart::compiler::target::word Thread_stack_limit_offset = 72;
@@ -680,7 +670,7 @@
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
96;
static constexpr dart::compiler::target::word Thread_callback_code_offset =
- 1312;
+ 1320;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
16;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -707,15 +697,15 @@
static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
0;
-static constexpr dart::compiler::target::word ClassTable_element_size = 288;
+static constexpr dart::compiler::target::word ClassTable_element_size = 1;
static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
8, 24, 16, 32};
static constexpr dart::compiler::target::word
Code_function_entry_point_offset[] = {8, 16};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 1168, 1176, 1184, 1192, -1, -1, 1200, 1208,
- 1216, 1224, 1232, -1, 1240, 1248, -1, -1};
+ 1176, 1184, 1192, 1200, -1, -1, 1208, 1216,
+ 1224, 1232, 1240, -1, 1248, 1256, -1, -1};
static constexpr dart::compiler::target::word Array_header_size = 24;
static constexpr dart::compiler::target::word Context_header_size = 24;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
@@ -799,14 +789,7 @@
static constexpr dart::compiler::target::word
Class_type_arguments_field_offset_in_words_offset = 96;
static constexpr dart::compiler::target::word
- ClassHeapStats_TraceAllocationMask = 1;
-static constexpr dart::compiler::target::word
- ClassHeapStats_allocated_since_gc_new_space_offset = 48;
-static constexpr dart::compiler::target::word
- ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
-static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 160;
-static constexpr dart::compiler::target::word
- ClassTable_shared_class_table_offset = 20;
+ ClassTable_shared_class_table_offset = 16;
static constexpr dart::compiler::target::word ClassTable_table_offset = 8;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
@@ -867,7 +850,7 @@
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 36;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 64;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 60;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 16;
static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 16;
static constexpr dart::compiler::target::word
@@ -915,11 +898,11 @@
static constexpr dart::compiler::target::word String_length_offset = 4;
static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 4;
static constexpr dart::compiler::target::word
- Thread_AllocateArray_entry_point_offset = 292;
+ Thread_AllocateArray_entry_point_offset = 296;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
- 592;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
596;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+ 600;
static constexpr dart::compiler::target::word
Thread_array_write_barrier_code_offset = 120;
static constexpr dart::compiler::target::word
@@ -927,14 +910,16 @@
static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
88;
static constexpr dart::compiler::target::word
- Thread_auto_scope_native_wrapper_entry_point_offset = 252;
+ Thread_auto_scope_native_wrapper_entry_point_offset = 256;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 112;
static constexpr dart::compiler::target::word Thread_bool_true_offset = 108;
static constexpr dart::compiler::target::word
+ Thread_bootstrap_native_wrapper_entry_point_offset = 248;
+static constexpr dart::compiler::target::word
Thread_call_to_runtime_entry_point_offset = 208;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 140;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 628;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 632;
static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
236;
static constexpr dart::compiler::target::word Thread_optimize_stub_offset = 164;
@@ -943,14 +928,14 @@
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
168;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
- 272;
+ 276;
static constexpr dart::compiler::target::word
- Thread_double_negate_address_offset = 268;
+ Thread_double_negate_address_offset = 272;
static constexpr dart::compiler::target::word Thread_end_offset = 64;
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 188;
static constexpr dart::compiler::target::word Thread_execution_state_offset =
- 612;
+ 616;
static constexpr dart::compiler::target::word
Thread_exit_safepoint_stub_offset = 192;
static constexpr dart::compiler::target::word
@@ -962,17 +947,17 @@
static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 124;
static constexpr dart::compiler::target::word
- Thread_float_absolute_address_offset = 284;
+ Thread_float_absolute_address_offset = 288;
static constexpr dart::compiler::target::word
- Thread_float_negate_address_offset = 280;
+ Thread_float_negate_address_offset = 284;
static constexpr dart::compiler::target::word Thread_float_not_address_offset =
- 276;
+ 280;
static constexpr dart::compiler::target::word
- Thread_float_zerow_address_offset = 288;
+ Thread_float_zerow_address_offset = 292;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
- 600;
+ 604;
static constexpr dart::compiler::target::word
- Thread_interpret_call_entry_point_offset = 256;
+ Thread_interpret_call_entry_point_offset = 260;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_from_bytecode_stub_offset = 136;
static constexpr dart::compiler::target::word
@@ -993,7 +978,7 @@
static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 160;
static constexpr dart::compiler::target::word
- Thread_no_scope_native_wrapper_entry_point_offset = 248;
+ Thread_no_scope_native_wrapper_entry_point_offset = 252;
static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_entry_point_offset = 216;
static constexpr dart::compiler::target::word
@@ -1004,12 +989,12 @@
Thread_null_error_shared_without_fpu_regs_stub_offset = 144;
static constexpr dart::compiler::target::word Thread_object_null_offset = 104;
static constexpr dart::compiler::target::word
- Thread_predefined_symbols_address_offset = 260;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 604;
+ Thread_predefined_symbols_address_offset = 264;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 608;
static constexpr dart::compiler::target::word
- Thread_saved_shadow_call_stack_offset = 608;
+ Thread_saved_shadow_call_stack_offset = 612;
static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
- 616;
+ 620;
static constexpr dart::compiler::target::word
Thread_slow_type_test_stub_offset = 180;
static constexpr dart::compiler::target::word Thread_stack_limit_offset = 36;
@@ -1040,7 +1025,7 @@
Thread_write_barrier_entry_point_offset = 200;
static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
48;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 620;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 624;
static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -1066,7 +1051,7 @@
static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
0;
-static constexpr dart::compiler::target::word ClassTable_element_size = 168;
+static constexpr dart::compiler::target::word ClassTable_element_size = 1;
static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
4, 12, 8, 16};
static constexpr dart::compiler::target::word
@@ -1156,14 +1141,7 @@
static constexpr dart::compiler::target::word
Class_type_arguments_field_offset_in_words_offset = 180;
static constexpr dart::compiler::target::word
- ClassHeapStats_TraceAllocationMask = 1;
-static constexpr dart::compiler::target::word
- ClassHeapStats_allocated_since_gc_new_space_offset = 96;
-static constexpr dart::compiler::target::word
- ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
-static constexpr dart::compiler::target::word ClassHeapStats_state_offset = 272;
-static constexpr dart::compiler::target::word
- ClassTable_shared_class_table_offset = 40;
+ ClassTable_shared_class_table_offset = 32;
static constexpr dart::compiler::target::word ClassTable_table_offset = 16;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
@@ -1224,7 +1202,7 @@
static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
static constexpr dart::compiler::target::word Isolate_object_store_offset = 72;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 128;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 120;
static constexpr dart::compiler::target::word Isolate_user_tag_offset = 32;
static constexpr dart::compiler::target::word LinkedHashMap_data_offset = 32;
static constexpr dart::compiler::target::word
@@ -1272,7 +1250,7 @@
static constexpr dart::compiler::target::word String_length_offset = 8;
static constexpr dart::compiler::target::word SubtypeTestCache_cache_offset = 8;
static constexpr dart::compiler::target::word
- Thread_AllocateArray_entry_point_offset = 568;
+ Thread_AllocateArray_entry_point_offset = 576;
static constexpr dart::compiler::target::word Thread_active_exception_offset =
1344;
static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
@@ -1284,10 +1262,12 @@
static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
176;
static constexpr dart::compiler::target::word
- Thread_auto_scope_native_wrapper_entry_point_offset = 488;
+ Thread_auto_scope_native_wrapper_entry_point_offset = 496;
static constexpr dart::compiler::target::word Thread_bool_false_offset = 208;
static constexpr dart::compiler::target::word Thread_bool_true_offset = 200;
static constexpr dart::compiler::target::word
+ Thread_bootstrap_native_wrapper_entry_point_offset = 480;
+static constexpr dart::compiler::target::word
Thread_call_to_runtime_entry_point_offset = 400;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
@@ -1300,9 +1280,9 @@
static constexpr dart::compiler::target::word Thread_deoptimize_stub_offset =
320;
static constexpr dart::compiler::target::word Thread_double_abs_address_offset =
- 528;
+ 536;
static constexpr dart::compiler::target::word
- Thread_double_negate_address_offset = 520;
+ Thread_double_negate_address_offset = 528;
static constexpr dart::compiler::target::word Thread_end_offset = 128;
static constexpr dart::compiler::target::word
Thread_enter_safepoint_stub_offset = 360;
@@ -1319,17 +1299,17 @@
static constexpr dart::compiler::target::word
Thread_fix_callers_target_code_offset = 232;
static constexpr dart::compiler::target::word
- Thread_float_absolute_address_offset = 552;
+ Thread_float_absolute_address_offset = 560;
static constexpr dart::compiler::target::word
- Thread_float_negate_address_offset = 544;
+ Thread_float_negate_address_offset = 552;
static constexpr dart::compiler::target::word Thread_float_not_address_offset =
- 536;
+ 544;
static constexpr dart::compiler::target::word
- Thread_float_zerow_address_offset = 560;
+ Thread_float_zerow_address_offset = 568;
static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
1360;
static constexpr dart::compiler::target::word
- Thread_interpret_call_entry_point_offset = 496;
+ Thread_interpret_call_entry_point_offset = 504;
static constexpr dart::compiler::target::word
Thread_invoke_dart_code_from_bytecode_stub_offset = 256;
static constexpr dart::compiler::target::word
@@ -1350,7 +1330,7 @@
static constexpr dart::compiler::target::word
Thread_monomorphic_miss_stub_offset = 304;
static constexpr dart::compiler::target::word
- Thread_no_scope_native_wrapper_entry_point_offset = 480;
+ Thread_no_scope_native_wrapper_entry_point_offset = 488;
static constexpr dart::compiler::target::word
Thread_null_error_shared_with_fpu_regs_entry_point_offset = 416;
static constexpr dart::compiler::target::word
@@ -1361,7 +1341,7 @@
Thread_null_error_shared_without_fpu_regs_stub_offset = 272;
static constexpr dart::compiler::target::word Thread_object_null_offset = 192;
static constexpr dart::compiler::target::word
- Thread_predefined_symbols_address_offset = 504;
+ Thread_predefined_symbols_address_offset = 512;
static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1368;
static constexpr dart::compiler::target::word
Thread_saved_shadow_call_stack_offset = 1376;
@@ -1425,16 +1405,16 @@
static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
0;
-static constexpr dart::compiler::target::word ClassTable_element_size = 288;
+static constexpr dart::compiler::target::word ClassTable_element_size = 1;
static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
8, 24, 16, 32};
static constexpr dart::compiler::target::word
Code_function_entry_point_offset[] = {8, 16};
static constexpr dart::compiler::target::word
Thread_write_barrier_wrappers_thread_offset[] = {
- 1168, 1176, 1184, 1192, 1200, 1208, 1216, 1224, 1232, 1240, 1248,
- 1256, 1264, 1272, 1280, -1, -1, -1, -1, 1288, 1296, 1304,
- 1312, 1320, 1328, 1336, -1, -1, -1, -1, -1, -1};
+ 1176, 1184, 1192, 1200, 1208, 1216, 1224, 1232, 1240, 1248, 1256,
+ 1264, 1272, 1280, 1288, -1, -1, -1, -1, 1296, 1304, 1312,
+ -1, 1320, 1328, 1336, -1, -1, -1, -1, -1, -1};
static constexpr dart::compiler::target::word Array_header_size = 24;
static constexpr dart::compiler::target::word Context_header_size = 24;
static constexpr dart::compiler::target::word Double_InstanceSize = 16;
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index dc49487..7631752 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -65,11 +65,6 @@
FIELD(Class, num_type_arguments_offset) \
FIELD(Class, super_type_offset) \
FIELD(Class, type_arguments_field_offset_in_words_offset) \
- NOT_IN_PRODUCT(FIELD(ClassHeapStats, TraceAllocationMask)) \
- NOT_IN_PRODUCT(FIELD(ClassHeapStats, allocated_since_gc_new_space_offset)) \
- NOT_IN_PRODUCT( \
- FIELD(ClassHeapStats, allocated_size_since_gc_new_space_offset)) \
- NOT_IN_PRODUCT(FIELD(ClassHeapStats, state_offset)) \
FIELD(ClassTable, shared_class_table_offset) \
FIELD(ClassTable, table_offset) \
NOT_IN_PRODUCT(FIELD(SharedClassTable, class_heap_stats_table_offset)) \
@@ -155,6 +150,7 @@
FIELD(Thread, auto_scope_native_wrapper_entry_point_offset) \
FIELD(Thread, bool_false_offset) \
FIELD(Thread, bool_true_offset) \
+ FIELD(Thread, bootstrap_native_wrapper_entry_point_offset) \
FIELD(Thread, call_to_runtime_entry_point_offset) \
FIELD(Thread, call_to_runtime_stub_offset) \
FIELD(Thread, dart_stream_offset) \
@@ -236,14 +232,6 @@
ARRAY(Array, element_offset) \
ARRAY(TypeArguments, type_at_offset) \
NOT_IN_PRODUCT(ARRAY(ClassTable, ClassOffsetFor)) \
- NOT_IN_PRODUCT(ARRAY_STRUCTFIELD( \
- ClassTable, NewSpaceCounterOffsetFor, ClassOffsetFor, \
- ClassHeapStats::allocated_since_gc_new_space_offset())) \
- NOT_IN_PRODUCT(ARRAY_STRUCTFIELD(ClassTable, StateOffsetFor, ClassOffsetFor, \
- ClassHeapStats::state_offset())) \
- NOT_IN_PRODUCT(ARRAY_STRUCTFIELD( \
- ClassTable, NewSpaceSizeOffsetFor, ClassOffsetFor, \
- ClassHeapStats::allocated_size_since_gc_new_space_offset())) \
RANGE(Code, entry_point_offset, CodeEntryKind, CodeEntryKind::kNormal, \
CodeEntryKind::kMonomorphicUnchecked, \
[](CodeEntryKind value) { return true; }) \
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index f506902..901940d 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -602,83 +602,10 @@
// R2 : address of first argument in argument array.
// R1 : argc_tag including number of arguments and function kind.
void StubCodeCompiler::GenerateCallBootstrapNativeStub(Assembler* assembler) {
- const intptr_t thread_offset = target::NativeArguments::thread_offset();
- const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
- const intptr_t argv_offset = target::NativeArguments::argv_offset();
- const intptr_t retval_offset = target::NativeArguments::retval_offset();
-
- __ EnterStubFrame();
-
- // Save exit frame information to enable stack walking as we are about
- // to transition to native code.
- __ StoreToOffset(kWord, FP, THR,
- target::Thread::top_exit_frame_info_offset());
-
-#if defined(DEBUG)
- {
- Label ok;
- // Check that we are always entering from Dart code.
- __ LoadFromOffset(kWord, R8, THR, target::Thread::vm_tag_offset());
- __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
- __ b(&ok, EQ);
- __ Stop("Not coming from Dart code.");
- __ Bind(&ok);
- }
-#endif
-
- // Mark that the thread is executing native code.
- __ StoreToOffset(kWord, R9, THR, target::Thread::vm_tag_offset());
-
- // Reserve space for the native arguments structure passed on the stack (the
- // outgoing pointer parameter to the native arguments structure is passed in
- // R0) and align frame before entering the C++ world.
- __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
-
- // Initialize target::NativeArguments structure and call native function.
- // Registers R0, R1, R2, and R3 are used.
-
- ASSERT(thread_offset == 0 * target::kWordSize);
- // Set thread in NativeArgs.
- __ mov(R0, Operand(THR));
-
- // There are no native calls to closures, so we do not need to set the tag
- // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
- ASSERT(argc_tag_offset == 1 * target::kWordSize);
- // Set argc in target::NativeArguments: R1 already contains argc.
-
- ASSERT(argv_offset == 2 * target::kWordSize);
- // Set argv in target::NativeArguments: R2 already contains argv.
-
- // Set retval in NativeArgs.
- ASSERT(retval_offset == 3 * target::kWordSize);
- __ add(R3, FP, Operand(2 * target::kWordSize));
-
- // Passing the structure by value as in runtime calls would require changing
- // Dart API for native functions.
- // For now, space is reserved on the stack and we pass a pointer to it.
- __ stm(IA, SP, (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3));
- __ mov(R0, Operand(SP)); // Pass the pointer to the target::NativeArguments.
-
- // Call native function or redirection via simulator.
- __ blx(R9);
-
- // Mark that the thread is executing Dart code.
- __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
- __ StoreToOffset(kWord, R2, THR, target::Thread::vm_tag_offset());
-
- // Reset exit frame information in Isolate structure.
- __ LoadImmediate(R2, 0);
- __ StoreToOffset(kWord, R2, THR,
- target::Thread::top_exit_frame_info_offset());
-
- // Restore the global object pool after returning from runtime (old space is
- // moving, so the GOP could have been relocated).
- if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
- __ ldr(PP, Address(THR, target::Thread::global_object_pool_offset()));
- }
-
- __ LeaveStubFrame();
- __ Ret();
+ GenerateCallNativeWithWrapperStub(
+ assembler,
+ Address(THR,
+ target::Thread::bootstrap_native_wrapper_entry_point_offset()));
}
// Input parameters:
@@ -1123,13 +1050,11 @@
// Successfully allocated the object(s), now update top to point to
// next object start and initialize the object.
- NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R3, cid));
__ str(NOTFP, Address(THR, target::Thread::top_offset()));
__ add(R0, R0, Operand(kHeapObjectTag));
// Initialize the tags.
// R0: new object start as a tagged pointer.
- // R3: allocation stats address.
// NOTFP: new object end address.
// R9: allocation size.
{
@@ -1161,13 +1086,11 @@
// Initialize all array elements to raw_null.
// R0: new object start as a tagged pointer.
- // R3: allocation stats address.
// R8, R9: null
// R4: iterator which initially points to the start of the variable
// data area to be initialized.
// NOTFP: new object end address.
// R9: allocation size.
- NOT_IN_PRODUCT(__ IncrementAllocationStatsWithSize(R3, R9));
__ LoadObject(R8, NullObject());
__ mov(R9, Operand(R8));
@@ -1518,7 +1441,6 @@
// R1: number of context variables.
// R2: object size.
// R3: next object start.
- NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R4, cid));
__ str(R3, Address(THR, target::Thread::top_offset()));
__ add(R0, R0, Operand(kHeapObjectTag));
@@ -1527,7 +1449,6 @@
// R1: number of context variables.
// R2: object size.
// R3: next object start.
- // R4: allocation stats address.
const intptr_t shift = target::RawObject::kTagBitsSizeTagPos -
target::ObjectAlignment::kObjectAlignmentLog2;
__ CompareImmediate(R2, target::RawObject::kSizeTagMaxSizeTag);
@@ -1549,7 +1470,6 @@
// R1: number of context variables as integer value (not object).
// R2: object size.
// R3: next object start.
- // R4: allocation stats address.
__ str(R1, FieldAddress(R0, target::Context::num_variables_offset()));
// Setup the parent field.
@@ -1557,7 +1477,6 @@
// R1: number of context variables.
// R2: object size.
// R3: next object start.
- // R4: allocation stats address.
__ LoadObject(R8, NullObject());
__ MoveRegister(R9, R8); // Needed for InitializeFieldsNoBarrier.
__ StoreIntoObjectNoBarrier(
@@ -1569,12 +1488,10 @@
// R2: object size.
// R3: next object start.
// R8, R9: raw null.
- // R4: allocation stats address.
Label loop;
__ AddImmediate(NOTFP, R0,
target::Context::variable_offset(0) - kHeapObjectTag);
__ InitializeFieldsNoBarrier(R0, NOTFP, R3, R8, R9);
- NOT_IN_PRODUCT(__ IncrementAllocationStatsWithSize(R4, R2));
// Done allocating and initializing the context.
// R0: new object.
@@ -1849,12 +1766,6 @@
}
__ str(kEndOfInstanceReg, Address(THR, target::Thread::top_offset()));
- // Load the address of the allocation stats table. We split up the load
- // and the increment so that the dependent load is not too nearby.
- NOT_IN_PRODUCT(static Register kAllocationStatsReg = R4);
- NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(kAllocationStatsReg,
- target::Class::GetId(cls)));
-
// Set the tags.
ASSERT(target::Class::GetId(cls) != kIllegalCid);
const uint32_t tags = target::MakeTagWordForNewSpaceObject(
@@ -1888,10 +1799,6 @@
kInstanceReg, FieldAddress(kInstanceReg, offset), kTypeArgumentsReg);
}
- // Update allocation stats.
- NOT_IN_PRODUCT(__ IncrementAllocationStats(kAllocationStatsReg,
- target::Class::GetId(cls)));
-
__ Ret();
__ Bind(&slow_case);
}
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 688e60b..afebf6d 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -147,9 +147,8 @@
__ mov(SP, CSP);
__ mov(CSP, R25);
- // Refresh write barrier mask.
- __ ldr(BARRIER_MASK,
- Address(THR, target::Thread::write_barrier_mask_offset()));
+ // Refresh pinned registers values (inc. write barrier mask and null object).
+ __ RestorePinnedRegisters();
// Retval is next to 1st argument.
// Mark that the thread is executing Dart code.
@@ -624,9 +623,8 @@
__ mov(SP, CSP);
__ mov(CSP, R25);
- // Refresh write barrier mask.
- __ ldr(BARRIER_MASK,
- Address(THR, target::Thread::write_barrier_mask_offset()));
+ // Refresh pinned registers values (inc. write barrier mask and null object).
+ __ RestorePinnedRegisters();
// Mark that the thread is executing Dart code.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
@@ -667,98 +665,10 @@
// R2 : address of first argument in argument array.
// R1 : argc_tag including number of arguments and function kind.
void StubCodeCompiler::GenerateCallBootstrapNativeStub(Assembler* assembler) {
- const intptr_t thread_offset = target::NativeArguments::thread_offset();
- const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
- const intptr_t argv_offset = target::NativeArguments::argv_offset();
- const intptr_t retval_offset = target::NativeArguments::retval_offset();
-
- __ EnterStubFrame();
-
- // Save exit frame information to enable stack walking as we are about
- // to transition to native code.
- __ StoreToOffset(FP, THR, target::Thread::top_exit_frame_info_offset());
-
-#if defined(DEBUG)
- {
- Label ok;
- // Check that we are always entering from Dart code.
- __ LoadFromOffset(R6, THR, target::Thread::vm_tag_offset());
- __ CompareImmediate(R6, VMTag::kDartCompiledTagId);
- __ b(&ok, EQ);
- __ Stop("Not coming from Dart code.");
- __ Bind(&ok);
- }
-#endif
-
- // Mark that the thread is executing native code.
- __ StoreToOffset(R5, THR, target::Thread::vm_tag_offset());
-
- // Reserve space for the native arguments structure passed on the stack (the
- // outgoing pointer parameter to the native arguments structure is passed in
- // R0) and align frame before entering the C++ world.
- __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
-
- // Initialize target::NativeArguments structure and call native function.
- // Registers R0, R1, R2, and R3 are used.
-
- ASSERT(thread_offset == 0 * target::kWordSize);
- // Set thread in NativeArgs.
- __ mov(R0, THR);
-
- // There are no native calls to closures, so we do not need to set the tag
- // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
- ASSERT(argc_tag_offset == 1 * target::kWordSize);
- // Set argc in target::NativeArguments: R1 already contains argc.
-
- ASSERT(argv_offset == 2 * target::kWordSize);
- // Set argv in target::NativeArguments: R2 already contains argv.
-
- // Set retval in NativeArgs.
- ASSERT(retval_offset == 3 * target::kWordSize);
- __ AddImmediate(R3, FP, 2 * target::kWordSize);
-
- // Passing the structure by value as in runtime calls would require changing
- // Dart API for native functions.
- // For now, space is reserved on the stack and we pass a pointer to it.
- __ StoreToOffset(R0, SP, thread_offset);
- __ StoreToOffset(R1, SP, argc_tag_offset);
- __ StoreToOffset(R2, SP, argv_offset);
- __ StoreToOffset(R3, SP, retval_offset);
- __ mov(R0, SP); // Pass the pointer to the target::NativeArguments.
-
- // We are entering runtime code, so the C stack pointer must be restored from
- // the stack limit to the top of the stack. We cache the stack limit address
- // in the Dart SP register, which is callee-saved in the C ABI.
- __ mov(R25, CSP);
- __ mov(CSP, SP);
-
- // Call native function or redirection via simulator.
- __ blr(R5);
-
- // Restore SP and CSP.
- __ mov(SP, CSP);
- __ mov(CSP, R25);
-
- // Refresh write barrier mask.
- __ ldr(BARRIER_MASK,
- Address(THR, target::Thread::write_barrier_mask_offset()));
-
- // Mark that the thread is executing Dart code.
- __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
- __ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
-
- // Reset exit frame information in Isolate structure.
- __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
-
- // Restore the global object pool after returning from runtime (old space is
- // moving, so the GOP could have been relocated).
- if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
- __ ldr(PP, Address(THR, target::Thread::global_object_pool_offset()));
- __ sub(PP, PP, Operand(kHeapObjectTag)); // Pool in PP is untagged!
- }
-
- __ LeaveStubFrame();
- __ ret();
+ GenerateCallNativeWithWrapperStub(
+ assembler,
+ Address(THR,
+ target::Thread::bootstrap_native_wrapper_entry_point_offset()));
}
// Input parameters:
@@ -1225,7 +1135,6 @@
// R7: potential next object start.
__ str(R7, Address(THR, target::Thread::top_offset()));
__ add(R0, R0, Operand(kHeapObjectTag));
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R3));
// R0: new object start as a tagged pointer.
// R1: array element type.
@@ -1268,13 +1177,12 @@
__ AddImmediate(R1, R0, target::Array::data_offset() - kHeapObjectTag);
// R1: iterator which initially points to the start of the variable
// data area to be initialized.
- __ LoadObject(TMP, NullObject());
Label loop, done;
__ Bind(&loop);
// TODO(cshapiro): StoreIntoObjectNoBarrier
__ CompareRegisters(R1, R7);
__ b(&done, CS);
- __ str(TMP, Address(R1)); // Store if unsigned lower.
+ __ str(NULL_REG, Address(R1)); // Store if unsigned lower.
__ AddImmediate(R1, target::kWordSize);
__ b(&loop); // Loop until R1 == R7.
__ Bind(&done);
@@ -1346,9 +1254,8 @@
__ mov(THR, R3);
}
- // Refresh write barrier mask.
- __ ldr(BARRIER_MASK,
- Address(THR, target::Thread::write_barrier_mask_offset()));
+ // Refresh pinned registers values (inc. write barrier mask and null object).
+ __ RestorePinnedRegisters();
// Save the current VMTag on the stack.
__ LoadFromOffset(R4, THR, target::Thread::vm_tag_offset());
@@ -1498,9 +1405,8 @@
__ mov(THR, R3);
}
- // Refresh write barrier mask.
- __ ldr(BARRIER_MASK,
- Address(THR, target::Thread::write_barrier_mask_offset()));
+ // Refresh pinned registers values (inc. write barrier mask and null object).
+ __ RestorePinnedRegisters();
// Save the current VMTag on the stack.
__ LoadFromOffset(R4, THR, target::Thread::vm_tag_offset());
@@ -1648,7 +1554,6 @@
// R3: next object start.
__ str(R3, Address(THR, target::Thread::top_offset()));
__ add(R0, R0, Operand(kHeapObjectTag));
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R2));
// Calculate the size tag.
// R0: new object.
@@ -2673,9 +2578,8 @@
__ mov(SP, CSP);
__ mov(CSP, R25);
- // Refresh write barrier mask.
- __ ldr(BARRIER_MASK,
- Address(THR, target::Thread::write_barrier_mask_offset()));
+ // Refresh pinned registers values (inc. write barrier mask and null object).
+ __ RestorePinnedRegisters();
// Mark that the thread is executing Dart code.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
@@ -3162,8 +3066,8 @@
#elif defined(USING_SHADOW_CALL_STACK)
#error Unimplemented
#endif
- __ ldr(BARRIER_MASK,
- Address(THR, target::Thread::write_barrier_mask_offset()));
+ // Refresh pinned registers values (inc. write barrier mask and null object).
+ __ RestorePinnedRegisters();
// Set the tag.
__ LoadImmediate(R2, VMTag::kDartCompiledTagId);
__ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 06817a0..8ed7559 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -417,67 +417,10 @@
// ECX : address of the native function to call.
// EDX : argc_tag including number of arguments and function kind.
void StubCodeCompiler::GenerateCallBootstrapNativeStub(Assembler* assembler) {
- const intptr_t native_args_struct_offset = target::kWordSize;
- const intptr_t thread_offset =
- target::NativeArguments::thread_offset() + native_args_struct_offset;
- const intptr_t argc_tag_offset =
- target::NativeArguments::argc_tag_offset() + native_args_struct_offset;
- const intptr_t argv_offset =
- target::NativeArguments::argv_offset() + native_args_struct_offset;
- const intptr_t retval_offset =
- target::NativeArguments::retval_offset() + native_args_struct_offset;
-
- __ EnterStubFrame();
-
- // Save exit frame information to enable stack walking as we are about
- // to transition to dart VM code.
- __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()), EBP);
-
-#if defined(DEBUG)
- {
- Label ok;
- // Check that we are always entering from Dart code.
- __ cmpl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
- __ j(EQUAL, &ok, Assembler::kNearJump);
- __ Stop("Not coming from Dart code.");
- __ Bind(&ok);
- }
-#endif
-
- // Mark that the thread is executing native code.
- __ movl(Assembler::VMTagAddress(), ECX);
-
- // Reserve space for the native arguments structure, the outgoing parameter
- // (pointer to the native arguments structure) and align frame before
- // entering the C++ world.
- __ AddImmediate(
- ESP,
- Immediate(-static_cast<int32_t>(target::NativeArguments::StructSize()) -
- target::kWordSize));
- if (OS::ActivationFrameAlignment() > 1) {
- __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
- }
-
- // Pass NativeArguments structure by value and call native function.
- __ movl(Address(ESP, thread_offset), THR); // Set thread in NativeArgs.
- __ movl(Address(ESP, argc_tag_offset), EDX); // Set argc in NativeArguments.
- __ movl(Address(ESP, argv_offset), EAX); // Set argv in NativeArguments.
- __ leal(EAX,
- Address(EBP, 2 * target::kWordSize)); // Compute return value addr.
- __ movl(Address(ESP, retval_offset), EAX); // Set retval in NativeArguments.
- __ leal(EAX,
- Address(ESP, target::kWordSize)); // Pointer to the NativeArguments.
- __ movl(Address(ESP, 0), EAX); // Pass the pointer to the NativeArguments.
- __ call(ECX);
-
- __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
-
- // Reset exit frame information in Isolate structure.
- __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
- Immediate(0));
-
- __ LeaveFrame();
- __ ret();
+ GenerateCallNativeWithWrapperStub(
+ assembler,
+ Address(THR,
+ target::Thread::bootstrap_native_wrapper_entry_point_offset()));
}
// Input parameters:
@@ -877,7 +820,6 @@
__ movl(Address(THR, target::Thread::top_offset()), EBX);
__ subl(EBX, EAX);
__ addl(EAX, Immediate(kHeapObjectTag));
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, EBX, EDI));
// Initialize the tags.
// EAX: new object start as a tagged pointer.
@@ -1260,7 +1202,6 @@
__ subl(EBX, EAX);
__ addl(EAX, Immediate(kHeapObjectTag));
// Generate isolate-independent code to allow sharing between isolates.
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, EBX, EDI));
// Calculate the size tag.
// EAX: new object.
@@ -1531,7 +1472,6 @@
__ j(ABOVE_EQUAL, &slow_case);
}
__ movl(Address(THR, target::Thread::top_offset()), EBX);
- NOT_IN_PRODUCT(__ UpdateAllocationStats(target::Class::GetId(cls), ECX));
// EAX: new object start (untagged).
// EBX: next object start.
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 5bdc6d2..b73316a 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -605,75 +605,10 @@
// RBX : address of the native function to call.
// R10 : argc_tag including number of arguments and function kind.
void StubCodeCompiler::GenerateCallBootstrapNativeStub(Assembler* assembler) {
- const intptr_t native_args_struct_offset = 0;
- const intptr_t thread_offset =
- target::NativeArguments::thread_offset() + native_args_struct_offset;
- const intptr_t argc_tag_offset =
- target::NativeArguments::argc_tag_offset() + native_args_struct_offset;
- const intptr_t argv_offset =
- target::NativeArguments::argv_offset() + native_args_struct_offset;
- const intptr_t retval_offset =
- target::NativeArguments::retval_offset() + native_args_struct_offset;
-
- __ EnterStubFrame();
-
- // Save exit frame information to enable stack walking as we are about
- // to transition to native code.
- __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()), RBP);
-
-#if defined(DEBUG)
- {
- Label ok;
- // Check that we are always entering from Dart code.
- __ movq(R8, Immediate(VMTag::kDartCompiledTagId));
- __ cmpq(R8, Assembler::VMTagAddress());
- __ j(EQUAL, &ok, Assembler::kNearJump);
- __ Stop("Not coming from Dart code.");
- __ Bind(&ok);
- }
-#endif
-
- // Mark that the thread is executing native code.
- __ movq(Assembler::VMTagAddress(), RBX);
-
- // Reserve space for the native arguments structure passed on the stack (the
- // outgoing pointer parameter to the native arguments structure is passed in
- // RDI) and align frame before entering the C++ world.
- __ subq(RSP, Immediate(target::NativeArguments::StructSize()));
- if (OS::ActivationFrameAlignment() > 1) {
- __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
- }
-
- // Pass target::NativeArguments structure by value and call native function.
- __ movq(Address(RSP, thread_offset), THR); // Set thread in NativeArgs.
- __ movq(Address(RSP, argc_tag_offset),
- R10); // Set argc in target::NativeArguments.
- __ movq(Address(RSP, argv_offset),
- RAX); // Set argv in target::NativeArguments.
- __ leaq(RAX,
- Address(RBP, 2 * target::kWordSize)); // Compute return value addr.
- __ movq(Address(RSP, retval_offset),
- RAX); // Set retval in target::NativeArguments.
-
- // Pass the pointer to the target::NativeArguments.
- __ movq(CallingConventions::kArg1Reg, RSP);
- __ CallCFunction(RBX);
-
- // Mark that the thread is executing Dart code.
- __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
-
- // Reset exit frame information in Isolate structure.
- __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
- Immediate(0));
-
- // Restore the global object pool after returning from runtime (old space is
- // moving, so the GOP could have been relocated).
- if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
- __ movq(PP, Address(THR, target::Thread::global_object_pool_offset()));
- }
-
- __ LeaveStubFrame();
- __ ret();
+ GenerateCallNativeWithWrapperStub(
+ assembler,
+ Address(THR,
+ target::Thread::bootstrap_native_wrapper_entry_point_offset()));
}
// Input parameters:
@@ -1123,7 +1058,7 @@
// next object start and initialize the object.
__ movq(Address(THR, target::Thread::top_offset()), RCX);
__ addq(RAX, Immediate(kHeapObjectTag));
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, RDI));
+
// Initialize the tags.
// RAX: new object start as a tagged pointer.
// RDI: allocation size.
@@ -1553,7 +1488,6 @@
__ subq(R13, RAX);
__ addq(RAX, Immediate(kHeapObjectTag));
// Generate isolate-independent code to allow sharing between isolates.
- NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R13));
// Calculate the size tag.
// RAX: new object.
@@ -1871,7 +1805,6 @@
__ j(ABOVE_EQUAL, &slow_case);
}
__ movq(Address(THR, target::Thread::top_offset()), RBX);
- NOT_IN_PRODUCT(__ UpdateAllocationStats(target::Class::GetId(cls)));
// RAX: new object start (untagged).
// RBX: next object start.
diff --git a/runtime/vm/constants_arm64.cc b/runtime/vm/constants_arm64.cc
index 95a52c0..7248ef1 100644
--- a/runtime/vm/constants_arm64.cc
+++ b/runtime/vm/constants_arm64.cc
@@ -10,7 +10,7 @@
const char* cpu_reg_names[kNumberOfCpuRegisters] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10",
"r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21",
- "r22", "r23", "r24", "ip0", "ip1", "pp", "ctx", "fp", "lr", "r31",
+ "nr", "r23", "r24", "ip0", "ip1", "pp", "ctx", "fp", "lr", "r31",
};
const char* fpu_reg_names[kNumberOfFpuRegisters] = {
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index cca7779..d141f81 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -36,7 +36,7 @@
R19 = 19,
R20 = 20,
R21 = 21,
- R22 = 22,
+ R22 = 22, // NULL_REG
R23 = 23,
R24 = 24,
R25 = 25,
@@ -124,6 +124,7 @@
const Register CALLEE_SAVED_TEMP = R19;
const Register CALLEE_SAVED_TEMP2 = R20;
const Register BARRIER_MASK = R28;
+const Register NULL_REG = R22; // Caches NullObject() value.
// ABI for catch-clause entry point.
const Register kExceptionObjectReg = R0;
@@ -173,9 +174,9 @@
const intptr_t kReservedCpuRegisters =
(1 << SPREG) | // Dart SP
(1 << FPREG) | (1 << TMP) | (1 << TMP2) | (1 << PP) | (1 << THR) |
- (1 << LR) | (1 << BARRIER_MASK) | (1 << R31) | // C++ SP
+ (1 << LR) | (1 << BARRIER_MASK) | (1 << NULL_REG) | (1 << R31) | // C++ SP
(1 << R18);
-constexpr intptr_t kNumberOfReservedCpuRegisters = 10;
+constexpr intptr_t kNumberOfReservedCpuRegisters = 11;
// CPU registers available to Dart allocator.
const RegList kDartAvailableCpuRegs =
kAllCpuRegistersList & ~kReservedCpuRegisters;
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 025d22d..1c59cac 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -553,9 +553,9 @@
V(UnusedOpcode079, 0, RESV, ___, ___, ___) \
V(UnusedOpcode080, 0, RESV, ___, ___, ___) \
V(UnusedOpcode081, 0, RESV, ___, ___, ___) \
- V(UnusedOpcode082, 0, RESV, ___, ___, ___) \
- V(UnusedOpcode083, 0, RESV, ___, ___, ___) \
- V(UnusedOpcode084, 0, RESV, ___, ___, ___) \
+ V(JumpIfInitialized, T, ORDN, tgt, ___, ___) \
+ V(JumpIfInitialized_Wide, T, WIDE, tgt, ___, ___) \
+ V(PushUninitializedSentinel, 0, ORDN, ___, ___, ___) \
V(Trap, 0, ORDN, ___, ___, ___) \
V(Entry, D, ORDN, num, ___, ___) \
V(Entry_Wide, D, WIDE, num, ___, ___) \
@@ -749,7 +749,7 @@
// Maximum bytecode format version supported by VM.
// The range of supported versions should include version produced by bytecode
// generator (currentBytecodeFormatVersion in pkg/vm/lib/bytecode/dbc.dart).
- static const intptr_t kMaxSupportedBytecodeFormatVersion = 26;
+ static const intptr_t kMaxSupportedBytecodeFormatVersion = 27;
enum Opcode {
#define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name,
@@ -887,6 +887,8 @@
case KernelBytecode::kJumpIfNotNull_Wide:
case KernelBytecode::kJumpIfUnchecked:
case KernelBytecode::kJumpIfUnchecked_Wide:
+ case KernelBytecode::kJumpIfInitialized:
+ case KernelBytecode::kJumpIfInitialized_Wide:
return true;
default:
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index c3d91d4..4078722 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -175,7 +175,11 @@
CpuInfo::FieldContains(kCpuInfoModel, "ARMv7")) {
arm_version_ = ARMv7;
} else {
- FATAL("Unsupported ARM CPU architecture.");
+#if defined(DART_RUN_IN_QEMU_ARMv7)
+ arm_version_ = ARMv7;
+#else
+ FATAL("Unrecognized ARM CPU architecture.");
+#endif
}
// Has floating point unit.
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index a8a2f94..63b9e59 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -607,7 +607,7 @@
MallocHooks::Cleanup();
Flags::Cleanup();
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
- IsolateReloadContext::SetFileModifiedCallback(NULL);
+ IsolateGroupReloadContext::SetFileModifiedCallback(NULL);
Service::SetEmbedderStreamCallbacks(NULL, NULL);
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
return NULL;
@@ -851,6 +851,10 @@
buffer.AddString(FLAG_causal_async_stacks ? " causal_async_stacks"
: " no-causal_async_stacks");
+#if !defined(PRODUCT)
+ buffer.AddString(FLAG_code_comments ? " code-comments"
+ : " no-code-comments");
+#endif
// Generated code must match the host architecture and ABI.
#if defined(TARGET_ARCH_ARM)
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 7db09c1..b5b144d 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -152,7 +152,8 @@
ASSERT(!list_class.IsNull());
const Instance& instance = Instance::Cast(obj);
const Class& obj_class = Class::Handle(zone, obj.clazz());
- if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(), list_class,
+ if (Class::IsSubtypeOf(NNBDMode::kLegacy, obj_class,
+ Object::null_type_arguments(), list_class,
Object::null_type_arguments(), Heap::kNew)) {
return instance.raw();
}
@@ -168,7 +169,8 @@
ASSERT(!map_class.IsNull());
const Instance& instance = Instance::Cast(obj);
const Class& obj_class = Class::Handle(zone, obj.clazz());
- if (Class::IsSubtypeOf(obj_class, Object::null_type_arguments(), map_class,
+ if (Class::IsSubtypeOf(NNBDMode::kLegacy, obj_class,
+ Object::null_type_arguments(), map_class,
Object::null_type_arguments(), Heap::kNew)) {
return instance.raw();
}
@@ -2043,7 +2045,8 @@
RETURN_TYPE_ERROR(Z, object, Instance);
}
CHECK_CALLBACK_STATE(T);
- *value = instance.IsInstanceOf(type_obj, Object::null_type_arguments(),
+ *value = instance.IsInstanceOf(NNBDMode::kLegacy, type_obj,
+ Object::null_type_arguments(),
Object::null_type_arguments());
return Api::Success();
}
@@ -2205,8 +2208,8 @@
ASSERT(!future_class.IsNull());
const Class& obj_class = Class::Handle(Z, obj.clazz());
bool is_future = Class::IsSubtypeOf(
- obj_class, Object::null_type_arguments(), future_class,
- Object::null_type_arguments(), Heap::kNew);
+ NNBDMode::kLegacy, obj_class, Object::null_type_arguments(),
+ future_class, Object::null_type_arguments(), Heap::kNew);
return is_future;
}
return false;
@@ -4043,8 +4046,8 @@
// We do not support generic constructors.
ASSERT(redirect_type.IsInstantiated(kFunctions));
redirect_type ^= redirect_type.InstantiateFrom(
- type_arguments, Object::null_type_arguments(), kNoneFree, NULL,
- Heap::kNew);
+ NNBDMode::kLegacy, type_arguments, Object::null_type_arguments(),
+ kNoneFree, NULL, Heap::kNew);
redirect_type ^= redirect_type.Canonicalize();
}
@@ -5852,33 +5855,33 @@
}
#if !defined(DART_PRECOMPILED_RUNTIME)
if (file_modified_callback != NULL) {
- if (IsolateReloadContext::file_modified_callback() != NULL) {
+ if (IsolateGroupReloadContext::file_modified_callback() != NULL) {
return strdup(
"Dart_SetFileModifiedCallback permits only one callback to be"
" registered, please remove the existing callback and then add"
" this callback");
}
} else {
- if (IsolateReloadContext::file_modified_callback() == NULL) {
+ if (IsolateGroupReloadContext::file_modified_callback() == NULL) {
return strdup(
"Dart_SetFileModifiedCallback expects 'file_modified_callback' to"
" be set before it is cleared.");
}
}
- IsolateReloadContext::SetFileModifiedCallback(file_modified_callback);
+ IsolateGroupReloadContext::SetFileModifiedCallback(file_modified_callback);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
#endif // !defined(PRODUCT)
return NULL;
}
DART_EXPORT bool Dart_IsReloading() {
-#if defined(PRODUCT)
+#if defined(PRODUCT) || defined(DART_PRECOMPILED_RUNTIME)
return false;
#else
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
- return isolate->IsReloading();
+ return isolate->group()->IsReloading();
#endif
}
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 937f7cf..1ba6b82 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -1543,26 +1543,6 @@
}
}
-// Helper class to ensure new gen GC is triggered without any side effects.
-// The normal call to CollectGarbage(Heap::kNew) could potentially trigger
-// an old gen collection if there is a promotion failure and this could
-// perturb the test.
-class GCTestHelper : public AllStatic {
- public:
- static void CollectNewSpace() {
- Thread* thread = Thread::Current();
- ASSERT(thread->execution_state() == Thread::kThreadInVM);
- thread->heap()->new_space()->Scavenge();
- }
-
- static void WaitForGCTasks() {
- Thread* thread = Thread::Current();
- ASSERT(thread->execution_state() == Thread::kThreadInVM);
- thread->heap()->WaitForMarkerTasks(thread);
- thread->heap()->WaitForSweeperTasks(thread);
- }
-};
-
static void ExternalStringCallbackFinalizer(void* isolate_callback_data,
Dart_WeakPersistentHandle handle,
void* peer) {
@@ -1595,12 +1575,10 @@
TransitionNativeToVM transition(thread);
EXPECT_EQ(40, peer8);
EXPECT_EQ(41, peer16);
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
- GCTestHelper::WaitForGCTasks();
+ GCTestHelper::CollectOldSpace();
EXPECT_EQ(40, peer8);
EXPECT_EQ(41, peer16);
- Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
- GCTestHelper::WaitForGCTasks();
+ GCTestHelper::CollectNewSpace();
EXPECT_EQ(80, peer8);
EXPECT_EQ(82, peer16);
}
@@ -2288,7 +2266,7 @@
{
TransitionNativeToVM transition(Thread::Current());
- Isolate::Current()->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
}
EXPECT(!byte_data_finalizer_run);
@@ -2298,7 +2276,7 @@
{
TransitionNativeToVM transition(Thread::Current());
- Isolate::Current()->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
}
EXPECT(byte_data_finalizer_run);
@@ -2481,7 +2459,7 @@
virtual void Run() {
Thread::EnterIsolateAsHelper(isolate_, Thread::kUnknownTask);
for (intptr_t i = 0; i < 10; i++) {
- Thread::Current()->heap()->CollectAllGarbage(Heap::kDebugging);
+ GCTestHelper::CollectAllGarbage();
}
Thread::ExitIsolateAsHelper();
{
@@ -2801,11 +2779,9 @@
{
TransitionNativeToVM transition(thread);
EXPECT(peer == 0);
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
- GCTestHelper::WaitForGCTasks();
+ GCTestHelper::CollectOldSpace();
EXPECT(peer == 0);
- Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
- GCTestHelper::WaitForGCTasks();
+ GCTestHelper::CollectNewSpace();
EXPECT(peer == 42);
}
}
@@ -2830,15 +2806,10 @@
{
TransitionNativeToVM transition(thread);
- Isolate::Current()->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
}
}
- {
- TransitionNativeToVM transition(thread);
- GCTestHelper::WaitForGCTasks();
- }
-
EXPECT_EQ(20, count);
}
@@ -2890,8 +2861,7 @@
Dart_ExitScope();
{
TransitionNativeToVM transition(thread);
- Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
- GCTestHelper::WaitForGCTasks();
+ GCTestHelper::CollectNewSpace();
EXPECT(peer == 42);
}
}
@@ -3130,7 +3100,6 @@
TransitionNativeToVM transition(thread);
// Garbage collect new space.
GCTestHelper::CollectNewSpace();
- GCTestHelper::WaitForGCTasks();
}
// Nothing should be invalidated or cleared.
@@ -3150,8 +3119,7 @@
{
TransitionNativeToVM transition(thread);
// Garbage collect old space.
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
- GCTestHelper::WaitForGCTasks();
+ GCTestHelper::CollectOldSpace();
}
// Nothing should be invalidated or cleared.
@@ -3176,7 +3144,6 @@
TransitionNativeToVM transition(thread);
// Garbage collect new space again.
GCTestHelper::CollectNewSpace();
- GCTestHelper::WaitForGCTasks();
}
{
@@ -3191,8 +3158,7 @@
{
TransitionNativeToVM transition(thread);
// Garbage collect old space again.
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
- GCTestHelper::WaitForGCTasks();
+ GCTestHelper::CollectOldSpace();
}
{
@@ -3206,9 +3172,7 @@
{
TransitionNativeToVM transition(thread);
// Garbage collect one last time to revisit deleted handles.
- Isolate::Current()->heap()->CollectGarbage(Heap::kNew);
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
- GCTestHelper::WaitForGCTasks();
+ GCTestHelper::CollectAllGarbage();
}
}
@@ -3253,10 +3217,9 @@
}
{
TransitionNativeToVM transition(thread);
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
EXPECT(peer == 0);
GCTestHelper::CollectNewSpace();
- GCTestHelper::WaitForGCTasks();
EXPECT(peer == 42);
}
}
@@ -3279,10 +3242,9 @@
EXPECT(peer == 0);
{
TransitionNativeToVM transition(thread);
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
EXPECT(peer == 0);
GCTestHelper::CollectNewSpace();
- GCTestHelper::WaitForGCTasks();
EXPECT(peer == 0);
}
}
@@ -3329,13 +3291,12 @@
}
{
TransitionNativeToVM transition(thread);
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
EXPECT(heap->ExternalInWords(Heap::kNew) ==
(kWeak1ExternalSize + kWeak2ExternalSize) / kWordSize);
// Collect weakly referenced string, and promote strongly referenced string.
GCTestHelper::CollectNewSpace();
GCTestHelper::CollectNewSpace();
- GCTestHelper::WaitForGCTasks();
EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
EXPECT(heap->ExternalInWords(Heap::kOld) == kWeak2ExternalSize / kWordSize);
}
@@ -3345,8 +3306,7 @@
Dart_DeletePersistentHandle(strong_ref);
{
TransitionNativeToVM transition(thread);
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
- GCTestHelper::WaitForGCTasks();
+ GCTestHelper::CollectOldSpace();
EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
}
}
@@ -3389,8 +3349,7 @@
Dart_DeleteWeakPersistentHandle(isolate, weak1);
{
TransitionNativeToVM transition(thread);
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
- GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
+ GCTestHelper::CollectOldSpace();
EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
}
}
@@ -3466,8 +3425,7 @@
EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
{
TransitionNativeToVM transition(thread);
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
- GCTestHelper::WaitForGCTasks(); // Finalize GC for accurate live size.
+ GCTestHelper::CollectOldSpace();
EXPECT_EQ(0, heap->ExternalInWords(Heap::kOld));
}
}
@@ -3600,7 +3558,7 @@
{
TransitionNativeToVM transition(thread);
- Isolate::Current()->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
}
{
@@ -7308,7 +7266,7 @@
EXPECT(out == reinterpret_cast<void*>(&peer));
{
TransitionNativeToVM transition(thread);
- isolate->heap()->CollectGarbage(Heap::kNew);
+ GCTestHelper::CollectNewSpace();
EXPECT_EQ(1, isolate->heap()->PeerCount());
}
out = &out;
@@ -7318,7 +7276,7 @@
Dart_ExitScope();
{
TransitionNativeToVM transition(thread);
- isolate->heap()->CollectGarbage(Heap::kNew);
+ GCTestHelper::CollectNewSpace();
EXPECT_EQ(0, isolate->heap()->PeerCount());
}
}
@@ -7398,7 +7356,7 @@
Dart_ExitScope();
{
TransitionNativeToVM transition(thread);
- isolate->heap()->CollectGarbage(Heap::kNew);
+ GCTestHelper::CollectNewSpace();
EXPECT_EQ(0, isolate->heap()->PeerCount());
}
}
@@ -7429,9 +7387,9 @@
EXPECT_EQ(kPeerCount, isolate->heap()->PeerCount());
{
TransitionNativeToVM transition(thread);
- isolate->heap()->CollectGarbage(Heap::kNew);
+ GCTestHelper::CollectNewSpace();
EXPECT_EQ(kPeerCount, isolate->heap()->PeerCount());
- isolate->heap()->CollectGarbage(Heap::kNew);
+ GCTestHelper::CollectNewSpace();
EXPECT_EQ(kPeerCount, isolate->heap()->PeerCount());
}
}
@@ -7456,8 +7414,8 @@
EXPECT_EQ(1, isolate->heap()->PeerCount());
{
TransitionNativeToVM transition(thread);
- isolate->heap()->CollectGarbage(Heap::kNew);
- isolate->heap()->CollectGarbage(Heap::kNew);
+ GCTestHelper::CollectNewSpace();
+ GCTestHelper::CollectNewSpace();
}
{
CHECK_API_SCOPE(thread);
@@ -7497,7 +7455,7 @@
EXPECT(out == reinterpret_cast<void*>(&peer));
{
TransitionNativeToVM transition(thread);
- isolate->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
EXPECT_EQ(1, isolate->heap()->PeerCount());
}
EXPECT_VALID(Dart_GetPeer(str, &out));
@@ -7533,7 +7491,7 @@
EXPECT(out == reinterpret_cast<void*>(&peer));
{
TransitionNativeToVM transition(thread);
- isolate->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
EXPECT_EQ(1, isolate->heap()->PeerCount());
}
EXPECT_VALID(Dart_GetPeer(str, &out));
@@ -7542,7 +7500,7 @@
Dart_ExitScope();
{
TransitionNativeToVM transition(thread);
- isolate->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
EXPECT_EQ(0, isolate->heap()->PeerCount());
}
}
@@ -7629,7 +7587,7 @@
Dart_ExitScope();
{
TransitionNativeToVM transition(thread);
- isolate->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
EXPECT_EQ(0, isolate->heap()->PeerCount());
}
}
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 49e4b47..bfe8f9e 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -359,11 +359,12 @@
RawArray* ArgumentsDescriptor::New(intptr_t type_args_len,
intptr_t num_arguments,
- const Array& optional_arguments_names) {
+ const Array& optional_arguments_names,
+ Heap::Space space) {
const intptr_t num_named_args =
optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length();
if (num_named_args == 0) {
- return ArgumentsDescriptor::New(type_args_len, num_arguments);
+ return ArgumentsDescriptor::New(type_args_len, num_arguments, space);
}
ASSERT(type_args_len >= 0);
ASSERT(num_arguments >= 0);
@@ -377,8 +378,7 @@
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
const intptr_t descriptor_len = LengthFor(num_named_args);
- Array& descriptor =
- Array::Handle(zone, Array::New(descriptor_len, Heap::kOld));
+ Array& descriptor = Array::Handle(zone, Array::New(descriptor_len, space));
// Set length of type argument vector.
descriptor.SetAt(kTypeArgsLenIndex, Smi::Handle(Smi::New(type_args_len)));
@@ -428,27 +428,28 @@
}
RawArray* ArgumentsDescriptor::New(intptr_t type_args_len,
- intptr_t num_arguments) {
+ intptr_t num_arguments,
+ Heap::Space space) {
ASSERT(type_args_len >= 0);
ASSERT(num_arguments >= 0);
if ((type_args_len == 0) && (num_arguments < kCachedDescriptorCount)) {
return cached_args_descriptors_[num_arguments];
}
- return NewNonCached(type_args_len, num_arguments, true);
+ return NewNonCached(type_args_len, num_arguments, true, space);
}
RawArray* ArgumentsDescriptor::NewNonCached(intptr_t type_args_len,
intptr_t num_arguments,
- bool canonicalize) {
+ bool canonicalize,
+ Heap::Space space) {
// Build the arguments descriptor array, which consists of the length of the
// type argument vector, total argument count; the positional argument count;
// and a terminating null to simplify iterating in generated code.
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
const intptr_t descriptor_len = LengthFor(0);
- Array& descriptor =
- Array::Handle(zone, Array::New(descriptor_len, Heap::kOld));
+ Array& descriptor = Array::Handle(zone, Array::New(descriptor_len, space));
const Smi& arg_count = Smi::Handle(zone, Smi::New(num_arguments));
// Set type argument vector length.
@@ -479,7 +480,8 @@
void ArgumentsDescriptor::Init() {
for (int i = 0; i < kCachedDescriptorCount; i++) {
- cached_args_descriptors_[i] = NewNonCached(/*type_args_len=*/0, i, false);
+ cached_args_descriptors_[i] =
+ NewNonCached(/*type_args_len=*/0, i, false, Heap::kOld);
}
}
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 94764a3..980fcfc 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -74,13 +74,16 @@
// num_arguments) is indicated by a non-zero type_args_len.
static RawArray* New(intptr_t type_args_len,
intptr_t num_arguments,
- const Array& optional_arguments_names);
+ const Array& optional_arguments_names,
+ Heap::Space space = Heap::kOld);
// Allocate and return an arguments descriptor that has no optional
// arguments. All arguments are positional. The presence of a type argument
// vector as first argument (not counted in num_arguments) is indicated
// by a non-zero type_args_len.
- static RawArray* New(intptr_t type_args_len, intptr_t num_arguments);
+ static RawArray* New(intptr_t type_args_len,
+ intptr_t num_arguments,
+ Heap::Space space = Heap::kOld);
// Initialize the preallocated fixed length arguments descriptors cache.
static void Init();
@@ -119,7 +122,8 @@
static RawArray* NewNonCached(intptr_t type_args_len,
intptr_t num_arguments,
- bool canonicalize);
+ bool canonicalize,
+ Heap::Space space);
// Used by Simulator to parse argument descriptors.
static intptr_t name_index(intptr_t index) {
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 392705a..c5ce88a 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -969,7 +969,8 @@
if (type.IsDynamicType()) {
return true;
}
- if (exc_obj.IsInstanceOf(type, Object::null_type_arguments(),
+ if (exc_obj.IsInstanceOf(NNBDMode::kLegacy, type,
+ Object::null_type_arguments(),
Object::null_type_arguments())) {
return true;
}
@@ -1014,7 +1015,6 @@
// Attempt to determine the token pos and try index from the async closure.
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- const Script& script = Script::Handle(zone, function().script());
ASSERT(function_.IsAsyncGenClosure() || function_.IsAsyncClosure());
// This should only be called on frames that aren't active on the stack.
@@ -1057,28 +1057,17 @@
if (await_jump_var < 0) {
return;
}
- intptr_t await_to_token_map_index = await_jump_var - 1;
- const auto& array =
- GrowableObjectArray::Handle(zone, script.GetYieldPositions(function_));
- // await_jump_var is non zero means that array should not be empty
- // index also fall into the correct range
- ASSERT(array.Length() > 0 && await_to_token_map_index < array.Length());
- const Object& token_pos =
- Object::Handle(zone, array.At(await_to_token_map_index));
- ASSERT(token_pos.IsSmi());
- token_pos_ = TokenPosition(Smi::Cast(token_pos).Value());
- token_pos_initialized_ = true;
- GetPcDescriptors();
- PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind);
- while (iter.MoveNext()) {
- if (iter.TokenPos() == token_pos_) {
- // Match the lowest try index at this token position.
- // TODO(johnmccutchan): Is this heuristic precise enough?
- if (iter.TryIndex() != kInvalidTryIndex) {
- if ((try_index_ == -1) || (iter.TryIndex() < try_index_)) {
- try_index_ = iter.TryIndex();
- }
- }
+
+ const auto& pc_descriptors =
+ PcDescriptors::Handle(zone, code().pc_descriptors());
+ ASSERT(!pc_descriptors.IsNull());
+ PcDescriptors::Iterator it(pc_descriptors, RawPcDescriptors::kOther);
+ while (it.MoveNext()) {
+ if (it.YieldIndex() == await_jump_var) {
+ try_index_ = it.TryIndex();
+ token_pos_ = it.TokenPos();
+ token_pos_initialized_ = true;
+ return;
}
}
}
@@ -1911,16 +1900,6 @@
void Debugger::OnIsolateRunnable() {}
-static RawFunction* ResolveLibraryFunction(const Library& library,
- const String& fname) {
- ASSERT(!library.IsNull());
- const Object& object = Object::Handle(library.ResolveName(fname));
- if (!object.IsNull() && object.IsFunction()) {
- return Function::Cast(object).raw();
- }
- return Function::null();
-}
-
bool Debugger::SetupStepOverAsyncSuspension(const char** error) {
ActivationFrame* top_frame = TopDartFrame();
if (!IsAtAsyncJump(top_frame)) {
@@ -1974,26 +1953,6 @@
}
}
-RawFunction* Debugger::ResolveFunction(const Library& library,
- const String& class_name,
- const String& function_name) {
- ASSERT(!library.IsNull());
- ASSERT(!class_name.IsNull());
- ASSERT(!function_name.IsNull());
- if (class_name.Length() == 0) {
- return ResolveLibraryFunction(library, function_name);
- }
- const Class& cls = Class::Handle(library.LookupClass(class_name));
- Function& function = Function::Handle();
- if (!cls.IsNull()) {
- function = cls.LookupStaticFunction(function_name);
- if (function.IsNull()) {
- function = cls.LookupDynamicFunction(function_name);
- }
- }
- return function.raw();
-}
-
// Deoptimize all functions in the isolate.
// TODO(hausner): Actually we only need to deoptimize those functions
// that inline the function that contains the newly created breakpoint.
@@ -2266,8 +2225,9 @@
return NULL;
}
+ bool sync_async_end = false;
intptr_t synchronous_stack_trace_length =
- StackTraceUtils::CountFrames(thread, 0, async_function);
+ StackTraceUtils::CountFrames(thread, 0, async_function, &sync_async_end);
// Append the top frames from the synchronous stack trace, up until the active
// asynchronous function. We truncate the remainder of the synchronous
@@ -2304,8 +2264,11 @@
// Now we append the asynchronous causal stack trace. These are not active
// frames but a historical record of how this asynchronous function was
// activated.
+
+ intptr_t frame_skip =
+ sync_async_end ? StackTrace::kSyncAsyncCroppedFrames : 0;
while (!async_stack_trace.IsNull()) {
- for (intptr_t i = 0; i < async_stack_trace.Length(); i++) {
+ for (intptr_t i = frame_skip; i < async_stack_trace.Length(); i++) {
code_obj = async_stack_trace.CodeAtFrame(i);
if (code_obj.IsNull()) {
break;
@@ -2340,22 +2303,15 @@
}
}
// Follow the link.
+ frame_skip = async_stack_trace.skip_sync_start_in_parent_stack()
+ ? StackTrace::kSyncAsyncCroppedFrames
+ : 0;
async_stack_trace = async_stack_trace.async_link();
}
return stack_trace;
}
-#if !defined(DART_PRECOMPILED_RUNTIME)
-static bool CheckAndSkipAsync(int skip_sync_async_frames_count,
- const String& function_name) {
- return (skip_sync_async_frames_count == 2 &&
- function_name.Equals(Symbols::_ClosureCall())) ||
- (skip_sync_async_frames_count == 1 &&
- function_name.Equals(Symbols::_AsyncAwaitCompleterStart()));
-}
-#endif
-
DebuggerStackTrace* Debugger::CollectAwaiterReturnStackTrace() {
#if defined(DART_PRECOMPILED_RUNTIME)
// Causal async stacks are not supported in the AOT runtime.
@@ -2407,9 +2363,8 @@
if (skip_sync_async_frames_count > 0) {
function_name = function.QualifiedScrubbedName();
- if (CheckAndSkipAsync(skip_sync_async_frames_count, function_name)) {
- skip_sync_async_frames_count--;
- } else {
+ if (!StackTraceUtils::CheckAndSkipAsync(&skip_sync_async_frames_count,
+ function_name)) {
// Unexpected function in synchronous call of async function.
break;
}
@@ -2457,10 +2412,8 @@
if (skip_sync_async_frames_count > 0) {
function_name ^= function.QualifiedScrubbedName();
- if (CheckAndSkipAsync(skip_sync_async_frames_count,
- function_name)) {
- skip_sync_async_frames_count--;
- } else {
+ if (!StackTraceUtils::CheckAndSkipAsync(
+ &skip_sync_async_frames_count, function_name)) {
// Unexpected function in sync async call
skip_sync_async_frames_count = -1;
abort_attempt_to_navigate_through_sync_async = true;
@@ -2512,10 +2465,8 @@
if (skip_sync_async_frames_count > 0) {
function_name ^= function.QualifiedScrubbedName();
- if (CheckAndSkipAsync(skip_sync_async_frames_count,
- function_name)) {
- skip_sync_async_frames_count--;
- } else {
+ if (!StackTraceUtils::CheckAndSkipAsync(
+ &skip_sync_async_frames_count, function_name)) {
// Unexpected function in synchronous call of async function.
break;
}
@@ -4357,6 +4308,8 @@
Object& closure_or_null =
Object::Handle(zone, top_frame->GetAsyncOperation());
if (!closure_or_null.IsNull()) {
+ ASSERT(top_frame->function().IsAsyncClosure() ||
+ top_frame->function().IsAsyncGenClosure());
ASSERT(closure_or_null.IsInstance());
ASSERT(Instance::Cast(closure_or_null).IsClosure());
if (top_frame->function().is_declared_in_bytecode()) {
@@ -4376,18 +4329,16 @@
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
ASSERT(!top_frame->IsInterpreted());
- const Script& script = Script::Handle(zone, top_frame->SourceScript());
- const auto& yield_positions = GrowableObjectArray::Handle(
- zone, script.GetYieldPositions(top_frame->function()));
- // No yield statements
- if (yield_positions.IsNull() || (yield_positions.Length() == 0)) {
+ const auto& pc_descriptors =
+ PcDescriptors::Handle(zone, top_frame->code().pc_descriptors());
+ if (pc_descriptors.IsNull()) {
return false;
}
- intptr_t looking_for = top_frame->TokenPos().value();
- Smi& value = Smi::Handle(zone);
- for (int i = 0; i < yield_positions.Length(); i++) {
- value ^= yield_positions.At(i);
- if (value.Value() == looking_for) {
+ const TokenPosition looking_for = top_frame->TokenPos();
+ PcDescriptors::Iterator it(pc_descriptors, RawPcDescriptors::kOther);
+ while (it.MoveNext()) {
+ if (it.TokenPos() == looking_for &&
+ it.YieldIndex() != RawPcDescriptors::kInvalidYieldIndex) {
return true;
}
}
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 3300813..b1fdd40 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -507,10 +507,6 @@
}
void NotifyDoneLoading();
- RawFunction* ResolveFunction(const Library& library,
- const String& class_name,
- const String& function_name);
-
// Set breakpoint at closest location to function entry.
Breakpoint* SetBreakpointAtEntry(const Function& target_function,
bool single_shot);
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 761ea02..6d9ea92 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -192,16 +192,23 @@
if (cached_catch_entry_moves != NULL) {
cached_catch_entry_moves_ = *cached_catch_entry_moves;
}
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
- intptr_t num_vars = Smi::Value(code_->variables());
if (cached_catch_entry_moves_.IsEmpty()) {
- GetCatchEntryMovesFromDeopt(num_vars, frame);
- }
-#else
- if (cached_catch_entry_moves_.IsEmpty()) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ // Only AOT mode is supported.
ReadCompressedCatchEntryMoves();
+#elif defined(DART_PRECOMPILER)
+ // Both AOT and JIT modes are supported.
+ if (FLAG_precompiled_mode) {
+ ReadCompressedCatchEntryMoves();
+ } else {
+ GetCatchEntryMovesFromDeopt(code_->num_variables(), frame);
+ }
+#else
+ // Only JIT mode is supported.
+ ASSERT(!FLAG_precompiled_mode);
+ GetCatchEntryMovesFromDeopt(code_->num_variables(), frame);
+#endif
}
-#endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
}
}
if (needs_stacktrace || is_catch_all) {
@@ -323,7 +330,9 @@
CatchEntryMovesMapReader reader(td);
catch_entry_moves_ = reader.ReadMovesForPcOffset(pc_offset);
}
-#else
+#endif // defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
void GetCatchEntryMovesFromDeopt(intptr_t num_vars, StackFrame* frame) {
Isolate* isolate = thread_->isolate();
DeoptContext* deopt_context =
@@ -336,7 +345,7 @@
isolate->set_deopt_context(NULL);
delete deopt_context;
}
-#endif // defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
bool needs_stacktrace;
uword handler_pc;
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index a3d9e05..6912711 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -24,22 +24,40 @@
constexpr bool kDartUseBytecode = false;
#endif
+// The disassembler might be force included even in product builds so we need
+// to conditionally make these into product flags to make the disassembler
+// usable in product mode.
+#if defined(FORCE_INCLUDE_DISASSEMBLER)
+#define DISASSEMBLE_FLAGS(P, R, C, D) \
+ P(disassemble, bool, false, "Disassemble dart code.") \
+ P(disassemble_optimized, bool, false, "Disassemble optimized code.") \
+ P(disassemble_relative, bool, false, "Use offsets instead of absolute PCs") \
+ P(support_disassembler, bool, true, "Support the disassembler.")
+#else
+#define DISASSEMBLE_FLAGS(P, R, C, D) \
+ R(disassemble, false, bool, false, "Disassemble dart code.") \
+ R(disassemble_optimized, false, bool, false, "Disassemble optimized code.") \
+ R(disassemble_relative, false, bool, false, \
+ "Use offsets instead of absolute PCs") \
+ R(support_disassembler, false, bool, true, "Support the disassembler.")
+#endif
+
// List of all flags in the VM.
-// Flags can be one of three categories:
+// Flags can be one of four categories:
// * P roduct flags: Can be set in any of the deployment modes, including in
// production.
// * R elease flags: Generally available flags except when building product.
-// * D ebug flags: Can only be set in debug VMs, which also have C++ assertions
-// enabled.
// * pre C ompile flags: Generally available flags except when building product
// or precompiled runtime.
+// * D ebug flags: Can only be set in debug VMs, which also have C++ assertions
+// enabled.
//
// Usage:
// P(name, type, default_value, comment)
// R(name, product_value, type, default_value, comment)
-// D(name, type, default_value, comment)
// C(name, precompiled_value, product_value, type, default_value, comment)
-#define FLAG_LIST(P, R, D, C) \
+// D(name, type, default_value, comment)
+#define FLAG_LIST(P, R, C, D) \
P(experimental_unsafe_mode_use_at_your_own_risk, bool, false, \
"Omit runtime strong mode type checks and disable optimizations based on " \
"types.") \
@@ -67,10 +85,9 @@
C(deoptimize_every, 0, 0, int, 0, \
"Deoptimize on every N stack overflow checks") \
R(disable_alloc_stubs_after_gc, false, bool, false, "Stress testing flag.") \
- R(disassemble, false, bool, false, "Disassemble dart code.") \
- R(disassemble_optimized, false, bool, false, "Disassemble optimized code.") \
- R(disassemble_relative, false, bool, false, \
- "Use offsets instead of absolute PCs") \
+ DISASSEMBLE_FLAGS(P, R, C, D) \
+ R(code_comments, false, bool, false, \
+ "Include comments into code and disassembly.") \
R(dump_megamorphic_stats, false, bool, false, \
"Dump megamorphic cache statistics") \
R(dump_symbol_stats, false, bool, false, "Dump symbol table statistics") \
@@ -148,12 +165,15 @@
P(reorder_basic_blocks, bool, true, "Reorder basic blocks") \
C(stress_async_stacks, false, false, bool, false, \
"Stress test async stack traces") \
+ P(strong_non_nullable_type_checks, bool, false, \
+ "Enable strong non-nullable type checking mode.") \
P(use_bare_instructions, bool, true, "Enable bare instructions mode.") \
+ P(enable_isolate_groups, bool, kDartPrecompiledRuntime, \
+ "Enable isolate group support.") \
P(show_invisible_frames, bool, false, \
"Show invisible frames in stack traces.") \
R(show_invisible_isolates, false, bool, false, \
"Show invisible isolates in the vm-service.") \
- R(support_disassembler, false, bool, true, "Support the disassembler.") \
R(support_il_printer, false, bool, true, "Support the IL printer.") \
C(support_reload, false, false, bool, true, "Support isolate reload.") \
R(support_service, false, bool, true, "Support the service protocol.") \
@@ -217,7 +237,7 @@
// same as during runtime.
//
// Usage:
-// P(name, command-line-flag-name)
+// V(name, command-line-flag-name)
#define VM_GLOBAL_FLAG_LIST(V) \
V(use_bare_instructions, FLAG_use_bare_instructions)
diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc
index 3cd3422..672cd68 100644
--- a/runtime/vm/flags.cc
+++ b/runtime/vm/flags.cc
@@ -16,60 +16,60 @@
false,
"Ignore unrecognized flags.");
-#define PRODUCT_FLAG_MARCO(name, type, default_value, comment) \
+#define PRODUCT_FLAG_MACRO(name, type, default_value, comment) \
type FLAG_##name = \
Flags::Register_##type(&FLAG_##name, #name, default_value, comment);
#if defined(DEBUG)
-#define DEBUG_FLAG_MARCO(name, type, default_value, comment) \
+#define DEBUG_FLAG_MACRO(name, type, default_value, comment) \
type FLAG_##name = \
Flags::Register_##type(&FLAG_##name, #name, default_value, comment);
#else // defined(DEBUG)
-#define DEBUG_FLAG_MARCO(name, type, default_value, comment)
+#define DEBUG_FLAG_MACRO(name, type, default_value, comment)
#endif // defined(DEBUG)
#if defined(PRODUCT) && defined(DART_PRECOMPILED_RUNTIME)
// Nothing to be done for the product flag definitions.
-#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment)
+#define RELEASE_FLAG_MACRO(name, product_value, type, default_value, comment)
// Nothing to be done for the precompilation flag definitions.
-#define PRECOMPILE_FLAG_MARCO(name, pre_value, product_value, type, \
+#define PRECOMPILE_FLAG_MACRO(name, pre_value, product_value, type, \
default_value, comment)
#elif defined(PRODUCT) // !PRECOMPILED
// Nothing to be done for the product flag definitions.
-#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment)
+#define RELEASE_FLAG_MACRO(name, product_value, type, default_value, comment)
// Nothing to be done for the precompilation flag definitions.
-#define PRECOMPILE_FLAG_MARCO(name, pre_value, product_value, type, \
+#define PRECOMPILE_FLAG_MACRO(name, pre_value, product_value, type, \
default_value, comment)
#elif defined(DART_PRECOMPILED_RUNTIME) // !PRODUCT
-#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
+#define RELEASE_FLAG_MACRO(name, product_value, type, default_value, comment) \
type FLAG_##name = \
Flags::Register_##type(&FLAG_##name, #name, default_value, comment);
// Nothing to be done for the precompilation flag definitions.
-#define PRECOMPILE_FLAG_MARCO(name, pre_value, product_value, type, \
+#define PRECOMPILE_FLAG_MACRO(name, pre_value, product_value, type, \
default_value, comment)
#else // !PRODUCT && !PRECOMPILED
-#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
+#define RELEASE_FLAG_MACRO(name, product_value, type, default_value, comment) \
type FLAG_##name = \
Flags::Register_##type(&FLAG_##name, #name, default_value, comment);
-#define PRECOMPILE_FLAG_MARCO(name, pre_value, product_value, type, \
+#define PRECOMPILE_FLAG_MACRO(name, pre_value, product_value, type, \
default_value, comment) \
type FLAG_##name = \
Flags::Register_##type(&FLAG_##name, #name, default_value, comment);
#endif
// Define all of the non-product flags here.
-FLAG_LIST(PRODUCT_FLAG_MARCO,
- RELEASE_FLAG_MARCO,
- DEBUG_FLAG_MARCO,
- PRECOMPILE_FLAG_MARCO)
+FLAG_LIST(PRODUCT_FLAG_MACRO,
+ RELEASE_FLAG_MACRO,
+ PRECOMPILE_FLAG_MACRO,
+ DEBUG_FLAG_MACRO)
-#undef RELEASE_FLAG_MARCO
-#undef DEBUG_FLAG_MARCO
-#undef PRODUCT_FLAG_MARCO
-#undef PRECOMPILE_FLAG_MARCO
+#undef PRODUCT_FLAG_MACRO
+#undef RELEASE_FLAG_MACRO
+#undef PRECOMPILE_FLAG_MACRO
+#undef DEBUG_FLAG_MACRO
bool Flags::initialized_ = false;
diff --git a/runtime/vm/flags.h b/runtime/vm/flags.h
index d230f5d..790e277 100644
--- a/runtime/vm/flags.h
+++ b/runtime/vm/flags.h
@@ -107,57 +107,57 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(Flags);
};
-#define PRODUCT_FLAG_MARCO(name, type, default_value, comment) \
+#define PRODUCT_FLAG_MACRO(name, type, default_value, comment) \
extern type FLAG_##name;
#if defined(DEBUG)
-#define DEBUG_FLAG_MARCO(name, type, default_value, comment) \
+#define DEBUG_FLAG_MACRO(name, type, default_value, comment) \
extern type FLAG_##name;
#else // defined(DEBUG)
-#define DEBUG_FLAG_MARCO(name, type, default_value, comment) \
+#define DEBUG_FLAG_MACRO(name, type, default_value, comment) \
const type FLAG_##name = default_value;
#endif // defined(DEBUG)
#if defined(PRODUCT) && defined(DART_PRECOMPILED_RUNTIME)
-#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
+#define RELEASE_FLAG_MACRO(name, product_value, type, default_value, comment) \
const type FLAG_##name = product_value;
-#define PRECOMPILE_FLAG_MARCO(name, precompiled_value, product_value, type, \
+#define PRECOMPILE_FLAG_MACRO(name, precompiled_value, product_value, type, \
default_value, comment) \
const type FLAG_##name = precompiled_value;
#elif defined(PRODUCT) // !PRECOMPILED
-#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
+#define RELEASE_FLAG_MACRO(name, product_value, type, default_value, comment) \
const type FLAG_##name = product_value;
-#define PRECOMPILE_FLAG_MARCO(name, precompiled_value, product_value, type, \
+#define PRECOMPILE_FLAG_MACRO(name, precompiled_value, product_value, type, \
default_value, comment) \
const type FLAG_##name = product_value;
#elif defined(DART_PRECOMPILED_RUNTIME) // !PRODUCT
-#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
+#define RELEASE_FLAG_MACRO(name, product_value, type, default_value, comment) \
extern type FLAG_##name;
-#define PRECOMPILE_FLAG_MARCO(name, precompiled_value, product_value, type, \
+#define PRECOMPILE_FLAG_MACRO(name, precompiled_value, product_value, type, \
default_value, comment) \
const type FLAG_##name = precompiled_value;
#else // !PRODUCT && !PRECOMPILED
-#define RELEASE_FLAG_MARCO(name, product_value, type, default_value, comment) \
+#define RELEASE_FLAG_MACRO(name, product_value, type, default_value, comment) \
extern type FLAG_##name;
-#define PRECOMPILE_FLAG_MARCO(name, precompiled_value, product_value, type, \
+#define PRECOMPILE_FLAG_MACRO(name, precompiled_value, product_value, type, \
default_value, comment) \
extern type FLAG_##name;
#endif
// Now declare all flags here.
-FLAG_LIST(PRODUCT_FLAG_MARCO,
- RELEASE_FLAG_MARCO,
- DEBUG_FLAG_MARCO,
- PRECOMPILE_FLAG_MARCO)
+FLAG_LIST(PRODUCT_FLAG_MACRO,
+ RELEASE_FLAG_MACRO,
+ PRECOMPILE_FLAG_MACRO,
+ DEBUG_FLAG_MACRO)
-#undef RELEASE_FLAG_MARCO
-#undef DEBUG_FLAG_MARCO
-#undef PRODUCT_FLAG_MARCO
-#undef PRECOMPILE_FLAG_MARCO
+#undef RELEASE_FLAG_MACRO
+#undef DEBUG_FLAG_MACRO
+#undef PRODUCT_FLAG_MACRO
+#undef PRECOMPILE_FLAG_MACRO
} // namespace dart
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 33487fb..26a8a5e 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -429,9 +429,19 @@
if (old_space_.ShouldPerformIdleMarkCompact(deadline)) {
TIMELINE_FUNCTION_GC_DURATION(thread, "IdleGC");
CollectOldSpaceGarbage(thread, kMarkCompact, kIdle);
- } else if (old_space_.ShouldPerformIdleMarkSweep(deadline)) {
- TIMELINE_FUNCTION_GC_DURATION(thread, "IdleGC");
- CollectOldSpaceGarbage(thread, kMarkSweep, kIdle);
+ } else if (old_space_.ShouldStartIdleMarkSweep(deadline)) {
+ PageSpace::Phase phase;
+ {
+ MonitorLocker ml(old_space_.tasks_lock());
+ phase = old_space_.phase();
+ }
+ if (phase == PageSpace::kAwaitingFinalization) {
+ TIMELINE_FUNCTION_GC_DURATION(thread, "IdleGC");
+ CollectOldSpaceGarbage(thread, Heap::kMarkSweep, Heap::kFinalize);
+ } else if (phase == PageSpace::kDone) {
+ TIMELINE_FUNCTION_GC_DURATION(thread, "IdleGC");
+ StartConcurrentMarking(thread);
+ }
} else if (old_space_.NeedsGarbageCollection()) {
// Even though the following GC may exceed our idle deadline, we need to
// ensure than that promotions during idle scavenges do not lead to
@@ -446,7 +456,7 @@
}
void Heap::NotifyLowMemory() {
- CollectAllGarbage(kLowMemory);
+ CollectMostGarbage(kLowMemory);
}
void Heap::EvacuateNewSpace(Thread* thread, GCReason reason) {
@@ -561,7 +571,8 @@
void Heap::CollectMostGarbage(GCReason reason) {
Thread* thread = Thread::Current();
CollectNewSpaceGarbage(thread, reason);
- CollectOldSpaceGarbage(thread, kMarkSweep, reason);
+ CollectOldSpaceGarbage(
+ thread, reason == kLowMemory ? kMarkCompact : kMarkSweep, reason);
}
void Heap::CollectAllGarbage(GCReason reason) {
@@ -570,8 +581,15 @@
// New space is evacuated so this GC will collect all dead objects
// kept alive by a cross-generational pointer.
EvacuateNewSpace(thread, reason);
+ if (thread->is_marking()) {
+ // If incremental marking is happening, we need to finish the GC cycle
+ // and perform a follow-up GC to pruge any "floating garbage" that may be
+ // retained by the incremental barrier.
+ CollectOldSpaceGarbage(thread, kMarkSweep, reason);
+ }
CollectOldSpaceGarbage(
thread, reason == kLowMemory ? kMarkCompact : kMarkSweep, reason);
+ WaitForSweeperTasks(thread);
}
void Heap::CheckStartConcurrentMarking(Thread* thread, GCReason reason) {
@@ -583,11 +601,15 @@
}
if (old_space_.AlmostNeedsGarbageCollection()) {
- if (BeginOldSpaceGC(thread)) {
- TIMELINE_FUNCTION_GC_DURATION_BASIC(thread, "StartConcurrentMarking");
- old_space_.CollectGarbage(/*compact=*/false, /*finalize=*/false);
- EndOldSpaceGC();
- }
+ StartConcurrentMarking(thread);
+ }
+}
+
+void Heap::StartConcurrentMarking(Thread* thread) {
+ if (BeginOldSpaceGC(thread)) {
+ TIMELINE_FUNCTION_GC_DURATION_BASIC(thread, "StartConcurrentMarking");
+ old_space_.CollectGarbage(/*compact=*/false, /*finalize=*/false);
+ EndOldSpaceGC();
}
}
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 7414467..bedad67 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -133,7 +133,9 @@
void CollectMostGarbage(GCReason reason = kFull);
// Collect both generations by performing an evacuation followed by a
- // mark-sweep. This function will collect all unreachable objects.
+ // mark-sweep. If incremental marking was in progress, perform another
+ // mark-sweep. This function will collect all unreachable objects, including
+ // those in inter-generational cycles or stored during incremental marking.
void CollectAllGarbage(GCReason reason = kFull);
bool NeedsGarbageCollection() const {
@@ -141,6 +143,7 @@
}
void CheckStartConcurrentMarking(Thread* thread, GCReason reason);
+ void StartConcurrentMarking(Thread* thread);
void CheckFinishConcurrentMarking(Thread* thread);
void WaitForMarkerTasks(Thread* thread);
void WaitForSweeperTasks(Thread* thread);
@@ -506,6 +509,47 @@
DISALLOW_COPY_AND_ASSIGN(BumpAllocateScope);
};
+#if defined(TESTING)
+class GCTestHelper : public AllStatic {
+ public:
+ // Collect new gen without triggering any side effects. The normal call to
+ // CollectGarbage(Heap::kNew) could potentially trigger an old gen collection
+ // if there is enough promotion, and this can perturb some tests.
+ static void CollectNewSpace() {
+ Thread* thread = Thread::Current();
+ ASSERT(thread->execution_state() == Thread::kThreadInVM);
+ thread->heap()->new_space()->Scavenge();
+ }
+
+ // Fully collect old gen and wait for the sweeper to finish. The normal call
+ // to CollectGarbage(Heap::kOld) may leave so-called "floating garbage",
+ // objects that were seen by the incremental barrier but later made
+ // unreachable, and this can perturb some tests.
+ static void CollectOldSpace() {
+ Thread* thread = Thread::Current();
+ ASSERT(thread->execution_state() == Thread::kThreadInVM);
+ if (thread->is_marking()) {
+ thread->heap()->CollectGarbage(Heap::kMarkSweep, Heap::kDebugging);
+ }
+ thread->heap()->CollectGarbage(Heap::kMarkSweep, Heap::kDebugging);
+ WaitForGCTasks();
+ }
+
+ static void CollectAllGarbage() {
+ Thread* thread = Thread::Current();
+ ASSERT(thread->execution_state() == Thread::kThreadInVM);
+ thread->heap()->CollectAllGarbage(Heap::kDebugging);
+ }
+
+ static void WaitForGCTasks() {
+ Thread* thread = Thread::Current();
+ ASSERT(thread->execution_state() == Thread::kThreadInVM);
+ thread->heap()->WaitForMarkerTasks(thread);
+ thread->heap()->WaitForSweeperTasks(thread);
+ }
+};
+#endif // TESTING
+
} // namespace dart
#endif // RUNTIME_VM_HEAP_HEAP_H_
diff --git a/runtime/vm/heap/heap_test.cc b/runtime/vm/heap/heap_test.cc
index 6ffad95..0bbe2fa 100644
--- a/runtime/vm/heap/heap_test.cc
+++ b/runtime/vm/heap/heap_test.cc
@@ -9,6 +9,7 @@
#include "vm/globals.h"
#include "vm/heap/become.h"
#include "vm/heap/heap.h"
+#include "vm/object_graph.h"
#include "vm/symbols.h"
#include "vm/unit_test.h"
@@ -27,14 +28,19 @@
EXPECT(!Dart_IsNull(result));
EXPECT(Dart_IsList(result));
TransitionNativeToVM transition(thread);
- Isolate* isolate = Isolate::Current();
- Heap* heap = isolate->heap();
- heap->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
}
#if !defined(PRODUCT)
TEST_CASE(OldGC_Unsync) {
+ // Finalize any GC in progress as it is unsafe to change FLAG_marker_tasks
+ // when incremental marking is in progress.
+ {
+ TransitionNativeToVM transition(thread);
+ GCTestHelper::CollectAllGarbage();
+ }
FLAG_marker_tasks = 0;
+
const char* kScriptChars =
"main() {\n"
" return [1, 2, 3];\n"
@@ -47,9 +53,7 @@
EXPECT(!Dart_IsNull(result));
EXPECT(Dart_IsList(result));
TransitionNativeToVM transition(thread);
- Isolate* isolate = Isolate::Current();
- Heap* heap = isolate->heap();
- heap->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
}
#endif // !defined(PRODUCT)
@@ -68,31 +72,16 @@
EXPECT(Dart_IsList(result));
{
TransitionNativeToVM transition(thread);
- thread->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
}
Dart_ExitScope();
{
TransitionNativeToVM transition(thread);
- thread->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
}
}
#ifndef PRODUCT
-class ClassHeapStatsTestHelper {
- public:
- static ClassHeapStats* GetHeapStatsForCid(ClassTable* class_table,
- intptr_t cid) {
- return class_table->shared_class_table()->PreliminaryStatsAt(cid);
- }
-
- static void DumpClassHeapStats(ClassHeapStats* stats) {
- OS::PrintErr("%" Pd " ", stats->recent.new_count.load());
- OS::PrintErr("%" Pd " ", stats->post_gc.new_count.load());
- OS::PrintErr("%" Pd " ", stats->pre_gc.new_count.load());
- OS::PrintErr("\n");
- }
-};
-
static RawClass* GetClass(const Library& lib, const char* name) {
const Class& cls = Class::Handle(
lib.LookupClass(String::Handle(Symbols::New(Thread::Current(), name))));
@@ -111,17 +100,14 @@
" var x = new A();\n"
" return new A();\n"
"}\n";
- bool saved_concurrent_sweep_mode = FLAG_concurrent_sweep;
- FLAG_concurrent_sweep = false;
Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars, NULL);
Isolate* isolate = Isolate::Current();
ClassTable* class_table = isolate->class_table();
- Heap* heap = isolate->heap();
Dart_EnterScope();
Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
EXPECT_VALID(result);
EXPECT(!Dart_IsNull(result));
- ClassHeapStats* class_stats;
+ intptr_t cid;
{
TransitionNativeToVM transition(thread);
Library& lib = Library::Handle();
@@ -129,112 +115,86 @@
EXPECT(!lib.IsNull());
const Class& cls = Class::Handle(GetClass(lib, "A"));
ASSERT(!cls.IsNull());
- intptr_t cid = cls.id();
- class_stats =
- ClassHeapStatsTestHelper::GetHeapStatsForCid(class_table, cid);
- // Verify preconditions:
- EXPECT_EQ(0, class_stats->pre_gc.old_count);
- EXPECT_EQ(0, class_stats->post_gc.old_count);
- EXPECT_EQ(0, class_stats->recent.old_count);
- EXPECT_EQ(0, class_stats->pre_gc.new_count);
- EXPECT_EQ(0, class_stats->post_gc.new_count);
- // Class allocated twice since GC from new space.
- EXPECT_EQ(2, class_stats->recent.new_count);
+ cid = cls.id();
+
+ {
+ // Verify preconditions: allocated twice in new space.
+ CountObjectsVisitor visitor(thread, class_table->NumCids());
+ HeapIterationScope iter(thread);
+ iter.IterateObjects(&visitor);
+ isolate->VisitWeakPersistentHandles(&visitor);
+ EXPECT_EQ(2, visitor.new_count_[cid]);
+ EXPECT_EQ(0, visitor.old_count_[cid]);
+ }
+
// Perform GC.
- heap->CollectGarbage(Heap::kNew);
- // Verify postconditions:
- EXPECT_EQ(0, class_stats->pre_gc.old_count);
- EXPECT_EQ(0, class_stats->post_gc.old_count);
- EXPECT_EQ(0, class_stats->recent.old_count);
- // Total allocations before GC.
- EXPECT_EQ(2, class_stats->pre_gc.new_count);
- // Only one survived.
- EXPECT_EQ(1, class_stats->post_gc.new_count);
- EXPECT_EQ(0, class_stats->recent.new_count);
+ GCTestHelper::CollectNewSpace();
+
+ {
+ // Verify postconditions: Only one survived.
+ CountObjectsVisitor visitor(thread, class_table->NumCids());
+ HeapIterationScope iter(thread);
+ iter.IterateObjects(&visitor);
+ isolate->VisitWeakPersistentHandles(&visitor);
+ EXPECT_EQ(1, visitor.new_count_[cid]);
+ EXPECT_EQ(0, visitor.old_count_[cid]);
+ }
+
// Perform GC. The following is heavily dependent on the behaviour
// of the GC: Retained instance of A will be promoted.
- heap->CollectGarbage(Heap::kNew);
- // Verify postconditions:
- EXPECT_EQ(0, class_stats->pre_gc.old_count);
- EXPECT_EQ(0, class_stats->post_gc.old_count);
- // One promoted instance.
- EXPECT_EQ(1, class_stats->promoted_count);
- // Promotion counted as an allocation from old space.
- EXPECT_EQ(1, class_stats->recent.old_count);
- // There was one instance allocated before GC.
- EXPECT_EQ(1, class_stats->pre_gc.new_count);
- // There are no instances allocated in new space after GC.
- EXPECT_EQ(0, class_stats->post_gc.new_count);
- // No new allocations.
- EXPECT_EQ(0, class_stats->recent.new_count);
+ GCTestHelper::CollectNewSpace();
+
+ {
+ // Verify postconditions: One promoted instance.
+ CountObjectsVisitor visitor(thread, class_table->NumCids());
+ HeapIterationScope iter(thread);
+ iter.IterateObjects(&visitor);
+ isolate->VisitWeakPersistentHandles(&visitor);
+ EXPECT_EQ(0, visitor.new_count_[cid]);
+ EXPECT_EQ(1, visitor.old_count_[cid]);
+ }
+
// Perform a GC on new space.
- heap->CollectGarbage(Heap::kNew);
- // There were no instances allocated before GC.
- EXPECT_EQ(0, class_stats->pre_gc.new_count);
- // There are no instances allocated in new space after GC.
- EXPECT_EQ(0, class_stats->post_gc.new_count);
- // No new allocations.
- EXPECT_EQ(0, class_stats->recent.new_count);
- // Nothing was promoted.
- EXPECT_EQ(0, class_stats->promoted_count);
- heap->CollectGarbage(Heap::kOld);
- // Verify postconditions:
- EXPECT_EQ(1, class_stats->pre_gc.old_count);
- EXPECT_EQ(1, class_stats->post_gc.old_count);
- EXPECT_EQ(0, class_stats->recent.old_count);
+ GCTestHelper::CollectNewSpace();
+
+ {
+ // Verify postconditions:
+ CountObjectsVisitor visitor(thread, class_table->NumCids());
+ HeapIterationScope iter(thread);
+ iter.IterateObjects(&visitor);
+ isolate->VisitWeakPersistentHandles(&visitor);
+ EXPECT_EQ(0, visitor.new_count_[cid]);
+ EXPECT_EQ(1, visitor.old_count_[cid]);
+ }
+
+ GCTestHelper::CollectOldSpace();
+
+ {
+ // Verify postconditions:
+ CountObjectsVisitor visitor(thread, class_table->NumCids());
+ HeapIterationScope iter(thread);
+ iter.IterateObjects(&visitor);
+ isolate->VisitWeakPersistentHandles(&visitor);
+ EXPECT_EQ(0, visitor.new_count_[cid]);
+ EXPECT_EQ(1, visitor.old_count_[cid]);
+ }
}
// Exit scope, freeing instance.
Dart_ExitScope();
{
TransitionNativeToVM transition(thread);
// Perform GC.
- heap->CollectGarbage(Heap::kOld);
- // Verify postconditions:
- EXPECT_EQ(1, class_stats->pre_gc.old_count);
- EXPECT_EQ(0, class_stats->post_gc.old_count);
- EXPECT_EQ(0, class_stats->recent.old_count);
- // Perform GC.
- heap->CollectGarbage(Heap::kOld);
- EXPECT_EQ(0, class_stats->pre_gc.old_count);
- EXPECT_EQ(0, class_stats->post_gc.old_count);
- EXPECT_EQ(0, class_stats->recent.old_count);
+ GCTestHelper::CollectOldSpace();
+ {
+ // Verify postconditions:
+ CountObjectsVisitor visitor(thread, class_table->NumCids());
+ HeapIterationScope iter(thread);
+ iter.IterateObjects(&visitor);
+ isolate->VisitWeakPersistentHandles(&visitor);
+ EXPECT_EQ(0, visitor.new_count_[cid]);
+ EXPECT_EQ(0, visitor.old_count_[cid]);
+ }
}
- FLAG_concurrent_sweep = saved_concurrent_sweep_mode;
-}
-
-TEST_CASE(ArrayHeapStats) {
- const char* kScriptChars =
- "List f(int len) {\n"
- " return new List(len);\n"
- "}\n"
- ""
- "main() {\n"
- " return f(1234);\n"
- "}\n";
- Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars, NULL);
- Isolate* isolate = Isolate::Current();
- ClassTable* class_table = isolate->class_table();
- intptr_t cid = kArrayCid;
- ClassHeapStats* class_stats =
- ClassHeapStatsTestHelper::GetHeapStatsForCid(class_table, cid);
- Dart_EnterScope();
- // Invoke 'main' twice, since initial compilation might trigger extra array
- // allocations.
- Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
- EXPECT_VALID(result);
- EXPECT(!Dart_IsNull(result));
- intptr_t before = class_stats->recent.new_size;
- Dart_Handle result2 = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
- EXPECT_VALID(result2);
- EXPECT(!Dart_IsNull(result2));
- intptr_t after = class_stats->recent.new_size;
- const intptr_t expected_size = Array::InstanceSize(1234);
- // Invoking the method might involve some additional tiny array allocations,
- // so we allow slightly more than expected.
- static const intptr_t kTolerance = 10 * kWordSize;
- EXPECT_LE(expected_size, after - before);
- EXPECT_GT(expected_size + kTolerance, after - before);
- Dart_ExitScope();
}
#endif // !PRODUCT
@@ -283,6 +243,11 @@
ISOLATE_UNIT_TEST_CASE(IterateReadOnly) {
const String& obj = String::Handle(String::New("x", Heap::kOld));
+
+ // It is not safe to make the heap read-only if marking or sweeping is in
+ // progress.
+ GCTestHelper::WaitForGCTasks();
+
Heap* heap = Thread::Current()->isolate()->heap();
EXPECT(heap->Contains(RawObject::ToAddr(obj.raw())));
heap->WriteProtect(true);
@@ -292,9 +257,6 @@
}
void TestBecomeForward(Heap::Space before_space, Heap::Space after_space) {
- Isolate* isolate = Isolate::Current();
- Heap* heap = isolate->heap();
-
const String& before_obj = String::Handle(String::New("old", before_space));
const String& after_obj = String::Handle(String::New("new", after_space));
@@ -310,7 +272,7 @@
EXPECT(before_obj.raw() == after_obj.raw());
- heap->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(before_obj.raw() == after_obj.raw());
}
@@ -357,9 +319,6 @@
}
ISOLATE_UNIT_TEST_CASE(BecomeForwardRememberedObject) {
- Isolate* isolate = Isolate::Current();
- Heap* heap = isolate->heap();
-
const String& new_element = String::Handle(String::New("new", Heap::kNew));
const String& old_element = String::Handle(String::New("old", Heap::kOld));
const Array& before_obj = Array::Handle(Array::New(1, Heap::kOld));
@@ -381,7 +340,7 @@
EXPECT(before_obj.raw() == after_obj.raw());
EXPECT(!after_obj.raw()->IsRemembered());
- heap->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(before_obj.raw() == after_obj.raw());
}
@@ -395,18 +354,11 @@
intptr_t size_before =
heap->new_space()->UsedInWords() + heap->old_space()->UsedInWords();
- {
- // Prevent allocation from starting marking, otherwise the incremental write
- // barrier will keep these objects live.
- NoHeapGrowthControlScope force_growth;
- EXPECT(!thread->is_marking());
- Array& old = Array::Handle(Array::New(1, Heap::kOld));
- Array& neu = Array::Handle(Array::New(1, Heap::kNew));
- old.SetAt(0, neu);
- old = Array::null();
- neu = Array::null();
- EXPECT(!thread->is_marking());
- }
+ Array& old = Array::Handle(Array::New(1, Heap::kOld));
+ Array& neu = Array::Handle(Array::New(1, Heap::kNew));
+ old.SetAt(0, neu);
+ old = Array::null();
+ neu = Array::null();
heap->CollectAllGarbage();
heap->WaitForMarkerTasks(thread); // Finalize marking to get live size.
@@ -426,18 +378,11 @@
intptr_t size_before =
heap->new_space()->UsedInWords() + heap->old_space()->UsedInWords();
- {
- // Prevent allocation from starting marking, otherwise the incremental write
- // barrier will keep these objects live.
- NoHeapGrowthControlScope force_growth;
- EXPECT(!thread->is_marking());
- Array& old = Array::Handle(Array::New(1, Heap::kOld));
- Array& neu = Array::Handle(Array::New(1, Heap::kNew));
- neu.SetAt(0, old);
- old = Array::null();
- neu = Array::null();
- EXPECT(!thread->is_marking());
- }
+ Array& old = Array::Handle(Array::New(1, Heap::kOld));
+ Array& neu = Array::Handle(Array::New(1, Heap::kNew));
+ neu.SetAt(0, old);
+ old = Array::null();
+ neu = Array::null();
heap->CollectAllGarbage();
heap->WaitForMarkerTasks(thread); // Finalize marking to get live size.
@@ -457,19 +402,12 @@
intptr_t size_before =
heap->new_space()->UsedInWords() + heap->old_space()->UsedInWords();
- {
- // Prevent allocation from starting marking, otherwise the incremental write
- // barrier will keep these objects live.
- NoHeapGrowthControlScope force_growth;
- EXPECT(!thread->is_marking());
- Array& old = Array::Handle(Array::New(1, Heap::kOld));
- Array& neu = Array::Handle(Array::New(1, Heap::kNew));
- neu.SetAt(0, old);
- old.SetAt(0, neu);
- old = Array::null();
- neu = Array::null();
- EXPECT(!thread->is_marking());
- }
+ Array& old = Array::Handle(Array::New(1, Heap::kOld));
+ Array& neu = Array::Handle(Array::New(1, Heap::kNew));
+ neu.SetAt(0, old);
+ old.SetAt(0, neu);
+ old = Array::null();
+ neu = Array::null();
heap->CollectAllGarbage();
heap->WaitForMarkerTasks(thread); // Finalize marking to get live size.
@@ -489,17 +427,10 @@
intptr_t size_before =
heap->new_space()->UsedInWords() + heap->old_space()->UsedInWords();
- {
- // Prevent allocation from starting marking, otherwise the incremental write
- // barrier will keep these objects live.
- NoHeapGrowthControlScope force_growth;
- EXPECT(!thread->is_marking());
- Array& old = Array::Handle(Array::New(1, Heap::kOld));
- Array& neu = Array::Handle(Array::New(1, Heap::kNew));
- neu.SetAt(0, old);
- old = Array::null();
- EXPECT(!thread->is_marking());
- }
+ Array& old = Array::Handle(Array::New(1, Heap::kOld));
+ Array& neu = Array::Handle(Array::New(1, Heap::kNew));
+ neu.SetAt(0, old);
+ old = Array::null();
heap->CollectAllGarbage();
heap->WaitForMarkerTasks(thread); // Finalize marking to get live size.
@@ -519,17 +450,10 @@
intptr_t size_before =
heap->new_space()->UsedInWords() + heap->old_space()->UsedInWords();
- {
- // Prevent allocation from starting marking, otherwise the incremental write
- // barrier will keep these objects live.
- NoHeapGrowthControlScope force_growth;
- EXPECT(!thread->is_marking());
- Array& old = Array::Handle(Array::New(1, Heap::kOld));
- Array& neu = Array::Handle(Array::New(1, Heap::kNew));
- old.SetAt(0, neu);
- neu = Array::null();
- EXPECT(!thread->is_marking());
- }
+ Array& old = Array::Handle(Array::New(1, Heap::kOld));
+ Array& neu = Array::Handle(Array::New(1, Heap::kNew));
+ old.SetAt(0, neu);
+ neu = Array::null();
heap->CollectAllGarbage();
heap->WaitForMarkerTasks(thread); // Finalize marking to get live size.
@@ -549,17 +473,10 @@
intptr_t size_before =
heap->new_space()->UsedInWords() + heap->old_space()->UsedInWords();
- {
- // Prevent allocation from starting marking, otherwise the incremental write
- // barrier will keep these objects live.
- NoHeapGrowthControlScope force_growth;
- EXPECT(!thread->is_marking());
- Array& old = Array::Handle(Array::New(1, Heap::kOld));
- Array& neu = Array::Handle(Array::New(1, Heap::kNew));
- neu = Array::null();
- old.SetAt(0, old);
- EXPECT(!thread->is_marking());
- }
+ Array& old = Array::Handle(Array::New(1, Heap::kOld));
+ Array& neu = Array::Handle(Array::New(1, Heap::kNew));
+ neu = Array::null();
+ old.SetAt(0, old);
heap->CollectAllGarbage();
heap->WaitForMarkerTasks(thread); // Finalize marking to get live size.
@@ -579,17 +496,10 @@
intptr_t size_before =
heap->new_space()->UsedInWords() + heap->old_space()->UsedInWords();
- {
- // Prevent allocation from starting marking, otherwise the incremental write
- // barrier will keep these objects live.
- NoHeapGrowthControlScope force_growth;
- EXPECT(!thread->is_marking());
- Array& old = Array::Handle(Array::New(1, Heap::kOld));
- Array& neu = Array::Handle(Array::New(1, Heap::kNew));
- old = Array::null();
- neu.SetAt(0, neu);
- EXPECT(!thread->is_marking());
- }
+ Array& old = Array::Handle(Array::New(1, Heap::kOld));
+ Array& neu = Array::Handle(Array::New(1, Heap::kNew));
+ old = Array::null();
+ neu.SetAt(0, neu);
heap->CollectAllGarbage();
heap->WaitForMarkerTasks(thread); // Finalize marking to get live size.
@@ -608,20 +518,13 @@
intptr_t size_before =
heap->new_space()->UsedInWords() + heap->old_space()->UsedInWords();
- {
- // Prevent allocation from starting marking, otherwise the incremental write
- // barrier will keep these objects live.
- NoHeapGrowthControlScope force_growth;
- EXPECT(!thread->is_marking());
- Array& old = Array::Handle(Array::New(1, Heap::kOld));
- Array& old2 = Array::Handle(Array::New(1, Heap::kOld));
- Array& neu = Array::Handle(Array::New(1, Heap::kNew));
- old.SetAt(0, old2);
- neu.SetAt(0, old);
- old = Array::null();
- old2 = Array::null();
- EXPECT(!thread->is_marking());
- }
+ Array& old = Array::Handle(Array::New(1, Heap::kOld));
+ Array& old2 = Array::Handle(Array::New(1, Heap::kOld));
+ Array& neu = Array::Handle(Array::New(1, Heap::kNew));
+ old.SetAt(0, old2);
+ neu.SetAt(0, old);
+ old = Array::null();
+ old2 = Array::null();
heap->CollectAllGarbage();
@@ -639,20 +542,13 @@
intptr_t size_before =
heap->new_space()->UsedInWords() + heap->old_space()->UsedInWords();
- {
- // Prevent allocation from starting marking, otherwise the incremental write
- // barrier will keep these objects live.
- NoHeapGrowthControlScope force_growth;
- EXPECT(!thread->is_marking());
- Array& old = Array::Handle(Array::New(1, Heap::kOld));
- Array& neu = Array::Handle(Array::New(1, Heap::kNew));
- Array& neu2 = Array::Handle(Array::New(1, Heap::kOld));
- neu.SetAt(0, neu2);
- old.SetAt(0, neu);
- neu = Array::null();
- neu2 = Array::null();
- EXPECT(!thread->is_marking());
- }
+ Array& old = Array::Handle(Array::New(1, Heap::kOld));
+ Array& neu = Array::Handle(Array::New(1, Heap::kNew));
+ Array& neu2 = Array::Handle(Array::New(1, Heap::kOld));
+ neu.SetAt(0, neu2);
+ old.SetAt(0, neu);
+ neu = Array::null();
+ neu2 = Array::null();
heap->CollectAllGarbage();
@@ -728,14 +624,14 @@
HeapTestHelper::Scavenge(thread);
}
- ClassHeapStats* stats = ClassHeapStatsTestHelper::GetHeapStatsForCid(
- isolate->class_table(), kArrayCid);
- EXPECT_LE(
- stats->post_gc.old_external_size + stats->recent.old_external_size,
- heap->old_space()->ExternalInWords() * kWordSize);
- EXPECT_LE(
- stats->post_gc.new_external_size + stats->recent.new_external_size,
- heap->new_space()->ExternalInWords() * kWordSize);
+ CountObjectsVisitor visitor(thread, isolate->class_table()->NumCids());
+ HeapIterationScope iter(thread);
+ iter.IterateObjects(&visitor);
+ isolate->VisitWeakPersistentHandles(&visitor);
+ EXPECT_LE(visitor.old_external_size_[kArrayCid],
+ heap->old_space()->ExternalInWords() * kWordSize);
+ EXPECT_LE(visitor.new_external_size_[kArrayCid],
+ heap->new_space()->ExternalInWords() * kWordSize);
}
}
#endif // !defined(PRODUCT)
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index ae2ecce..7b451bd 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -394,16 +394,6 @@
RawObject* raw_obj = handle->raw();
if (IsUnreachable(raw_obj)) {
handle->UpdateUnreachable(thread()->isolate());
- } else {
-#ifndef PRODUCT
- intptr_t cid = raw_obj->GetClassIdMayBeSmi();
- intptr_t size = handle->external_size();
- if (raw_obj->IsSmiOrOldObject()) {
- class_table_->UpdateLiveOldExternal(cid, size);
- } else {
- class_table_->UpdateLiveNewExternal(cid, size);
- }
-#endif // !PRODUCT
}
}
@@ -700,7 +690,6 @@
}
}
- isolate_->ScheduleInterrupts(Thread::kVMInterrupt);
// Exit isolate cleanly *before* notifying it, to avoid shutdown race.
Thread::ExitIsolateAsHelper(true);
// This marker task is done. Notify the original isolate.
@@ -732,18 +721,6 @@
MutexLocker ml(&stats_mutex_);
marked_bytes_ += visitor->marked_bytes();
marked_micros_ += visitor->marked_micros();
-#ifndef PRODUCT
- // Class heap stats are not themselves thread-safe yet, so we update the
- // stats while holding stats_mutex_.
- auto table = heap_->isolate()->shared_class_table();
- for (intptr_t i = 0; i < table->NumCids(); ++i) {
- const intptr_t count = visitor->live_count(i);
- if (count > 0) {
- const intptr_t size = visitor->live_size(i);
- table->UpdateLiveOld(i, size, count);
- }
- }
-#endif // !PRODUCT
}
visitor->Finalize();
}
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 60a3fd7..7047236 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -536,9 +536,6 @@
void PageSpace::AllocateExternal(intptr_t cid, intptr_t size) {
intptr_t size_in_words = size >> kWordSizeLog2;
usage_.external_in_words += size_in_words;
- NOT_IN_PRODUCT(
- heap_->isolate()->shared_class_table()->UpdateAllocatedExternalOld(cid,
- size));
}
void PageSpace::PromoteExternal(intptr_t cid, intptr_t size) {
@@ -931,7 +928,7 @@
}
}
-bool PageSpace::ShouldPerformIdleMarkSweep(int64_t deadline) {
+bool PageSpace::ShouldStartIdleMarkSweep(int64_t deadline) {
// To make a consistent decision, we should not yield for a safepoint in the
// middle of deciding whether to perform an idle GC.
NoSafepointScope no_safepoint;
@@ -950,8 +947,11 @@
}
}
+ // This uses the size of new-space because the pause time to start concurrent
+ // marking is related to the size of the root set, which is mostly new-space.
int64_t estimated_mark_completion =
- OS::GetCurrentMonotonicMicros() + UsedInWords() / mark_words_per_micro_;
+ OS::GetCurrentMonotonicMicros() +
+ heap_->new_space()->UsedInWords() / mark_words_per_micro_;
return estimated_mark_completion <= deadline;
}
@@ -1094,7 +1094,6 @@
return;
}
- NOT_IN_PRODUCT(isolate->shared_class_table()->ResetCountersOld());
marker_->MarkObjects(this);
usage_.used_in_words = marker_->marked_words() + allocated_black_in_words_;
allocated_black_in_words_ = 0;
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 92472c8..5c705f0 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -358,7 +358,7 @@
void WriteProtect(bool read_only);
void WriteProtectCode(bool read_only);
- bool ShouldPerformIdleMarkSweep(int64_t deadline);
+ bool ShouldStartIdleMarkSweep(int64_t deadline);
bool ShouldPerformIdleMarkCompact(int64_t deadline);
void AddGCTime(int64_t micros) { gc_time_micros_ += micros; }
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 9ee2adb..01a8a96 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -245,7 +245,16 @@
}
// Update the reference.
RawObject* new_obj = RawObject::FromAddr(new_addr);
- *p = new_obj;
+ if (new_obj->IsOldObject()) {
+ // Setting the mark bit above must not be ordered after a publishing store
+ // of this object. Note this could be a publishing store even if the
+ // object was promoted by an early invocation of ScavengePointer. Compare
+ // Object::Allocate.
+ reinterpret_cast<std::atomic<RawObject*>*>(p)->store(
+ new_obj, std::memory_order_release);
+ } else {
+ *p = new_obj;
+ }
// Update the store buffer as needed.
if (visiting_old_object_ != NULL) {
UpdateStoreBuffer(p, new_obj);
@@ -283,15 +292,6 @@
handle->UpdateUnreachable(thread()->isolate());
} else {
handle->UpdateRelocated(thread()->isolate());
-#ifndef PRODUCT
- intptr_t cid = (*p)->GetClassIdMayBeSmi();
- intptr_t size = handle->external_size();
- if ((*p)->IsSmiOrOldObject()) {
- class_table_->UpdateLiveOldExternal(cid, size);
- } else {
- class_table_->UpdateLiveNewExternal(cid, size);
- }
-#endif // !PRODUCT
}
}
@@ -481,8 +481,6 @@
}
SemiSpace* Scavenger::Prologue(Isolate* isolate) {
- NOT_IN_PRODUCT(isolate->shared_class_table()->ResetCountersNew());
-
isolate->ReleaseStoreBuffers();
AbandonTLABs(isolate);
@@ -587,8 +585,6 @@
if (heap_ != NULL) {
heap_->UpdateGlobalMaxUsed();
}
-
- NOT_IN_PRODUCT(isolate->shared_class_table()->UpdatePromoted());
}
bool Scavenger::ShouldPerformIdleScavenge(int64_t deadline) {
@@ -703,7 +699,6 @@
void Scavenger::ProcessToSpace(ScavengerVisitor* visitor) {
Thread* thread = Thread::Current();
- NOT_IN_PRODUCT(auto class_table = visitor->isolate()->shared_class_table());
// Iterate until all work has been drained.
while ((resolved_top_ < top_) || PromotedStackHasMore()) {
@@ -717,7 +712,6 @@
RawWeakProperty* raw_weak = reinterpret_cast<RawWeakProperty*>(raw_obj);
size = ProcessWeakProperty(raw_weak, visitor);
}
- NOT_IN_PRODUCT(class_table->UpdateLiveNewGC(class_id, size));
resolved_top_ += size;
}
{
@@ -730,12 +724,7 @@
// objects to be resolved in the to space.
ASSERT(!raw_object->IsRemembered());
visitor->VisitingOldObject(raw_object);
- intptr_t size = raw_object->VisitPointersNonvirtual(visitor);
-#if defined(PRODUCT)
- USE(size);
-#else
- class_table->UpdateAllocatedOldGC(raw_object->GetClassId(), size);
-#endif
+ raw_object->VisitPointersNonvirtual(visitor);
if (raw_object->IsMarked()) {
// Complete our promise from ScavengePointer. Note that marker cannot
// visit this object until it pops a block from the mark stack, which
@@ -1155,9 +1144,6 @@
void Scavenger::AllocateExternal(intptr_t cid, intptr_t size) {
ASSERT(size >= 0);
external_size_ += size;
- NOT_IN_PRODUCT(
- heap_->isolate()->shared_class_table()->UpdateAllocatedExternalNew(cid,
- size));
}
void Scavenger::FreeExternal(intptr_t size) {
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index c1217a2..5adf25a 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -183,7 +183,7 @@
case kCompressedStackMapsCid: {
RawCompressedStackMaps* raw_maps =
static_cast<RawCompressedStackMaps*>(raw_object);
- return CompressedStackMapsSizeInSnapshot(raw_maps->ptr()->payload_size_);
+ return CompressedStackMapsSizeInSnapshot(raw_maps->ptr()->payload_size());
}
case kOneByteStringCid:
case kTwoByteStringCid: {
@@ -381,9 +381,9 @@
marked_tags = RawObject::SizeTag::update(size_in_bytes * 2, marked_tags);
stream->WriteTargetWord(marked_tags);
- stream->WriteFixed<uint32_t>(payload_size);
// We do not need to align the stream to a word boundary on 64-bit because
// sizeof(RawCompressedStackMaps) is 12, even there.
+ stream->WriteFixed<uint32_t>(map.raw()->ptr()->flags_and_size_);
stream->WriteBytes(map.raw()->ptr()->data(), payload_size);
stream->Align(compiler::target::ObjectAlignment::kObjectAlignment);
} else if (obj.IsString()) {
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index aedda0b..80ef2bf 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -275,9 +275,6 @@
const intptr_t remaining = thread->end() - start;
if (LIKELY(remaining >= instance_size)) {
thread->set_top(start + instance_size);
-#ifndef PRODUCT
- table->UpdateAllocatedNew(class_id, instance_size);
-#endif
*result = InitializeHeader(start, class_id, instance_size);
return true;
}
@@ -1238,6 +1235,65 @@
return InvokeRuntime(thread, this, DRT_TypeCheck, native_args);
}
+template <bool is_getter>
+bool Interpreter::AssertAssignableField(Thread* thread,
+ const KBCInstr* pc,
+ RawObject** FP,
+ RawObject** SP,
+ RawInstance* instance,
+ RawField* field,
+ RawInstance* value) {
+ RawAbstractType* field_type = field->ptr()->type_;
+ // Perform type test of value if field type is not one of dynamic, object,
+ // or void, and if the value is not null.
+ // TODO(regis): Revisit when type checking mode is not kUnaware anymore.
+ if (field_type->GetClassId() == kTypeCid) {
+ classid_t cid = Smi::Value(reinterpret_cast<RawSmi*>(
+ Type::RawCast(field_type)->ptr()->type_class_id_));
+ if (cid == kDynamicCid || cid == kInstanceCid || cid == kVoidCid) {
+ return true;
+ }
+ }
+ RawObject* null_value = Object::null();
+ if (value == null_value) {
+ return true;
+ }
+
+ RawSubtypeTestCache* cache = field->ptr()->type_test_cache_;
+ if (UNLIKELY(cache == null_value)) {
+ // Allocate new cache.
+ SP[1] = instance; // Preserve.
+ SP[2] = field; // Preserve.
+ SP[3] = value; // Preserve.
+ SP[4] = null_value; // Result slot.
+
+ Exit(thread, FP, SP + 5, pc);
+ if (!InvokeRuntime(thread, this, DRT_AllocateSubtypeTestCache,
+ NativeArguments(thread, 0, /* argv */ SP + 4,
+ /* retval */ SP + 4))) {
+ return false;
+ }
+
+ // Reload objects after the call which may trigger GC.
+ instance = reinterpret_cast<RawInstance*>(SP[1]);
+ field = reinterpret_cast<RawField*>(SP[2]);
+ value = reinterpret_cast<RawInstance*>(SP[3]);
+ cache = reinterpret_cast<RawSubtypeTestCache*>(SP[4]);
+ field_type = field->ptr()->type_;
+ field->ptr()->type_test_cache_ = cache;
+ }
+
+ // Push arguments of type test.
+ SP[1] = value;
+ SP[2] = field_type;
+ // Provide type arguments of instance as instantiator.
+ SP[3] = InterpreterHelpers::GetTypeArguments(thread, instance);
+ SP[4] = null_value; // Implicit setters cannot be generic.
+ SP[5] = is_getter ? Symbols::FunctionResult().raw() : field->ptr()->name_;
+ return AssertAssignable(thread, pc, FP, /* argv */ SP + 5,
+ /* reval */ SP + 1, cache);
+}
+
RawObject* Interpreter::Call(const Function& function,
const Array& arguments_descriptor,
const Array& arguments,
@@ -2253,6 +2309,21 @@
}
{
+ BYTECODE(PushUninitializedSentinel, 0);
+ *++SP = Object::sentinel().raw();
+ DISPATCH();
+ }
+
+ {
+ BYTECODE(JumpIfInitialized, T);
+ SP -= 1;
+ if (SP[1] != Object::sentinel().raw()) {
+ LOAD_JUMP_TARGET();
+ }
+ DISPATCH();
+ }
+
+ {
BYTECODE(StoreStaticTOS, D);
RawField* field = reinterpret_cast<RawField*>(LOAD_CONSTANT(rD));
RawInstance* value = static_cast<RawInstance*>(*SP--);
@@ -3064,8 +3135,8 @@
const intptr_t kArgc = 1;
RawInstance* instance =
reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[0]);
- RawObject* value =
- reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
+ RawInstance* value =
+ reinterpret_cast<RawInstance**>(instance->ptr())[offset_in_words];
if (UNLIKELY(value == Object::sentinel().raw())) {
SP[1] = 0; // Result slot.
@@ -3080,11 +3151,24 @@
instance = reinterpret_cast<RawInstance*>(SP[2]);
field = reinterpret_cast<RawField*>(SP[3]);
offset_in_words = Smi::Value(field->ptr()->value_.offset_);
- value = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
+ value = reinterpret_cast<RawInstance**>(instance->ptr())[offset_in_words];
}
*++SP = value;
+#if !defined(PRODUCT)
+ if (UNLIKELY(Field::NeedsLoadGuardBit::decode(field->ptr()->kind_bits_))) {
+ if (!AssertAssignableField<true>(thread, pc, FP, SP, instance, field,
+ value)) {
+ HANDLE_EXCEPTION;
+ }
+ // Reload objects after the call which may trigger GC.
+ field = reinterpret_cast<RawField*>(FrameFunction(FP)->ptr()->data_);
+ instance = reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[0]);
+ value = reinterpret_cast<RawInstance**>(instance->ptr())[offset_in_words];
+ }
+#endif
+
const bool unboxing =
(field->ptr()->is_nullable_ != kNullCid) &&
Field::UnboxingCandidateBit::decode(field->ptr()->kind_bits_);
@@ -3131,60 +3215,17 @@
const intptr_t kArgc = 2;
RawInstance* instance =
reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[0]);
- RawObject* value = FrameArguments(FP, kArgc)[1];
+ RawInstance* value =
+ reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[1]);
- RawAbstractType* field_type = field->ptr()->type_;
- classid_t cid;
- if (field_type->GetClassId() == kTypeCid) {
- cid = Smi::Value(reinterpret_cast<RawSmi*>(
- Type::RawCast(field_type)->ptr()->type_class_id_));
- } else {
- cid = kIllegalCid; // Not really illegal, but not a Type to skip.
+ if (!AssertAssignableField<false>(thread, pc, FP, SP, instance, field,
+ value)) {
+ HANDLE_EXCEPTION;
}
- // Perform type test of value if field type is not one of dynamic, object,
- // or void, and if the value is not null.
- RawObject* null_value = Object::null();
- // TODO(regis): Revisit when type checking mode is not kUnaware anymore.
- if (cid != kDynamicCid && cid != kInstanceCid && cid != kVoidCid &&
- value != null_value) {
- RawSubtypeTestCache* cache = field->ptr()->type_test_cache_;
- if (cache->GetClassId() != kSubtypeTestCacheCid) {
- // Allocate new cache.
- SP[1] = null_value; // Result.
-
- Exit(thread, FP, SP + 2, pc);
- if (!InvokeRuntime(thread, this, DRT_AllocateSubtypeTestCache,
- NativeArguments(thread, 0, /* argv */ SP + 1,
- /* retval */ SP + 1))) {
- HANDLE_EXCEPTION;
- }
-
- // Reload objects after the call which may trigger GC.
- field = reinterpret_cast<RawField*>(FrameFunction(FP)->ptr()->data_);
- field_type = field->ptr()->type_;
- instance = reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[0]);
- value = FrameArguments(FP, kArgc)[1];
- cache = reinterpret_cast<RawSubtypeTestCache*>(SP[1]);
- field->ptr()->type_test_cache_ = cache;
- }
-
- // Push arguments of type test.
- SP[1] = value;
- SP[2] = field_type;
- // Provide type arguments of instance as instantiator.
- SP[3] = InterpreterHelpers::GetTypeArguments(thread, instance);
- SP[4] = null_value; // Implicit setters cannot be generic.
- SP[5] = field->ptr()->name_;
- if (!AssertAssignable(thread, pc, FP, /* argv */ SP + 5,
- /* reval */ SP + 1, cache)) {
- HANDLE_EXCEPTION;
- }
-
- // Reload objects after the call which may trigger GC.
- field = reinterpret_cast<RawField*>(FrameFunction(FP)->ptr()->data_);
- instance = reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[0]);
- value = FrameArguments(FP, kArgc)[1];
- }
+ // Reload objects after the call which may trigger GC.
+ field = reinterpret_cast<RawField*>(FrameFunction(FP)->ptr()->data_);
+ instance = reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[0]);
+ value = reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[1]);
if (InterpreterHelpers::FieldNeedsGuardUpdate(field, value)) {
SP[1] = 0; // Unused result of runtime call.
@@ -3200,7 +3241,7 @@
// Reload objects after the call which may trigger GC.
field = reinterpret_cast<RawField*>(FrameFunction(FP)->ptr()->data_);
instance = reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[0]);
- value = FrameArguments(FP, kArgc)[1];
+ value = reinterpret_cast<RawInstance*>(FrameArguments(FP, kArgc)[1]);
}
const bool unboxing =
@@ -3231,7 +3272,7 @@
raw_value.writeTo(box->ptr()->value_);
} else {
instance->StorePointer(
- reinterpret_cast<RawObject**>(instance->ptr()) + offset_in_words,
+ reinterpret_cast<RawInstance**>(instance->ptr()) + offset_in_words,
value, thread);
}
@@ -3269,6 +3310,16 @@
// Field was initialized. Return its value.
*++SP = value;
+#if !defined(PRODUCT)
+ if (UNLIKELY(Field::NeedsLoadGuardBit::decode(field->ptr()->kind_bits_))) {
+ if (!AssertAssignableField<true>(
+ thread, pc, FP, SP, reinterpret_cast<RawInstance*>(null_value),
+ field, value)) {
+ HANDLE_EXCEPTION;
+ }
+ }
+#endif
+
DISPATCH();
}
@@ -3396,7 +3447,6 @@
// Function 'call' could not be resolved for argdesc_.
// Invoke noSuchMethod.
- RawObject* null_value = Object::null();
SP[1] = null_value;
SP[2] = receiver;
SP[3] = argdesc_;
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index c7e3445..03d913a 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -13,21 +13,23 @@
namespace dart {
-class Isolate;
-class RawObject;
-class InterpreterSetjmpBuffer;
-class Thread;
-class Code;
class Array;
+class Code;
+class InterpreterSetjmpBuffer;
+class Isolate;
+class ObjectPointerVisitor;
+class RawArray;
+class RawField;
+class RawFunction;
class RawICData;
class RawImmutableArray;
-class RawArray;
+class RawInstance;
+class RawObject;
class RawObjectPool;
-class RawFunction;
class RawString;
class RawSubtypeTestCache;
class RawTypeArguments;
-class ObjectPointerVisitor;
+class Thread;
class LookupCache : public ValueObject {
public:
@@ -198,6 +200,14 @@
RawObject** call_top,
RawObject** args,
RawSubtypeTestCache* cache);
+ template <bool is_getter>
+ bool AssertAssignableField(Thread* thread,
+ const KBCInstr* pc,
+ RawObject** FP,
+ RawObject** SP,
+ RawInstance* instance,
+ RawField* field,
+ RawInstance* value);
bool AllocateMint(Thread* thread,
int64_t value,
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index f1ea56d..a63c300 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -208,9 +208,13 @@
: embedder_data_(embedder_data),
isolates_rwlock_(new RwLock()),
isolates_(),
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+ last_reload_timestamp_(OS::GetCurrentTimeMillis()),
+#endif
source_(std::move(source)),
thread_registry_(new ThreadRegistry()),
- safepoint_handler_(new SafepointHandler(this)) {}
+ safepoint_handler_(new SafepointHandler(this)) {
+}
IsolateGroup::~IsolateGroup() {}
@@ -517,7 +521,7 @@
void Isolate::RegisterClass(const Class& cls) {
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
- if (IsReloading()) {
+ if (group()->IsReloading()) {
reload_context()->RegisterClass(cls);
return;
}
@@ -1242,7 +1246,6 @@
ISOLATE_METRIC_LIST(ISOLATE_METRIC_CONSTRUCTORS)
#undef ISOLATE_METRIC_CONSTRUCTORS
reload_every_n_stack_overflow_checks_(FLAG_reload_every),
- last_reload_timestamp_(OS::GetCurrentTimeMillis()),
#endif // !defined(PRODUCT)
start_time_micros_(OS::GetCurrentMonotonicMicros()),
random_(),
@@ -1592,52 +1595,85 @@
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
bool Isolate::CanReload() const {
return !Isolate::IsVMInternalIsolate(this) && is_runnable() &&
- !IsReloading() && (no_reload_scope_depth_ == 0) &&
+ !group()->IsReloading() && (no_reload_scope_depth_ == 0) &&
IsolateCreationEnabled() &&
OSThread::Current()->HasStackHeadroom(64 * KB);
}
-bool Isolate::ReloadSources(JSONStream* js,
- bool force_reload,
- const char* root_script_url,
- const char* packages_url,
- bool dont_delete_reload_context) {
+bool IsolateGroup::ReloadSources(JSONStream* js,
+ bool force_reload,
+ const char* root_script_url,
+ const char* packages_url,
+ bool dont_delete_reload_context) {
ASSERT(!IsReloading());
- SetHasAttemptedReload(true);
- reload_context_ = new IsolateReloadContext(this, js);
- reload_context_->Reload(force_reload, root_script_url, packages_url,
- /* kernel_buffer= */ nullptr,
- /* kernel_buffer_size= */ 0);
- bool success = !reload_context_->reload_aborted();
+
+ // TODO(dartbug.com/36097): Support multiple isolates within an isolate group.
+ RELEASE_ASSERT(!FLAG_enable_isolate_groups);
+ RELEASE_ASSERT(isolates_.First() == isolates_.Last());
+ RELEASE_ASSERT(isolates_.First() == Isolate::Current());
+
+ auto shared_class_table = Isolate::Current()->shared_class_table();
+ std::shared_ptr<IsolateGroupReloadContext> group_reload_context(
+ new IsolateGroupReloadContext(this, shared_class_table, js));
+ group_reload_context_ = group_reload_context;
+
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->SetHasAttemptedReload(true);
+ isolate->reload_context_ =
+ new IsolateReloadContext(group_reload_context_, isolate);
+ });
+ const bool success =
+ group_reload_context_->Reload(force_reload, root_script_url, packages_url,
+ /*kernel_buffer=*/nullptr,
+ /*kernel_buffer_size=*/0);
if (!dont_delete_reload_context) {
+ ForEachIsolate([&](Isolate* isolate) { isolate->DeleteReloadContext(); });
DeleteReloadContext();
}
return success;
}
-bool Isolate::ReloadKernel(JSONStream* js,
- bool force_reload,
- const uint8_t* kernel_buffer,
- intptr_t kernel_buffer_size,
- bool dont_delete_reload_context) {
+bool IsolateGroup::ReloadKernel(JSONStream* js,
+ bool force_reload,
+ const uint8_t* kernel_buffer,
+ intptr_t kernel_buffer_size,
+ bool dont_delete_reload_context) {
ASSERT(!IsReloading());
- SetHasAttemptedReload(true);
- reload_context_ = new IsolateReloadContext(this, js);
- reload_context_->Reload(force_reload,
- /* root_script_url= */ nullptr,
- /* packages_url= */ nullptr, kernel_buffer,
- kernel_buffer_size);
- bool success = !reload_context_->reload_aborted();
+
+ // TODO(dartbug.com/36097): Support multiple isolates within an isolate group.
+ RELEASE_ASSERT(!FLAG_enable_isolate_groups);
+ RELEASE_ASSERT(isolates_.First() == isolates_.Last());
+ RELEASE_ASSERT(isolates_.First() == Isolate::Current());
+
+ auto shared_class_table = Isolate::Current()->shared_class_table();
+ std::shared_ptr<IsolateGroupReloadContext> group_reload_context(
+ new IsolateGroupReloadContext(this, shared_class_table, js));
+ group_reload_context_ = group_reload_context;
+
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->SetHasAttemptedReload(true);
+ isolate->reload_context_ =
+ new IsolateReloadContext(group_reload_context_, isolate);
+ });
+ const bool success = group_reload_context_->Reload(
+ force_reload,
+ /*root_script_url=*/nullptr,
+ /*packages_url=*/nullptr, kernel_buffer, kernel_buffer_size);
if (!dont_delete_reload_context) {
+ ForEachIsolate([&](Isolate* isolate) { isolate->DeleteReloadContext(); });
DeleteReloadContext();
}
return success;
}
+void IsolateGroup::DeleteReloadContext() {
+ SafepointOperationScope safepoint_scope(Thread::Current());
+ group_reload_context_.reset();
+}
+
void Isolate::DeleteReloadContext() {
// Another thread may be in the middle of GetClassForHeapWalkAt.
- Thread* thread = Thread::Current();
- SafepointOperationScope safepoint_scope(thread);
+ SafepointOperationScope safepoint_scope(Thread::Current());
delete reload_context_;
reload_context_ = nullptr;
@@ -2334,6 +2370,7 @@
// Visit objects that are being used for isolate reload.
if (reload_context() != nullptr) {
reload_context()->VisitObjectPointers(visitor);
+ reload_context()->group_reload_context()->VisitObjectPointers(visitor);
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
if (ServiceIsolate::IsServiceIsolate(this)) {
@@ -2393,6 +2430,14 @@
ASSERT(!Thread::Current()->is_marking());
}
+void IsolateGroup::ForEachIsolate(
+ std::function<void(Isolate* isolate)> function) {
+ ReadRwLocker wl(ThreadState::Current(), isolates_rwlock_.get());
+ for (Isolate* isolate : isolates_) {
+ function(isolate);
+ }
+}
+
void IsolateGroup::RunWithStoppedMutators(
std::function<void()> single_current_mutator,
std::function<void()> otherwise,
@@ -2420,7 +2465,7 @@
RawClass* Isolate::GetClassForHeapWalkAt(intptr_t cid) {
RawClass* raw_class = nullptr;
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
- if (IsReloading()) {
+ if (group()->IsReloading()) {
raw_class = reload_context()->GetClassForHeapWalkAt(cid);
} else {
raw_class = class_table()->At(cid);
@@ -2435,8 +2480,8 @@
intptr_t Isolate::GetClassSizeForHeapWalkAt(intptr_t cid) {
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
- if (IsReloading()) {
- return reload_context()->GetClassSizeForHeapWalkAt(cid);
+ if (group()->IsReloading()) {
+ return group()->reload_context()->GetClassSizeForHeapWalkAt(cid);
} else {
return class_table()->SizeAt(cid);
}
@@ -2525,7 +2570,7 @@
jsobj.AddProperty("livePorts", message_handler()->live_ports());
jsobj.AddProperty("pauseOnExit", message_handler()->should_pause_on_exit());
#if !defined(DART_PRECOMPILED_RUNTIME)
- jsobj.AddProperty("_isReloading", IsReloading());
+ jsobj.AddProperty("_isReloading", group()->IsReloading());
#endif // !defined(DART_PRECOMPILED_RUNTIME)
if (!is_runnable()) {
@@ -2957,7 +3002,9 @@
#if !defined(DART_PRECOMPILED_RUNTIME)
const bool had_isolate_reload_context = reload_context() != nullptr;
const int64_t start_time_micros =
- !had_isolate_reload_context ? 0 : reload_context()->start_time_micros();
+ !had_isolate_reload_context
+ ? 0
+ : reload_context()->group_reload_context()->start_time_micros();
#endif // !defined(DART_PRECOMPILED_RUNTIME)
bool resume = false;
bool handle_non_service_messages = false;
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 9c83e6b..b5913f8 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -302,6 +302,12 @@
library_tag_handler_ = handler;
}
+ // Runs the given [function] on every isolate in the isolate group.
+ //
+ // During the duration of this function, no new isolates can be added to the
+ // isolate group.
+ void ForEachIsolate(std::function<void(Isolate* isolate)> function);
+
// Ensures mutators are stopped during execution of the provided function.
//
// If the current thread is the only mutator in the isolate group,
@@ -329,6 +335,36 @@
void PrintMemoryUsageJSON(JSONStream* stream);
#endif
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+ // By default the reload context is deleted. This parameter allows
+ // the caller to delete is separately if it is still needed.
+ bool ReloadSources(JSONStream* js,
+ bool force_reload,
+ const char* root_script_url = nullptr,
+ const char* packages_url = nullptr,
+ bool dont_delete_reload_context = false);
+
+ // If provided, the VM takes ownership of kernel_buffer.
+ bool ReloadKernel(JSONStream* js,
+ bool force_reload,
+ const uint8_t* kernel_buffer = nullptr,
+ intptr_t kernel_buffer_size = 0,
+ bool dont_delete_reload_context = false);
+
+ void set_last_reload_timestamp(int64_t value) {
+ last_reload_timestamp_ = value;
+ }
+ int64_t last_reload_timestamp() const { return last_reload_timestamp_; }
+
+ IsolateGroupReloadContext* reload_context() {
+ return group_reload_context_.get();
+ }
+
+ void DeleteReloadContext();
+
+ bool IsReloading() const { return group_reload_context_ != nullptr; }
+#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+
uint64_t id() { return id_; }
static void Init();
@@ -352,6 +388,11 @@
bool initial_spawn_successful_ = false;
Dart_LibraryTagHandler library_tag_handler_ = nullptr;
+#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
+ int64_t last_reload_timestamp_;
+ std::shared_ptr<IsolateGroupReloadContext> group_reload_context_;
+#endif
+
std::unique_ptr<IsolateGroupSource> source_;
std::unique_ptr<ThreadRegistry> thread_registry_;
std::unique_ptr<SafepointHandler> safepoint_handler_;
@@ -528,23 +569,6 @@
void ScheduleInterrupts(uword interrupt_bits);
-#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
- // By default the reload context is deleted. This parameter allows
- // the caller to delete is separately if it is still needed.
- bool ReloadSources(JSONStream* js,
- bool force_reload,
- const char* root_script_url = nullptr,
- const char* packages_url = nullptr,
- bool dont_delete_reload_context = false);
-
- // If provided, the VM takes ownership of kernel_buffer.
- bool ReloadKernel(JSONStream* js,
- bool force_reload,
- const uint8_t* kernel_buffer = nullptr,
- intptr_t kernel_buffer_size = 0,
- bool dont_delete_reload_context = false);
-#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
-
const char* MakeRunnable();
void Run();
@@ -765,8 +789,6 @@
VMTagCounters* vm_tag_counters() { return &vm_tag_counters_; }
#if !defined(DART_PRECOMPILED_RUNTIME)
- bool IsReloading() const { return reload_context_ != nullptr; }
-
IsolateReloadContext* reload_context() { return reload_context_; }
void DeleteReloadContext();
@@ -779,11 +801,6 @@
}
bool CanReload() const;
-
- void set_last_reload_timestamp(int64_t value) {
- last_reload_timestamp_ = value;
- }
- int64_t last_reload_timestamp() const { return last_reload_timestamp_; }
#else
bool IsReloading() const { return false; }
bool HasAttemptedReload() const { return false; }
@@ -1147,10 +1164,7 @@
V(HasAttemptedReload) \
V(HasAttemptedStepping) \
V(ShouldPausePostServiceRequest) \
- V(EnableTypeChecks) \
V(EnableAsserts) \
- V(ErrorOnBadType) \
- V(ErrorOnBadOverride) \
V(UseFieldGuards) \
V(UseOsr) \
V(Obfuscate) \
@@ -1216,7 +1230,6 @@
// Per-isolate copy of FLAG_reload_every.
intptr_t reload_every_n_stack_overflow_checks_;
IsolateReloadContext* reload_context_ = nullptr;
- int64_t last_reload_timestamp_;
// Ring buffer of objects assigned an id.
ObjectIdRing* object_id_ring_ = nullptr;
#endif // !defined(PRODUCT)
@@ -1323,6 +1336,7 @@
friend class Thread;
friend class Timeline;
friend class NoReloadScope; // reload_block
+ friend class IsolateGroup; // reload_context_
DISALLOW_COPY_AND_ASSIGN(Isolate);
};
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 4b7914b..7cb3ca6 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -54,50 +54,75 @@
check_reloaded,
false,
"Assert that an isolate has reloaded at least once.")
+DEFINE_FLAG(bool, gc_during_reload, false, "Cause explicit GC during reload.");
DECLARE_FLAG(bool, trace_deoptimization);
#define I (isolate())
-#define Z (thread->zone())
+#define Z zone_
#define TIMELINE_SCOPE(name) \
TimelineDurationScope tds##name(Thread::Current(), \
Timeline::GetIsolateStream(), #name)
-InstanceMorpher::InstanceMorpher(Zone* zone, const Class& from, const Class& to)
- : from_(Class::Handle(zone, from.raw())),
- to_(Class::Handle(zone, to.raw())),
- mapping_(zone, 0) {
- before_ = new (zone) ZoneGrowableArray<const Instance*>(zone, 0);
- after_ = new (zone) ZoneGrowableArray<const Instance*>(zone, 0);
- new_fields_ = new (zone) ZoneGrowableArray<const Field*>(zone, 0);
- ASSERT(from_.id() == to_.id());
- cid_ = from_.id();
- ComputeMapping();
+// The ObjectLocator is used for collecting instances that
+// needs to be morphed.
+class ObjectLocator : public ObjectVisitor {
+ public:
+ explicit ObjectLocator(IsolateGroupReloadContext* context)
+ : context_(context), count_(0) {}
+
+ void VisitObject(RawObject* obj) {
+ InstanceMorpher* morpher =
+ context_->instance_morpher_by_cid_.LookupValue(obj->GetClassId());
+ if (morpher != NULL) {
+ morpher->AddObject(obj);
+ count_++;
+ }
+ }
+
+ // Return the number of located objects for morphing.
+ intptr_t count() { return count_; }
+
+ private:
+ IsolateGroupReloadContext* context_;
+ intptr_t count_;
+};
+
+static bool HasNoTasks(Heap* heap) {
+ MonitorLocker ml(heap->old_space()->tasks_lock());
+ return heap->old_space()->tasks() == 0;
}
-void InstanceMorpher::AddObject(RawObject* object) const {
- ASSERT(object->GetClassId() == cid());
- const Instance& instance = Instance::Cast(Object::Handle(object));
- before_->Add(&instance);
-}
+// TODO(dartbug.com/36097): Once classes are split up into a read-only
+// descriptor which can be shared across isolates, we can make this function
+// take descriptors instead of the isolate-specific [Class] objects.
+//
+// (The information we access from [from]/[to] *must* be the same across
+// isolates.)
+InstanceMorpher* InstanceMorpher::CreateFromClassDescriptors(
+ Zone* zone,
+ SharedClassTable* shared_class_table,
+ const Class& from,
+ const Class& to) {
+ auto mapping = new (zone) ZoneGrowableArray<intptr_t>();
+ auto new_fields_offsets = new (zone) ZoneGrowableArray<intptr_t>();
-void InstanceMorpher::ComputeMapping() {
- if (from_.NumTypeArguments() > 0) {
+ if (from.NumTypeArguments() > 0) {
// Add copying of the optional type argument field.
- intptr_t from_offset = from_.type_arguments_field_offset();
+ intptr_t from_offset = from.type_arguments_field_offset();
ASSERT(from_offset != Class::kNoTypeArguments);
- intptr_t to_offset = to_.type_arguments_field_offset();
+ intptr_t to_offset = to.type_arguments_field_offset();
ASSERT(to_offset != Class::kNoTypeArguments);
- mapping_.Add(from_offset);
- mapping_.Add(to_offset);
+ mapping->Add(from_offset);
+ mapping->Add(to_offset);
}
// Add copying of the instance fields if matching by name.
// Note: currently the type of the fields are ignored.
const Array& from_fields =
- Array::Handle(from_.OffsetToFieldMap(true /* original classes */));
- const Array& to_fields = Array::Handle(to_.OffsetToFieldMap());
+ Array::Handle(from.OffsetToFieldMap(true /* original classes */));
+ const Array& to_fields = Array::Handle(to.OffsetToFieldMap());
Field& from_field = Field::Handle();
Field& to_field = Field::Handle();
String& from_name = String::Handle();
@@ -127,8 +152,8 @@
from_name = from_field.name();
if (from_name.Equals(to_name)) {
// Success
- mapping_.Add(from_field.Offset());
- mapping_.Add(to_field.Offset());
+ mapping->Add(from_field.Offset());
+ mapping->Add(to_field.Offset());
// Field did exist in old class deifnition.
new_field = false;
}
@@ -136,91 +161,97 @@
if (new_field) {
const Field& field = Field::Handle(to_field.raw());
- new_fields_->Add(&field);
-
field.set_needs_load_guard(true);
field.set_is_unboxing_candidate(false);
+ new_fields_offsets->Add(field.Offset());
}
}
+
+ ASSERT(from.id() == to.id());
+ return new (zone) InstanceMorpher(zone, to.id(), shared_class_table, mapping,
+ new_fields_offsets);
+}
+
+InstanceMorpher::InstanceMorpher(
+ Zone* zone,
+ classid_t cid,
+ SharedClassTable* shared_class_table,
+ ZoneGrowableArray<intptr_t>* mapping,
+ ZoneGrowableArray<intptr_t>* new_fields_offsets)
+ : zone_(zone),
+ cid_(cid),
+ shared_class_table_(shared_class_table),
+ mapping_(mapping),
+ new_fields_offsets_(new_fields_offsets),
+ before_(zone, 16),
+ after_(zone, 16) {}
+
+void InstanceMorpher::AddObject(RawObject* object) {
+ ASSERT(object->GetClassId() == cid_);
+ const Instance& instance = Instance::Cast(Object::Handle(Z, object));
+ before_.Add(&instance);
}
RawInstance* InstanceMorpher::Morph(const Instance& instance) const {
- const Instance& result = Instance::Handle(Instance::New(to_));
+ const auto& result = Instance::Handle(
+ Z, Instance::NewFromCidAndSize(shared_class_table_, cid_));
+
+#if defined(HASH_IN_OBJECT_HEADER)
+ const uint32_t hash = Object::GetCachedHash(instance.raw());
+ Object::SetCachedHash(result.raw(), hash);
+#endif
+
// Morph the context from instance to result using mapping_.
- for (intptr_t i = 0; i < mapping_.length(); i += 2) {
- intptr_t from_offset = mapping_.At(i);
- intptr_t to_offset = mapping_.At(i + 1);
- const Object& value =
- Object::Handle(instance.RawGetFieldAtOffset(from_offset));
+ Object& value = Object::Handle(Z);
+ for (intptr_t i = 0; i < mapping_->length(); i += 2) {
+ intptr_t from_offset = mapping_->At(i);
+ intptr_t to_offset = mapping_->At(i + 1);
+ ASSERT(from_offset > 0);
+ ASSERT(to_offset > 0);
+ value = instance.RawGetFieldAtOffset(from_offset);
result.RawSetFieldAtOffset(to_offset, value);
}
- for (intptr_t i = 0; i < new_fields_->length(); i++) {
- // Create a function that returns the expression.
- const Field* field = new_fields_->At(i);
- ASSERT(field->needs_load_guard());
- result.RawSetFieldAtOffset(field->Offset(), Object::sentinel());
+
+ for (intptr_t i = 0; i < new_fields_offsets_->length(); i++) {
+ const intptr_t field_offset = new_fields_offsets_->At(i);
+ result.RawSetFieldAtOffset(field_offset, Object::sentinel());
}
+
// Convert the instance into a filler object.
Become::MakeDummyObject(instance);
return result.raw();
}
-void InstanceMorpher::CreateMorphedCopies() const {
- for (intptr_t i = 0; i < before()->length(); i++) {
- const Instance& copy = Instance::Handle(Morph(*before()->At(i)));
- after()->Add(©);
+void InstanceMorpher::CreateMorphedCopies() {
+ for (intptr_t i = 0; i < before_.length(); i++) {
+ const Instance& copy = Instance::Handle(Z, Morph(*before_.At(i)));
+ after_.Add(©);
}
}
-void InstanceMorpher::DumpFormatFor(const Class& cls) const {
- THR_Print("%s\n", cls.ToCString());
- if (cls.NumTypeArguments() > 0) {
- intptr_t field_offset = cls.type_arguments_field_offset();
- ASSERT(field_offset != Class::kNoTypeArguments);
- THR_Print(" - @%" Pd " <type arguments>\n", field_offset);
- }
- const Array& fields = Array::Handle(cls.OffsetToFieldMap());
- Field& field = Field::Handle();
- String& name = String::Handle();
- for (intptr_t i = 0; i < fields.Length(); i++) {
- if (fields.At(i) != Field::null()) {
- field = Field::RawCast(fields.At(i));
- ASSERT(field.is_instance());
- name = field.name();
- THR_Print(" - @%" Pd " %s\n", field.Offset(), name.ToCString());
- }
- }
-
- THR_Print("Mapping: ");
- for (int i = 0; i < mapping_.length(); i += 2) {
- THR_Print(" %" Pd "->%" Pd, mapping_.At(i), mapping_.At(i + 1));
- }
- THR_Print("\n");
-}
-
void InstanceMorpher::Dump() const {
LogBlock blocker;
- THR_Print("Morphing from ");
- DumpFormatFor(from_);
- THR_Print("To ");
- DumpFormatFor(to_);
+ THR_Print("Morphing objects with cid: %d via this mapping: ", cid_);
+ for (int i = 0; i < mapping_->length(); i += 2) {
+ THR_Print(" %" Pd "->%" Pd, mapping_->At(i), mapping_->At(i + 1));
+ }
THR_Print("\n");
}
void InstanceMorpher::AppendTo(JSONArray* array) {
JSONObject jsobj(array);
jsobj.AddProperty("type", "ShapeChangeMapping");
- jsobj.AddProperty("class", to_);
- jsobj.AddProperty("instanceCount", before()->length());
+ jsobj.AddProperty64("class-id", cid_);
+ jsobj.AddProperty("instanceCount", before_.length());
JSONArray map(&jsobj, "fieldOffsetMappings");
- for (int i = 0; i < mapping_.length(); i += 2) {
+ for (int i = 0; i < mapping_->length(); i += 2) {
JSONArray pair(&map);
- pair.AddValue(mapping_.At(i));
- pair.AddValue(mapping_.At(i + 1));
+ pair.AddValue(mapping_->At(i));
+ pair.AddValue(mapping_->At(i + 1));
}
}
-void ReasonForCancelling::Report(IsolateReloadContext* context) {
+void ReasonForCancelling::Report(IsolateGroupReloadContext* context) {
const Error& error = Error::Handle(ToError());
context->ReportError(error);
}
@@ -258,8 +289,8 @@
jsobj.AddProperty("message", message.ToCString());
}
-RawError* IsolateReloadContext::error() const {
- ASSERT(reload_aborted());
+RawError* IsolateGroupReloadContext::error() const {
+ ASSERT(!reasons_to_cancel_reload_.is_empty());
// Report the first error to the surroundings.
return reasons_to_cancel_reload_.At(0)->ToError();
}
@@ -347,23 +378,6 @@
}
};
-bool IsolateReloadContext::IsSameField(const Field& a, const Field& b) {
- if (a.is_static() != b.is_static()) {
- return false;
- }
- const Class& a_cls = Class::Handle(a.Owner());
- const Class& b_cls = Class::Handle(b.Owner());
-
- if (!IsSameClass(a_cls, b_cls)) {
- return false;
- }
-
- const String& a_name = String::Handle(a.name());
- const String& b_name = String::Handle(b.name());
-
- return a_name.Equals(b_name);
-}
-
bool IsolateReloadContext::IsSameClass(const Class& a, const Class& b) {
if (a.is_patch() != b.is_patch()) {
// TODO(johnmccutchan): Should we just check the class kind bits?
@@ -398,24 +412,32 @@
return a_lib_url.Equals(b_lib_url);
}
-IsolateReloadContext::IsolateReloadContext(Isolate* isolate, JSONStream* js)
+IsolateGroupReloadContext::IsolateGroupReloadContext(
+ IsolateGroup* isolate_group,
+ SharedClassTable* shared_class_table,
+ JSONStream* js)
: zone_(Thread::Current()->zone()),
+ isolate_group_(isolate_group),
+ shared_class_table_(shared_class_table),
start_time_micros_(OS::GetCurrentMonotonicMicros()),
reload_timestamp_(OS::GetCurrentTimeMillis()),
- isolate_(isolate),
- reload_skipped_(false),
- reload_aborted_(false),
- reload_finalized_(false),
js_(js),
- saved_num_cids_(-1),
- saved_class_table_(nullptr),
- num_saved_libs_(-1),
+ saved_size_table_(nullptr),
instance_morphers_(zone_, 0),
reasons_to_cancel_reload_(zone_, 0),
- cid_mapper_(),
- modified_libs_(NULL),
- script_url_(String::null()),
- error_(Error::null()),
+ instance_morpher_by_cid_(zone_),
+ root_lib_url_(String::Handle(Z, String::null())),
+ root_url_prefix_(String::null()),
+ old_root_url_prefix_(String::null()) {}
+IsolateGroupReloadContext::~IsolateGroupReloadContext() {}
+
+IsolateReloadContext::IsolateReloadContext(
+ std::shared_ptr<IsolateGroupReloadContext> group_reload_context,
+ Isolate* isolate)
+ : zone_(Thread::Current()->zone()),
+ group_reload_context_(group_reload_context),
+ isolate_(isolate),
+ saved_class_table_(nullptr),
old_classes_set_storage_(Array::null()),
class_map_storage_(Array::null()),
removed_class_set_storage_(Array::null()),
@@ -424,9 +446,7 @@
become_map_storage_(Array::null()),
become_enum_mappings_(GrowableObjectArray::null()),
saved_root_library_(Library::null()),
- saved_libraries_(GrowableObjectArray::null()),
- root_url_prefix_(String::null()),
- old_root_url_prefix_(String::null()) {
+ saved_libraries_(GrowableObjectArray::null()) {
// NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not
// associated with the isolate yet and if a GC is triggered here the raw
// objects will not be properly accounted for.
@@ -438,23 +458,27 @@
ASSERT(saved_class_table_.load(std::memory_order_relaxed) == nullptr);
}
-void IsolateReloadContext::ReportError(const Error& error) {
- if (!FLAG_support_service || Isolate::IsVMInternalIsolate(I)) {
+void IsolateGroupReloadContext::ReportError(const Error& error) {
+ // TODO(dartbug.com/36097): We need to change the "reloadSources" service-api
+ // call to accept an isolate group instead of an isolate.
+ Isolate* isolate = Isolate::Current();
+ if (!FLAG_support_service || Isolate::IsVMInternalIsolate(isolate)) {
return;
}
- if (FLAG_trace_reload) {
- THR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString());
- }
- ServiceEvent service_event(I, ServiceEvent::kIsolateReload);
+ TIR_Print("ISO-RELOAD: Error: %s\n", error.ToErrorCString());
+ ServiceEvent service_event(isolate, ServiceEvent::kIsolateReload);
service_event.set_reload_error(&error);
Service::HandleEvent(&service_event);
}
-void IsolateReloadContext::ReportSuccess() {
- if (!FLAG_support_service || Isolate::IsVMInternalIsolate(I)) {
+void IsolateGroupReloadContext::ReportSuccess() {
+ // TODO(dartbug.com/36097): We need to change the "reloadSources" service-api
+ // call to accept an isolate group instead of an isolate.
+ Isolate* isolate = Isolate::Current();
+ if (!FLAG_support_service || Isolate::IsVMInternalIsolate(isolate)) {
return;
}
- ServiceEvent service_event(I, ServiceEvent::kIsolateReload);
+ ServiceEvent service_event(isolate, ServiceEvent::kIsolateReload);
Service::HandleEvent(&service_event);
}
@@ -502,45 +526,36 @@
}
}
-// NOTE: This function returns *after* FinalizeLoading is called.
// If [root_script_url] is null, attempt to load from [kernel_buffer].
-void IsolateReloadContext::Reload(bool force_reload,
- const char* root_script_url,
- const char* packages_url_,
- const uint8_t* kernel_buffer,
- intptr_t kernel_buffer_size) {
+bool IsolateGroupReloadContext::Reload(bool force_reload,
+ const char* root_script_url,
+ const char* packages_url,
+ const uint8_t* kernel_buffer,
+ intptr_t kernel_buffer_size) {
TIMELINE_SCOPE(Reload);
+
Thread* thread = Thread::Current();
- ASSERT(isolate() == thread->isolate());
+
+ // All isolates have the same sources, so all of them have the same libraries.
+ // We use the [first_isolate_] here to determine which of libraries have
+ // changed.
+ ASSERT(first_isolate_ == nullptr);
+ first_isolate_ = thread->isolate();
+
+ // All isolates within an isolate group need to share one heap.
+ // TODO(dartbug.com/36097): Remove this assert once the shared heap CL has
+ // landed.
+ RELEASE_ASSERT(!FLAG_enable_isolate_groups);
+ Heap* heap = first_isolate_->heap();
+
+ num_old_libs_ = GrowableObjectArray::Handle(
+ Z, first_isolate_->object_store()->libraries())
+ .Length();
// Grab root library before calling CheckpointBeforeReload.
- const Library& old_root_lib = Library::Handle(object_store()->root_library());
- ASSERT(!old_root_lib.IsNull());
- const String& old_root_lib_url = String::Handle(old_root_lib.url());
- // Root library url.
- const String& root_lib_url =
- (root_script_url == NULL) ? old_root_lib_url
- : String::Handle(String::New(root_script_url));
+ GetRootLibUrl(root_script_url);
- // Check to see if the base url of the loaded libraries has moved.
- if (!old_root_lib_url.Equals(root_lib_url)) {
- const char* old_root_library_url_c = old_root_lib_url.ToCString();
- const char* root_library_url_c = root_lib_url.ToCString();
- const intptr_t common_suffix_length =
- CommonSuffixLength(root_library_url_c, old_root_library_url_c);
- root_url_prefix_ = String::SubString(
- root_lib_url, 0, root_lib_url.Length() - common_suffix_length + 1);
- old_root_url_prefix_ =
- String::SubString(old_root_lib_url, 0,
- old_root_lib_url.Length() - common_suffix_length + 1);
- }
-
- Object& result = Object::Handle(thread->zone());
std::unique_ptr<kernel::Program> kernel_program;
- String& packages_url = String::Handle();
- if (packages_url_ != NULL) {
- packages_url = String::New(packages_url_);
- }
// Reset stats.
num_received_libs_ = 0;
@@ -552,10 +567,6 @@
bool skip_reload = false;
{
// Load the kernel program and figure out the modified libraries.
- const GrowableObjectArray& libs =
- GrowableObjectArray::Handle(object_store()->libraries());
- intptr_t num_libs = libs.Length();
- modified_libs_ = new (Z) BitVector(Z, num_libs);
intptr_t* p_num_received_classes = nullptr;
intptr_t* p_num_received_procedures = nullptr;
@@ -570,70 +581,44 @@
p_num_received_classes = &num_received_classes_;
p_num_received_procedures = &num_received_procedures_;
} else {
- Dart_KernelCompilationResult retval = {};
- if (kernel_buffer != NULL && kernel_buffer_size != 0) {
- retval.kernel = const_cast<uint8_t*>(kernel_buffer);
- retval.kernel_size = kernel_buffer_size;
- retval.status = Dart_KernelCompilationStatus_Ok;
- } else {
- Dart_SourceFile* modified_scripts = NULL;
- intptr_t modified_scripts_count = 0;
-
- FindModifiedSources(thread, force_reload, &modified_scripts,
- &modified_scripts_count, packages_url_);
-
- {
- TransitionVMToNative transition(thread);
- retval = KernelIsolate::CompileToKernel(
- root_lib_url.ToCString(), NULL, 0, modified_scripts_count,
- modified_scripts, true, NULL);
- did_kernel_compilation = true;
+ if (kernel_buffer == NULL || kernel_buffer_size == 0) {
+ char* error = CompileToKernel(force_reload, packages_url,
+ &kernel_buffer, &kernel_buffer_size);
+ did_kernel_compilation = true;
+ if (error != nullptr) {
+ TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n");
+ const auto& error_str = String::Handle(Z, String::New(error));
+ free(error);
+ const ApiError& error = ApiError::Handle(Z, ApiError::New(error_str));
+ AddReasonForCancelling(new Aborted(Z, error));
+ ReportReasonsForCancelling();
+ CommonFinalizeTail(num_old_libs_);
+ return false;
}
}
-
- if (retval.status != Dart_KernelCompilationStatus_Ok) {
- TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n");
- const String& error_str = String::Handle(String::New(retval.error));
- free(retval.error);
- const ApiError& error = ApiError::Handle(ApiError::New(error_str));
- if (retval.kernel != NULL) {
- free(const_cast<uint8_t*>(retval.kernel));
- }
- AddReasonForCancelling(new Aborted(zone_, error));
- ReportReasonsForCancelling();
- CommonFinalizeTail();
- return;
- }
-
- // The ownership of the kernel buffer goes now to the VM.
- const ExternalTypedData& typed_data = ExternalTypedData::Handle(
- Z,
- ExternalTypedData::New(kExternalTypedDataUint8ArrayCid, retval.kernel,
- retval.kernel_size, Heap::kOld));
- typed_data.AddFinalizer(
- retval.kernel,
- [](void* isolate_callback_data, Dart_WeakPersistentHandle handle,
- void* data) { free(data); },
- retval.kernel_size);
-
- // TODO(dartbug.com/33973): Change the heap objects to have a proper
- // retaining path to the kernel blob and ensure the finalizer will free it
- // once there are no longer references to it.
- // (The [ExternalTypedData] currently referenced by e.g. functions point
- // into the middle of c-allocated buffer and don't have a finalizer).
- I->RetainKernelBlob(typed_data);
-
+ const auto& typed_data = ExternalTypedData::Handle(
+ Z, MakeRetainedTypedData(kernel_buffer, kernel_buffer_size));
kernel_program = kernel::Program::ReadFromTypedData(typed_data);
}
+ modified_libs_ = new (Z) BitVector(Z, num_old_libs_);
kernel::KernelLoader::FindModifiedLibraries(
- kernel_program.get(), I, modified_libs_, force_reload, &skip_reload,
- p_num_received_classes, p_num_received_procedures);
+ kernel_program.get(), first_isolate_, modified_libs_, force_reload,
+ &skip_reload, p_num_received_classes, p_num_received_procedures);
+
+ ASSERT(num_saved_libs_ == -1);
+ num_saved_libs_ = 0;
+ for (intptr_t i = 0; i < modified_libs_->length(); i++) {
+ if (!modified_libs_->Contains(i)) {
+ num_saved_libs_++;
+ }
+ }
}
+
if (skip_reload) {
ASSERT(modified_libs_->IsEmpty());
reload_skipped_ = true;
- ReportOnJSON(js_);
+ ReportOnJSON(js_, num_old_libs_);
// If we use the CFE and performed a compilation, we need to notify that
// we have accepted the compilation to clear some state in the incremental
@@ -642,11 +627,340 @@
AcceptCompilation(thread);
}
TIR_Print("---- SKIPPING RELOAD (No libraries were modified)\n");
- return;
+ return false;
}
TIR_Print("---- STARTING RELOAD\n");
+ intptr_t number_of_isolates = 0;
+ isolate_group_->ForEachIsolate(
+ [&](Isolate* isolate) { number_of_isolates++; });
+
+ // Disable the background compiler while we are performing the reload.
+ ForEachIsolate(
+ [&](Isolate* isolate) { BackgroundCompiler::Disable(isolate); });
+
+ // Wait for any concurrent marking tasks to finish and turn off the
+ // concurrent marker during reload as we might be allocating new instances
+ // (constants) when loading the new kernel file and this could cause
+ // inconsistency between the saved class table and the new class table.
+ const bool old_concurrent_mark_flag =
+ heap->old_space()->enable_concurrent_mark();
+ if (old_concurrent_mark_flag) {
+ heap->WaitForMarkerTasks(thread);
+ heap->old_space()->set_enable_concurrent_mark(false);
+ }
+
+ // Ensure all functions on the stack have unoptimized code.
+ // Deoptimize all code that had optimizing decisions that are dependent on
+ // assumptions from field guards or CHA.
+ // TODO(johnmccutchan): Deoptimizing dependent code here (before the reload)
+ // is paranoid. This likely can be moved to the commit phase.
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->reload_context()->EnsuredUnoptimizedCodeForStack();
+ isolate->reload_context()->DeoptimizeDependentCode();
+ isolate->reload_context()->ReloadPhase1AllocateStorageMapsAndCheckpoint();
+ });
+ // Renumbering the libraries has invalidated this.
+ modified_libs_ = nullptr;
+
+ if (FLAG_gc_during_reload) {
+ // We use kLowMemory to force the GC to compact, which is more likely to
+ // discover untracked pointers (and other issues, like incorrect class
+ // table).
+ heap->CollectAllGarbage(Heap::kLowMemory);
+ }
+
+ // Copy the size table for isolate group & class tables for each isolate.
+ {
+ TIMELINE_SCOPE(CheckpointClasses);
+ CheckpointSharedClassTable();
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->reload_context()->CheckpointClasses();
+ });
+ }
+
+ if (FLAG_gc_during_reload) {
+ // We use kLowMemory to force the GC to compact, which is more likely to
+ // discover untracked pointers (and other issues, like incorrect class
+ // table).
+ heap->CollectAllGarbage(Heap::kLowMemory);
+ }
+
+ // We synchronously load the hot-reload kernel diff (which includes changed
+ // libraries and any libraries transitively depending on them).
+ //
+ // If loading the hot-reload diff succeeded we'll finalize the loading, which
+ // will either commit or reject the reload request.
+ const auto& results = Array::Handle(Z, Array::New(number_of_isolates));
+ intptr_t isolateIndex = 0;
+ intptr_t load_errors = 0;
+
+ auto& tmp = Object::Handle(Z);
+ ForEachIsolate([&](Isolate* isolate) {
+ tmp = isolate->reload_context()->ReloadPhase2LoadKernel(
+ kernel_program.get(), root_lib_url_);
+ if (tmp.IsError()) {
+ results.SetAt(isolateIndex, tmp);
+ load_errors++;
+ }
+ isolateIndex++;
+ });
+
+ const auto& result = Object::Handle(results.At(0));
+
+ if (load_errors > 0) {
+ TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n");
+
+ const auto& error = Error::Cast(result);
+ AddReasonForCancelling(new Aborted(Z, error));
+
+ DiscardSavedClassTable(/*is_rollback=*/true);
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->reload_context()->ReloadPhase4Rollback();
+ });
+ CommonFinalizeTail(num_old_libs_);
+ } else {
+ ASSERT(!reload_skipped_ && !reload_finalized_);
+ TIR_Print("---- LOAD SUCCEEDED\n");
+
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->reload_context()->ReloadPhase3FinalizeLoading();
+ });
+
+ if (FLAG_gc_during_reload) {
+ // We use kLowMemory to force the GC to compact, which is more likely to
+ // discover untracked pointers (and other issues, like incorrect class
+ // table).
+ heap->CollectAllGarbage(Heap::kLowMemory);
+ }
+
+ if (!FLAG_reload_force_rollback && !HasReasonsForCancelling()) {
+ TIR_Print("---- COMMITTING RELOAD\n");
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->reload_context()->ReloadPhase4CommitPrepare();
+ });
+ bool discard_class_tables = true;
+ if (HasInstanceMorphers()) {
+ // Find all objects that need to be morphed (reallocated to a new size).
+ ObjectLocator locator(this);
+ {
+ HeapIterationScope iteration(Thread::Current());
+ iteration.IterateObjects(&locator);
+ }
+
+ // We are still using the old class table at this point.
+ if (FLAG_gc_during_reload) {
+ // We use kLowMemory to force the GC to compact, which is more likely
+ // to discover untracked pointers (and other issues, like incorrect
+ // class table).
+ heap->CollectAllGarbage(Heap::kLowMemory);
+ }
+ const intptr_t count = locator.count();
+ if (count > 0) {
+ TIMELINE_SCOPE(MorphInstances);
+
+ // While we are reallocating instances to their new size, the heap
+ // will contain a mix of instances with the old and new sizes that
+ // have the same cid. This makes the heap unwalkable until the
+ // "become" operation below replaces all the instances of the old
+ // size with forwarding corpses. Force heap growth to prevent size
+ // confusion during this period.
+ NoHeapGrowthControlScope scope;
+ // The HeapIterationScope above ensures no other GC tasks can be
+ // active.
+ ASSERT(HasNoTasks(heap));
+
+ const Array& before = Array::Handle(Z, Array::New(count));
+ const Array& after = Array::Handle(Z, Array::New(count));
+
+ MorphInstancesPhase1Allocate(&locator, before, after);
+ {
+ // Apply the new class table before "become". Become will replace
+ // all the instances of the old size with forwarding corpses, then
+ // perform a heap walk to fix references to the forwarding corpses.
+ // During this heap walk, it will encounter instances of the new
+ // size, so it requires the new class table.
+ ASSERT(HasNoTasks(heap));
+
+ // We accepted the hot-reload and morphed instances. So now we can
+ // commit to the changed class table and deleted the saved one.
+ DiscardSavedClassTable(/*is_rollback=*/false);
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->reload_context()->DiscardSavedClassTable(
+ /*is_rollback=*/false);
+ });
+ }
+ MorphInstancesPhase2Become(before, after);
+
+ discard_class_tables = false;
+ }
+ // We are using the new class table now.
+ if (FLAG_gc_during_reload) {
+ // We use kLowMemory to force the GC to compact, which is more likely
+ // to discover untracked pointers (and other issues, like incorrect
+ // class table).
+ heap->CollectAllGarbage(Heap::kLowMemory);
+ }
+ }
+ if (discard_class_tables) {
+ DiscardSavedClassTable(/*is_rollback=*/false);
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->reload_context()->DiscardSavedClassTable(
+ /*is_rollback=*/false);
+ });
+ }
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->reload_context()->ReloadPhase4CommitFinish();
+ });
+ TIR_Print("---- DONE COMMIT\n");
+ isolate_group_->set_last_reload_timestamp(reload_timestamp_);
+ } else {
+ TIR_Print("---- ROLLING BACK");
+ DiscardSavedClassTable(/*is_rollback=*/true);
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->reload_context()->ReloadPhase4Rollback();
+ });
+ }
+
+ // ValidateReload mutates the direct subclass information and does
+ // not remove dead subclasses. Rebuild the direct subclass
+ // information from scratch.
+ ForEachIsolate([&](Isolate* isolate) {
+ isolate->reload_context()->RebuildDirectSubclasses();
+ });
+ const intptr_t final_library_count =
+ GrowableObjectArray::Handle(Z,
+ first_isolate_->object_store()->libraries())
+ .Length();
+ CommonFinalizeTail(final_library_count);
+
+ // If we use the CFE and performed a compilation, we need to notify that
+ // we have accepted the compilation to clear some state in the incremental
+ // compiler.
+ if (did_kernel_compilation) {
+ AcceptCompilation(thread);
+ }
+ }
+
+ // Re-enable the background compiler. Do this before propagating any errors.
+ ForEachIsolate(
+ [&](Isolate* isolate) { BackgroundCompiler::Enable(isolate); });
+
+ // Reenable concurrent marking if it was initially on.
+ if (old_concurrent_mark_flag) {
+ heap->old_space()->set_enable_concurrent_mark(true);
+ }
+
+ bool success;
+ if (load_errors == 0 || HasReasonsForCancelling()) {
+ ReportSuccess();
+ success = true;
+ } else {
+ ReportReasonsForCancelling();
+ success = false;
+ }
+
+ // Once we --enable-isolate-groups in JIT again, we have to ensure unwind
+ // errors will be propagated to all isolates.
+ if (result.IsUnwindError()) {
+ const auto& error = Error::Cast(result);
+ if (thread->top_exit_frame_info() == 0) {
+ // We can only propagate errors when there are Dart frames on the stack.
+ // In this case there are no Dart frames on the stack and we set the
+ // thread's sticky error. This error will be returned to the message
+ // handler.
+ thread->set_sticky_error(error);
+ } else {
+ // If the tag handler returns with an UnwindError error, propagate it and
+ // give up.
+ Exceptions::PropagateError(error);
+ UNREACHABLE();
+ }
+ }
+
+ return success;
+}
+
+void IsolateGroupReloadContext::GetRootLibUrl(const char* root_script_url) {
+ const auto& old_root_lib =
+ Library::Handle(first_isolate_->object_store()->root_library());
+ ASSERT(!old_root_lib.IsNull());
+ const auto& old_root_lib_url = String::Handle(old_root_lib.url());
+
+ // Root library url.
+ if (root_script_url != nullptr) {
+ root_lib_url_ = String::New(root_script_url);
+ } else {
+ root_lib_url_ = old_root_lib_url.raw();
+ }
+
+ // Check to see if the base url of the loaded libraries has moved.
+ if (!old_root_lib_url.Equals(root_lib_url_)) {
+ const char* old_root_library_url_c = old_root_lib_url.ToCString();
+ const char* root_library_url_c = root_lib_url_.ToCString();
+ const intptr_t common_suffix_length =
+ CommonSuffixLength(root_library_url_c, old_root_library_url_c);
+ root_url_prefix_ = String::SubString(
+ root_lib_url_, 0, root_lib_url_.Length() - common_suffix_length + 1);
+ old_root_url_prefix_ =
+ String::SubString(old_root_lib_url, 0,
+ old_root_lib_url.Length() - common_suffix_length + 1);
+ }
+}
+
+char* IsolateGroupReloadContext::CompileToKernel(bool force_reload,
+ const char* packages_url,
+ const uint8_t** kernel_buffer,
+ intptr_t* kernel_buffer_size) {
+ Dart_SourceFile* modified_scripts = nullptr;
+ intptr_t modified_scripts_count = 0;
+ FindModifiedSources(force_reload, &modified_scripts, &modified_scripts_count,
+ packages_url);
+
+ Dart_KernelCompilationResult retval = {};
+ {
+ TransitionVMToNative transition(Thread::Current());
+ retval = KernelIsolate::CompileToKernel(root_lib_url_.ToCString(), nullptr,
+ 0, modified_scripts_count,
+ modified_scripts, true, nullptr);
+ }
+ if (retval.status != Dart_KernelCompilationStatus_Ok) {
+ if (retval.kernel != nullptr) {
+ free(retval.kernel);
+ }
+ return retval.error;
+ }
+ *kernel_buffer = retval.kernel;
+ *kernel_buffer_size = retval.kernel_size;
+ return nullptr;
+}
+
+RawExternalTypedData* IsolateGroupReloadContext::MakeRetainedTypedData(
+ const uint8_t* kernel_buffer,
+ intptr_t kernel_buffer_size) {
+ // The ownership of the kernel buffer goes now to the VM.
+ const auto& typed_data = ExternalTypedData::Handle(
+ Z, ExternalTypedData::New(kExternalTypedDataUint8ArrayCid,
+ const_cast<uint8_t*>(kernel_buffer),
+ kernel_buffer_size, Heap::kOld));
+ typed_data.AddFinalizer(
+ const_cast<uint8_t*>(kernel_buffer),
+ [](void* isolate_callback_data, Dart_WeakPersistentHandle handle,
+ void* data) { free(data); },
+ kernel_buffer_size);
+
+ // TODO(dartbug.com/33973): Change the heap objects to have a proper
+ // retaining path to the kernel blob and ensure the finalizer will free it
+ // once there are no longer references to it.
+ // (The [ExternalTypedData] currently referenced by e.g. functions point
+ // into the middle of c-allocated buffer and don't have a finalizer).
+ first_isolate_->RetainKernelBlob(typed_data);
+
+ return typed_data.raw();
+}
+
+void IsolateReloadContext::ReloadPhase1AllocateStorageMapsAndCheckpoint() {
// Preallocate storage for maps.
old_classes_set_storage_ =
HashTables::New<UnorderedHashSet<ClassMapTraits> >(4);
@@ -662,89 +976,54 @@
// hashCode on the instances.
become_enum_mappings_ = GrowableObjectArray::New(Heap::kOld);
- // Disable the background compiler while we are performing the reload.
- BackgroundCompiler::Disable(I);
-
- // Wait for any concurrent marking tasks to finish and turn off the
- // concurrent marker during reload as we might be allocating new instances
- // (constants) when loading the new kernel file and this could cause
- // inconsistency between the saved class table and the new class table.
- Heap* heap = thread->heap();
- const bool old_concurrent_mark_flag =
- heap->old_space()->enable_concurrent_mark();
- if (old_concurrent_mark_flag) {
- heap->WaitForMarkerTasks(thread);
- heap->old_space()->set_enable_concurrent_mark(false);
- }
-
- // Ensure all functions on the stack have unoptimized code.
- EnsuredUnoptimizedCodeForStack();
- // Deoptimize all code that had optimizing decisions that are dependent on
- // assumptions from field guards or CHA.
- // TODO(johnmccutchan): Deoptimizing dependent code here (before the reload)
- // is paranoid. This likely can be moved to the commit phase.
- DeoptimizeDependentCode();
- Checkpoint();
-
- // We synchronously load the hot-reload kernel diff (which includes changed
- // libraries and any libraries transitively depending on them).
- //
- // If loading the hot-reload diff succeeded we'll finalize the loading, which
- // will either commit or reject the reload request.
+ // While reloading everything we do must be reversible so that we can abort
+ // safely if the reload fails. This function stashes things to the side and
+ // prepares the isolate for the reload attempt.
{
- const Object& tmp =
- kernel::KernelLoader::LoadEntireProgram(kernel_program.get());
- if (!tmp.IsError()) {
- Library& lib = Library::Handle(thread->zone());
- lib ^= tmp.raw();
- // If main method disappeared or were not there to begin with then
- // KernelLoader will return null. In this case lookup library by
- // URL.
- if (lib.IsNull()) {
- lib = Library::LookupLibrary(thread, root_lib_url);
- }
- isolate()->object_store()->set_root_library(lib);
- FinalizeLoading();
- result = Object::null();
+ TIMELINE_SCOPE(Checkpoint);
+ CheckpointLibraries();
+ }
+}
- // If we use the CFE and performed a compilation, we need to notify that
- // we have accepted the compilation to clear some state in the incremental
- // compiler.
- if (did_kernel_compilation) {
- AcceptCompilation(thread);
- }
- } else {
- result = tmp.raw();
- }
+RawObject* IsolateReloadContext::ReloadPhase2LoadKernel(
+ kernel::Program* program,
+ const String& root_lib_url) {
+ Thread* thread = Thread::Current();
+
+ const Object& tmp = kernel::KernelLoader::LoadEntireProgram(program);
+ if (tmp.IsError()) {
+ return tmp.raw();
}
- // Re-enable the background compiler. Do this before propagating any errors.
- BackgroundCompiler::Enable(I);
-
- // Reenable concurrent marking if it was initially on.
- heap->old_space()->set_enable_concurrent_mark(old_concurrent_mark_flag);
-
- if (result.IsUnwindError()) {
- if (thread->top_exit_frame_info() == 0) {
- // We can only propagate errors when there are Dart frames on the stack.
- // In this case there are no Dart frames on the stack and we set the
- // thread's sticky error. This error will be returned to the message
- // handler.
- thread->set_sticky_error(Error::Cast(result));
- } else {
- // If the tag handler returns with an UnwindError error, propagate it and
- // give up.
- Exceptions::PropagateError(Error::Cast(result));
- UNREACHABLE();
- }
+ // If main method disappeared or were not there to begin with then
+ // KernelLoader will return null. In this case lookup library by
+ // URL.
+ auto& lib = Library::Handle(Library::RawCast(tmp.raw()));
+ if (lib.IsNull()) {
+ lib = Library::LookupLibrary(thread, root_lib_url);
}
+ isolate_->object_store()->set_root_library(lib);
+ return Object::null();
+}
- // Other errors (e.g. a parse error) are captured by the reload system.
- if (result.IsError()) {
- FinalizeFailedLoad(Error::Cast(result));
- } else {
- ReportSuccess();
- }
+void IsolateReloadContext::ReloadPhase3FinalizeLoading() {
+ BuildLibraryMapping();
+ BuildRemovedClassesSet();
+ ValidateReload();
+}
+
+void IsolateReloadContext::ReloadPhase4CommitPrepare() {
+ CommitBeforeInstanceMorphing();
+}
+
+void IsolateReloadContext::ReloadPhase4CommitFinish() {
+ CommitAfterInstanceMorphing();
+ PostCommit();
+}
+
+void IsolateReloadContext::ReloadPhase4Rollback() {
+ RollbackClasses();
+ RollbackLibraries();
}
void IsolateReloadContext::RegisterClass(const Class& new_cls) {
@@ -764,7 +1043,7 @@
}
VTIR_Print("Registering class: %s\n", new_cls.ToCString());
new_cls.set_id(old_cls.id());
- isolate()->class_table()->SetAt(old_cls.id(), new_cls.raw());
+ I->class_table()->SetAt(old_cls.id(), new_cls.raw());
if (!old_cls.is_enum_class()) {
new_cls.CopyCanonicalConstants(old_cls);
}
@@ -773,47 +1052,15 @@
AddClassMapping(new_cls, old_cls);
}
-void IsolateReloadContext::FinalizeLoading() {
- if (reload_skipped_ || reload_finalized_) {
- return;
- }
- BuildLibraryMapping();
- BuildRemovedClassesSet();
-
- TIR_Print("---- LOAD SUCCEEDED\n");
- if (ValidateReload()) {
- Commit();
- PostCommit();
- isolate()->set_last_reload_timestamp(reload_timestamp_);
- } else {
- ReportReasonsForCancelling();
- Rollback();
- }
- // ValidateReload mutates the direct subclass information and does
- // not remove dead subclasses. Rebuild the direct subclass
- // information from scratch.
- RebuildDirectSubclasses();
- CommonFinalizeTail();
-}
-
-// FinalizeFailedLoad will be called *before* Reload() returns and will only
-// be called if the embedder fails to load sources.
-void IsolateReloadContext::FinalizeFailedLoad(const Error& error) {
- TIR_Print("---- LOAD FAILED, ABORTING RELOAD\n");
- AddReasonForCancelling(new Aborted(zone_, error));
- ReportReasonsForCancelling();
- if (!reload_finalized_) {
- Rollback();
- }
- CommonFinalizeTail();
-}
-
-void IsolateReloadContext::CommonFinalizeTail() {
- ReportOnJSON(js_);
+void IsolateGroupReloadContext::CommonFinalizeTail(
+ intptr_t final_library_count) {
+ RELEASE_ASSERT(!reload_finalized_);
+ ReportOnJSON(js_, final_library_count);
reload_finalized_ = true;
}
-void IsolateReloadContext::ReportOnJSON(JSONStream* stream) {
+void IsolateGroupReloadContext::ReportOnJSON(JSONStream* stream,
+ intptr_t final_library_count) {
JSONObject jsobj(stream);
jsobj.AddProperty("type", "ReloadReport");
jsobj.AddProperty("success", reload_skipped_ || !HasReasonsForCancelling());
@@ -829,9 +1076,6 @@
}
JSONObject details(&jsobj, "details");
- const GrowableObjectArray& libs =
- GrowableObjectArray::Handle(object_store()->libraries());
- const intptr_t final_library_count = libs.Length();
details.AddProperty("finalLibraryCount", final_library_count);
details.AddProperty("receivedLibraryCount", num_received_libs_);
details.AddProperty("receivedLibrariesBytes", bytes_received_libs_);
@@ -910,8 +1154,23 @@
DeoptimizeTypeTestingStubs();
}
+void IsolateGroupReloadContext::CheckpointSharedClassTable() {
+ // Copy the size table for isolate group.
+ intptr_t* saved_size_table = nullptr;
+ shared_class_table_->CopyBeforeHotReload(&saved_size_table, &saved_num_cids_);
+ {
+ NoSafepointScope no_safepoint_scope(Thread::Current());
+
+ // The saved_size_table_ will now become source of truth for GC.
+ saved_size_table_.store(saved_size_table, std::memory_order_release);
+
+ // We can therefore wipe out all of the old entries (if that table is used
+ // for GC during the hot-reload we have a bug).
+ shared_class_table_->ResetBeforeHotReload();
+ }
+}
+
void IsolateReloadContext::CheckpointClasses() {
- TIMELINE_SCOPE(CheckpointClasses);
TIR_Print("---- CHECKPOINTING CLASSES\n");
// Checkpoint classes before a reload. We need to copy the following:
// 1) The size of the class table.
@@ -919,12 +1178,9 @@
// For efficiency, we build a set of classes before the reload. This set
// is used to pair new classes with old classes.
+ // Copy the class table for isolate.
ClassTable* class_table = I->class_table();
-
- // Copy the size of the class table.
- saved_num_cids_ = I->class_table()->NumCids();
-
- ClassAndSize* saved_class_table = nullptr;
+ RawClass** saved_class_table = nullptr;
class_table->CopyBeforeHotReload(&saved_class_table, &saved_num_cids_);
// Copy classes into saved_class_table_ first. Make sure there are no
@@ -958,17 +1214,19 @@
TIR_Print("---- System had %" Pd " classes\n", saved_num_cids_);
}
-Dart_FileModifiedCallback IsolateReloadContext::file_modified_callback_ = NULL;
+Dart_FileModifiedCallback IsolateGroupReloadContext::file_modified_callback_ =
+ nullptr;
-bool IsolateReloadContext::ScriptModifiedSince(const Script& script,
- int64_t since) {
- if (file_modified_callback_ == NULL) {
+bool IsolateGroupReloadContext::ScriptModifiedSince(const Script& script,
+ int64_t since) {
+ if (IsolateGroupReloadContext::file_modified_callback_ == NULL) {
return true;
}
// We use the resolved url to determine if the script has been modified.
const String& url = String::Handle(script.resolved_url());
const char* url_chars = url.ToCString();
- return (*file_modified_callback_)(url_chars, since);
+ return (*IsolateGroupReloadContext::file_modified_callback_)(url_chars,
+ since);
}
static bool ContainsScriptUri(const GrowableArray<const char*>& seen_uris,
@@ -985,21 +1243,19 @@
return false;
}
-void IsolateReloadContext::FindModifiedSources(
- Thread* thread,
+void IsolateGroupReloadContext::FindModifiedSources(
bool force_reload,
Dart_SourceFile** modified_sources,
intptr_t* count,
const char* packages_url) {
- Zone* zone = thread->zone();
- int64_t last_reload = I->last_reload_timestamp();
+ const int64_t last_reload = isolate_group_->last_reload_timestamp();
GrowableArray<const char*> modified_sources_uris;
- const GrowableObjectArray& libs =
- GrowableObjectArray::Handle(object_store()->libraries());
- Library& lib = Library::Handle(zone);
- Array& scripts = Array::Handle(zone);
- Script& script = Script::Handle(zone);
- String& uri = String::Handle(zone);
+ const auto& libs =
+ GrowableObjectArray::Handle(first_isolate_->object_store()->libraries());
+ Library& lib = Library::Handle(Z);
+ Array& scripts = Array::Handle(Z);
+ Script& script = Script::Handle(Z);
+ String& uri = String::Handle(Z);
for (intptr_t lib_idx = 0; lib_idx < libs.Length(); lib_idx++) {
lib ^= libs.At(lib_idx);
@@ -1025,8 +1281,9 @@
// In addition to all sources, we need to check if the .packages file
// contents have been modified.
if (packages_url != NULL) {
- if (file_modified_callback_ == NULL ||
- (*file_modified_callback_)(packages_url, last_reload)) {
+ if (IsolateGroupReloadContext::file_modified_callback_ == NULL ||
+ (*IsolateGroupReloadContext::file_modified_callback_)(packages_url,
+ last_reload)) {
modified_sources_uris.Add(packages_url);
}
}
@@ -1036,7 +1293,7 @@
return;
}
- *modified_sources = zone_->Alloc<Dart_SourceFile>(*count);
+ *modified_sources = Z->Alloc<Dart_SourceFile>(*count);
for (intptr_t i = 0; i < *count; ++i) {
(*modified_sources)[i].uri = modified_sources_uris[i];
(*modified_sources)[i].source = NULL;
@@ -1048,12 +1305,12 @@
TIR_Print("---- CHECKPOINTING LIBRARIES\n");
// Save the root library in case we abort the reload.
const Library& root_lib = Library::Handle(object_store()->root_library());
- set_saved_root_library(root_lib);
+ saved_root_library_ = root_lib.raw();
// Save the old libraries array in case we abort the reload.
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(object_store()->libraries());
- set_saved_libraries(libs);
+ saved_libraries_ = libs.raw();
// Make a filtered copy of the old libraries array. Keep "clean" libraries
// that we will use instead of reloading.
@@ -1062,23 +1319,20 @@
Library& lib = Library::Handle();
UnorderedHashSet<LibraryMapTraits> old_libraries_set(
old_libraries_set_storage_);
- num_saved_libs_ = 0;
for (intptr_t i = 0; i < libs.Length(); i++) {
lib ^= libs.At(i);
- if (modified_libs_->Contains(i)) {
+ if (group_reload_context_->modified_libs_->Contains(i)) {
// We are going to reload this library. Clear the index.
lib.set_index(-1);
} else {
// We are preserving this library across the reload, assign its new index
lib.set_index(new_libs.Length());
new_libs.Add(lib, Heap::kOld);
- num_saved_libs_++;
}
// Add old library to old libraries set.
bool already_present = old_libraries_set.Insert(lib);
ASSERT(!already_present);
}
- modified_libs_ = NULL; // Renumbering the libraries has invalidated this.
old_libraries_set_storage_ = old_libraries_set.Release().raw();
// Reset the registered libraries to the filtered array.
@@ -1087,15 +1341,6 @@
object_store()->set_root_library(Library::Handle());
}
-// While reloading everything we do must be reversible so that we can abort
-// safely if the reload fails. This function stashes things to the side and
-// prepares the isolate for the reload attempt.
-void IsolateReloadContext::Checkpoint() {
- TIMELINE_SCOPE(Checkpoint);
- CheckpointClasses();
- CheckpointLibraries();
-}
-
void IsolateReloadContext::RollbackClasses() {
TIR_Print("---- ROLLING BACK CLASS TABLE\n");
ASSERT(saved_num_cids_ > 0);
@@ -1108,8 +1353,7 @@
TIR_Print("---- ROLLING BACK LIBRARY CHANGES\n");
Thread* thread = Thread::Current();
Library& lib = Library::Handle();
- GrowableObjectArray& saved_libs =
- GrowableObjectArray::Handle(Z, saved_libraries());
+ const auto& saved_libs = GrowableObjectArray::Handle(Z, saved_libraries_);
if (!saved_libs.IsNull()) {
for (intptr_t i = 0; i < saved_libs.Length(); i++) {
lib = Library::RawCast(saved_libs.At(i));
@@ -1121,19 +1365,13 @@
Library::RegisterLibraries(thread, saved_libs);
}
- Library& saved_root_lib = Library::Handle(Z, saved_root_library());
+ Library& saved_root_lib = Library::Handle(Z, saved_root_library_);
if (!saved_root_lib.IsNull()) {
object_store()->set_root_library(saved_root_lib);
}
- set_saved_root_library(Library::Handle());
- set_saved_libraries(GrowableObjectArray::Handle());
-}
-
-void IsolateReloadContext::Rollback() {
- TIR_Print("---- ROLLING BACK");
- RollbackClasses();
- RollbackLibraries();
+ saved_root_library_ = Library::null();
+ saved_libraries_ = GrowableObjectArray::null();
}
#ifdef DEBUG
@@ -1172,9 +1410,8 @@
}
#endif
-void IsolateReloadContext::Commit() {
+void IsolateReloadContext::CommitBeforeInstanceMorphing() {
TIMELINE_SCOPE(Commit);
- TIR_Print("---- COMMITTING RELOAD\n");
#ifdef DEBUG
VerifyMaps();
@@ -1270,13 +1507,13 @@
for (intptr_t i = 0; i < libs.Length(); i++) {
lib = Library::RawCast(libs.At(i));
// Mark the library dirty if it comes after the libraries we saved.
- library_infos_[i].dirty = i >= num_saved_libs_;
+ library_infos_[i].dirty = i >= group_reload_context_->num_saved_libs_;
}
}
+}
+void IsolateReloadContext::CommitAfterInstanceMorphing() {
{
- MorphInstancesAndApplyNewClassTable();
-
const GrowableObjectArray& become_enum_mappings =
GrowableObjectArray::Handle(become_enum_mappings_);
UnorderedHashMap<BecomeMapTraits> become_map(become_map_storage_);
@@ -1326,8 +1563,7 @@
TIR_Print("Identity reload failed! B#C=%" Pd " A#C=%" Pd "\n",
saved_num_cids_, I->class_table()->NumCids());
}
- const GrowableObjectArray& saved_libs =
- GrowableObjectArray::Handle(saved_libraries());
+ const auto& saved_libs = GrowableObjectArray::Handle(saved_libraries_);
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(I->object_store()->libraries());
if (saved_libs.Length() != libs.Length()) {
@@ -1349,65 +1585,41 @@
void IsolateReloadContext::PostCommit() {
TIMELINE_SCOPE(PostCommit);
- set_saved_root_library(Library::Handle());
- set_saved_libraries(GrowableObjectArray::Handle());
+ saved_root_library_ = Library::null();
+ saved_libraries_ = GrowableObjectArray::null();
InvalidateWorld();
- TIR_Print("---- DONE COMMIT\n");
}
-void IsolateReloadContext::AddReasonForCancelling(ReasonForCancelling* reason) {
- reload_aborted_ = true;
+void IsolateGroupReloadContext::AddReasonForCancelling(
+ ReasonForCancelling* reason) {
reasons_to_cancel_reload_.Add(reason);
}
-void IsolateReloadContext::AddInstanceMorpher(InstanceMorpher* morpher) {
- instance_morphers_.Add(morpher);
- cid_mapper_.Insert(morpher);
+void IsolateGroupReloadContext::EnsureHasInstanceMorpherFor(
+ classid_t cid,
+ InstanceMorpher* instance_morpher) {
+ for (intptr_t i = 0; i < instance_morphers_.length(); ++i) {
+ if (instance_morphers_[i]->cid() == cid) {
+ return;
+ }
+ }
+ instance_morphers_.Add(instance_morpher);
+ instance_morpher_by_cid_.Insert(instance_morpher);
+ ASSERT(instance_morphers_[instance_morphers_.length() - 1]->cid() == cid);
}
-void IsolateReloadContext::ReportReasonsForCancelling() {
+void IsolateGroupReloadContext::ReportReasonsForCancelling() {
ASSERT(FLAG_reload_force_rollback || HasReasonsForCancelling());
for (int i = 0; i < reasons_to_cancel_reload_.length(); i++) {
reasons_to_cancel_reload_.At(i)->Report(this);
}
}
-// The ObjectLocator is used for collecting instances that
-// needs to be morphed.
-class ObjectLocator : public ObjectVisitor {
- public:
- explicit ObjectLocator(IsolateReloadContext* context)
- : context_(context), count_(0) {}
-
- void VisitObject(RawObject* obj) {
- InstanceMorpher* morpher =
- context_->cid_mapper_.LookupValue(obj->GetClassId());
- if (morpher != NULL) {
- morpher->AddObject(obj);
- count_++;
- }
- }
-
- // Return the number of located objects for morphing.
- intptr_t count() { return count_; }
-
- private:
- IsolateReloadContext* context_;
- intptr_t count_;
-};
-
-static bool HasNoTasks(Heap* heap) {
- MonitorLocker ml(heap->old_space()->tasks_lock());
- return heap->old_space()->tasks() == 0;
-}
-
-void IsolateReloadContext::MorphInstancesAndApplyNewClassTable() {
- TIMELINE_SCOPE(MorphInstances);
- if (!HasInstanceMorphers()) {
- // Fast path: no class had a shape change.
- DiscardSavedClassTable(/*is_rollback=*/false);
- return;
- }
+void IsolateGroupReloadContext::MorphInstancesPhase1Allocate(
+ ObjectLocator* locator,
+ const Array& before,
+ const Array& after) {
+ ASSERT(HasInstanceMorphers());
if (FLAG_trace_reload) {
LogBlock blocker;
@@ -1417,40 +1629,16 @@
}
}
- // Find all objects that need to be morphed (reallocated to a new size).
- ObjectLocator locator(this);
- {
- HeapIterationScope iteration(Thread::Current());
- iteration.IterateObjects(&locator);
- }
-
- intptr_t count = locator.count();
- if (count == 0) {
- // Fast path: classes with shape change have no instances.
- DiscardSavedClassTable(/*is_rollback=*/false);
- return;
- }
-
+ const intptr_t count = locator->count();
TIR_Print("Found %" Pd " object%s subject to morphing.\n", count,
(count > 1) ? "s" : "");
- // While we are reallocating instances to their new size, the heap will
- // contain a mix of instances with the old and new sizes that have the same
- // cid. This makes the heap unwalkable until the "become" operation below
- // replaces all the instances of the old size with forwarding corpses. Force
- // heap growth to prevent size confusion during this period.
- NoHeapGrowthControlScope scope;
- // The HeapIterationScope above ensures no other GC tasks can be active.
- ASSERT(HasNoTasks(I->heap()));
-
for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
instance_morphers_.At(i)->CreateMorphedCopies();
}
// Create the inputs for Become.
intptr_t index = 0;
- const Array& before = Array::Handle(Array::New(count));
- const Array& after = Array::Handle(Array::New(count));
for (intptr_t i = 0; i < instance_morphers_.length(); i++) {
InstanceMorpher* morpher = instance_morphers_.At(i);
for (intptr_t j = 0; j < morpher->before()->length(); j++) {
@@ -1460,31 +1648,24 @@
}
}
ASSERT(index == count);
+}
- // Apply the new class table before "become". Become will replace all the
- // instances of the old size with forwarding corpses, then perform a heap walk
- // to fix references to the forwarding corpses. During this heap walk, it will
- // encounter instances of the new size, so it requires the new class table.
- ASSERT(HasNoTasks(I->heap()));
-#if defined(DEBUG)
- for (intptr_t i = 0; i < saved_num_cids_; i++) {
- saved_class_table_.load(std::memory_order_relaxed)[i] =
- ClassAndSize(nullptr, -1);
- }
-#endif
-
- // We accepted the hot-reload and morphed instances. So now we can commit to
- // the changed class table and deleted the saved one.
- DiscardSavedClassTable(/*is_rollback=*/false);
+void IsolateGroupReloadContext::MorphInstancesPhase2Become(const Array& before,
+ const Array& after) {
+ ASSERT(HasInstanceMorphers());
Become::ElementsForwardIdentity(before, after);
// The heap now contains only instances with the new size. Ordinary GC is safe
// again.
}
-bool IsolateReloadContext::ValidateReload() {
+void IsolateGroupReloadContext::ForEachIsolate(
+ std::function<void(Isolate*)> callback) {
+ isolate_group_->ForEachIsolate(callback);
+}
+
+void IsolateReloadContext::ValidateReload() {
TIMELINE_SCOPE(ValidateReload);
- if (reload_aborted()) return false;
TIR_Print("---- VALIDATING RELOAD\n");
@@ -1523,73 +1704,58 @@
}
map.Release();
}
-
- return !FLAG_reload_force_rollback && !HasReasonsForCancelling();
-}
-
-RawClass* IsolateReloadContext::FindOriginalClass(const Class& cls) {
- return MappedClass(cls);
}
RawClass* IsolateReloadContext::GetClassForHeapWalkAt(intptr_t cid) {
- ClassAndSize* class_table =
- saved_class_table_.load(std::memory_order_acquire);
+ RawClass** class_table = saved_class_table_.load(std::memory_order_acquire);
if (class_table != NULL) {
ASSERT(cid > 0);
ASSERT(cid < saved_num_cids_);
- return class_table[cid].get_raw_class();
+ return class_table[cid];
} else {
return isolate_->class_table()->At(cid);
}
}
-intptr_t IsolateReloadContext::GetClassSizeForHeapWalkAt(intptr_t cid) {
- ClassAndSize* class_table =
- saved_class_table_.load(std::memory_order_acquire);
- if (class_table != NULL) {
+intptr_t IsolateGroupReloadContext::GetClassSizeForHeapWalkAt(classid_t cid) {
+ intptr_t* size_table = saved_size_table_.load(std::memory_order_acquire);
+ if (size_table != nullptr) {
ASSERT(cid > 0);
ASSERT(cid < saved_num_cids_);
- return class_table[cid].size();
+ return size_table[cid];
} else {
- return isolate_->class_table()->SizeAt(cid);
+ return shared_class_table_->SizeAt(cid);
}
}
void IsolateReloadContext::DiscardSavedClassTable(bool is_rollback) {
- ClassAndSize* local_saved_class_table =
+ RawClass** local_saved_class_table =
saved_class_table_.load(std::memory_order_relaxed);
I->class_table()->ResetAfterHotReload(local_saved_class_table,
saved_num_cids_, is_rollback);
saved_class_table_.store(nullptr, std::memory_order_release);
}
-RawLibrary* IsolateReloadContext::saved_root_library() const {
- return saved_root_library_;
+void IsolateGroupReloadContext::DiscardSavedClassTable(bool is_rollback) {
+ intptr_t* local_saved_size_table = saved_size_table_;
+ shared_class_table_->ResetAfterHotReload(local_saved_size_table,
+ saved_num_cids_, is_rollback);
+ saved_size_table_.store(nullptr, std::memory_order_release);
}
-void IsolateReloadContext::set_saved_root_library(const Library& value) {
- saved_root_library_ = value.raw();
-}
-
-RawGrowableObjectArray* IsolateReloadContext::saved_libraries() const {
- return saved_libraries_;
-}
-
-void IsolateReloadContext::set_saved_libraries(
- const GrowableObjectArray& value) {
- saved_libraries_ = value.raw();
+void IsolateGroupReloadContext::VisitObjectPointers(
+ ObjectPointerVisitor* visitor) {
+ visitor->VisitPointers(from(), to());
}
void IsolateReloadContext::VisitObjectPointers(ObjectPointerVisitor* visitor) {
visitor->VisitPointers(from(), to());
- ClassAndSize* saved_class_table =
+ RawClass** saved_class_table =
saved_class_table_.load(std::memory_order_relaxed);
- if (saved_class_table != nullptr) {
- for (intptr_t i = 0; i < saved_num_cids_; i++) {
- visitor->VisitPointer(
- reinterpret_cast<RawObject**>(&(saved_class_table[i].class_)));
- }
+ if (saved_class_table != NULL) {
+ auto class_table = reinterpret_cast<RawObject**>(&(saved_class_table[0]));
+ visitor->VisitPointers(class_table, saved_num_cids_);
}
}
@@ -1645,23 +1811,32 @@
public:
InvalidationCollector(Zone* zone,
GrowableArray<const Function*>* functions,
- GrowableArray<const KernelProgramInfo*>* kernel_infos)
- : zone_(zone), functions_(functions), kernel_infos_(kernel_infos) {}
+ GrowableArray<const KernelProgramInfo*>* kernel_infos,
+ GrowableArray<const Field*>* fields,
+ GrowableArray<const Instance*>* instances)
+ : zone_(zone),
+ functions_(functions),
+ kernel_infos_(kernel_infos),
+ fields_(fields),
+ instances_(instances) {}
virtual ~InvalidationCollector() {}
- virtual void VisitObject(RawObject* obj) {
- if (obj->IsPseudoObject()) {
- return; // Cannot be wrapped in handles.
- }
- const Object& handle = Object::Handle(zone_, obj);
- if (handle.IsFunction()) {
- const auto& func = Function::Cast(handle);
+ void VisitObject(RawObject* obj) {
+ intptr_t cid = obj->GetClassId();
+ if (cid == kFunctionCid) {
+ const Function& func =
+ Function::Handle(zone_, static_cast<RawFunction*>(obj));
if (!func.ForceOptimize()) {
// Force-optimized functions cannot deoptimize.
functions_->Add(&func);
}
- } else if (handle.IsKernelProgramInfo()) {
- kernel_infos_->Add(&KernelProgramInfo::Cast(handle));
+ } else if (cid == kKernelProgramInfoCid) {
+ kernel_infos_->Add(&KernelProgramInfo::Handle(
+ zone_, static_cast<RawKernelProgramInfo*>(obj)));
+ } else if (cid == kFieldCid) {
+ fields_->Add(&Field::Handle(zone_, static_cast<RawField*>(obj)));
+ } else if (cid > kNumPredefinedCids) {
+ instances_->Add(&Instance::Handle(zone_, static_cast<RawInstance*>(obj)));
}
}
@@ -1669,18 +1844,19 @@
Zone* const zone_;
GrowableArray<const Function*>* const functions_;
GrowableArray<const KernelProgramInfo*>* const kernel_infos_;
+ GrowableArray<const Field*>* const fields_;
+ GrowableArray<const Instance*>* const instances_;
};
typedef UnorderedHashMap<SmiTraits> IntHashMap;
void IsolateReloadContext::RunInvalidationVisitors() {
- TIMELINE_SCOPE(MarkAllFunctionsForRecompilation);
TIR_Print("---- RUNNING INVALIDATION HEAP VISITORS\n");
Thread* thread = Thread::Current();
StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone();
- Thread* mutator_thread = isolate()->mutator_thread();
+ Thread* mutator_thread = I->mutator_thread();
if (mutator_thread != nullptr) {
Interpreter* interpreter = mutator_thread->interpreter();
if (interpreter != nullptr) {
@@ -1690,13 +1866,27 @@
GrowableArray<const Function*> functions(4 * KB);
GrowableArray<const KernelProgramInfo*> kernel_infos(KB);
+ GrowableArray<const Field*> fields(4 * KB);
+ GrowableArray<const Instance*> instances(4 * KB);
{
HeapIterationScope iteration(thread);
- InvalidationCollector visitor(zone, &functions, &kernel_infos);
+ InvalidationCollector visitor(zone, &functions, &kernel_infos, &fields,
+ &instances);
iteration.IterateObjects(&visitor);
}
+ InvalidateKernelInfos(zone, kernel_infos);
+ InvalidateFunctions(zone, functions);
+ InvalidateFields(zone, fields, instances);
+}
+
+void IsolateReloadContext::InvalidateKernelInfos(
+ Zone* zone,
+ const GrowableArray<const KernelProgramInfo*>& kernel_infos) {
+ TIMELINE_SCOPE(InvalidateKernelInfos);
+ HANDLESCOPE(Thread::Current());
+
Array& data = Array::Handle(zone);
Object& key = Object::Handle(zone);
Smi& value = Smi::Handle(zone);
@@ -1723,6 +1913,13 @@
kernel::BytecodeReader::ResetObjectTable(info);
}
}
+}
+
+void IsolateReloadContext::InvalidateFunctions(
+ Zone* zone,
+ const GrowableArray<const Function*>& functions) {
+ TIMELINE_SCOPE(InvalidateFunctions);
+ HANDLESCOPE(Thread::Current());
CallSiteResetter resetter(zone);
@@ -1781,7 +1978,196 @@
}
}
+// Finds fields that are initialized or have a value that does not conform to
+// the field's static type, setting Field::needs_load_guard(). Accessors for
+// such fields are compiled with additional checks to handle lazy initialization
+// and to preserve type soundness.
+class FieldInvalidator {
+ public:
+ explicit FieldInvalidator(Zone* zone)
+ : cls_(Class::Handle(zone)),
+ cls_fields_(Array::Handle(zone)),
+ entry_(Object::Handle(zone)),
+ value_(Instance::Handle(zone)),
+ type_(AbstractType::Handle(zone)),
+ cache_(SubtypeTestCache::Handle(zone)),
+ entries_(Array::Handle(zone)),
+ instantiator_type_arguments_(TypeArguments::Handle(zone)),
+ function_type_arguments_(TypeArguments::Handle(zone)),
+ instance_cid_or_function_(Object::Handle(zone)),
+ instance_type_arguments_(TypeArguments::Handle(zone)),
+ parent_function_type_arguments_(TypeArguments::Handle(zone)),
+ delayed_function_type_arguments_(TypeArguments::Handle(zone)) {}
+
+ void CheckStatics(const GrowableArray<const Field*>& fields) {
+ HANDLESCOPE(Thread::Current());
+ instantiator_type_arguments_ = TypeArguments::null();
+ for (intptr_t i = 0; i < fields.length(); i++) {
+ const Field& field = *fields[i];
+ if (!field.is_static()) {
+ continue;
+ }
+ if (field.needs_load_guard()) {
+ continue; // Already guarding.
+ }
+ value_ = field.StaticValue();
+ CheckValueType(value_, field);
+ }
+ }
+
+ void CheckInstances(const GrowableArray<const Instance*>& instances) {
+ for (intptr_t i = 0; i < instances.length(); i++) {
+ // This handle scope does run very frequently, but is a net-win by
+ // preventing us from spending too much time in malloc for new handle
+ // blocks.
+ HANDLESCOPE(Thread::Current());
+ CheckInstance(*instances[i]);
+ }
+ }
+
+ private:
+ DART_FORCE_INLINE
+ void CheckInstance(const Instance& instance) {
+ cls_ = instance.clazz();
+ if (cls_.NumTypeArguments() > 0) {
+ instantiator_type_arguments_ = instance.GetTypeArguments();
+ } else {
+ instantiator_type_arguments_ = TypeArguments::null();
+ }
+ cls_fields_ = cls_.OffsetToFieldMap();
+ for (intptr_t i = 0; i < cls_fields_.Length(); i++) {
+ entry_ = cls_fields_.At(i);
+ if (!entry_.IsField()) {
+ continue;
+ }
+ const Field& field = Field::Cast(entry_);
+ CheckInstanceField(instance, field);
+ }
+ }
+
+ DART_FORCE_INLINE
+ void CheckInstanceField(const Instance& instance, const Field& field) {
+ if (field.needs_load_guard()) {
+ return; // Already guarding.
+ }
+ value_ ^= instance.GetField(field);
+ if (value_.raw() == Object::sentinel().raw()) {
+ // Needs guard for initialization.
+ ASSERT(!FLAG_identity_reload);
+ field.set_needs_load_guard(true);
+ return;
+ }
+ CheckValueType(value_, field);
+ }
+
+ DART_FORCE_INLINE
+ void CheckValueType(const Instance& value, const Field& field) {
+ if (value.IsNull()) {
+ return; // TODO(nnbd): Implement.
+ }
+ type_ = field.type();
+ if (type_.IsDynamicType()) {
+ return;
+ }
+
+ cls_ = value.clazz();
+ const intptr_t cid = cls_.id();
+ if (cid == kClosureCid) {
+ instance_cid_or_function_ = Closure::Cast(value).function();
+ instance_type_arguments_ =
+ Closure::Cast(value).instantiator_type_arguments();
+ parent_function_type_arguments_ =
+ Closure::Cast(value).function_type_arguments();
+ delayed_function_type_arguments_ =
+ Closure::Cast(value).delayed_type_arguments();
+ } else {
+ instance_cid_or_function_ = Smi::New(cid);
+ if (cls_.NumTypeArguments() > 0) {
+ instance_type_arguments_ = value_.GetTypeArguments();
+ } else {
+ instance_type_arguments_ = TypeArguments::null();
+ }
+ parent_function_type_arguments_ = TypeArguments::null();
+ delayed_function_type_arguments_ = TypeArguments::null();
+ }
+
+ cache_ = field.type_test_cache();
+ if (cache_.IsNull()) {
+ cache_ = SubtypeTestCache::New();
+ field.set_type_test_cache(cache_);
+ }
+ entries_ = cache_.cache();
+
+ bool cache_hit = false;
+ for (intptr_t i = 0; entries_.At(i) != Object::null();
+ i += SubtypeTestCache::kTestEntryLength) {
+ if ((entries_.At(i + SubtypeTestCache::kInstanceClassIdOrFunction) ==
+ instance_cid_or_function_.raw()) &&
+ (entries_.At(i + SubtypeTestCache::kInstanceTypeArguments) ==
+ instance_type_arguments_.raw()) &&
+ (entries_.At(i + SubtypeTestCache::kInstantiatorTypeArguments) ==
+ instantiator_type_arguments_.raw()) &&
+ (entries_.At(i + SubtypeTestCache::kFunctionTypeArguments) ==
+ function_type_arguments_.raw()) &&
+ (entries_.At(
+ i + SubtypeTestCache::kInstanceParentFunctionTypeArguments) ==
+ parent_function_type_arguments_.raw()) &&
+ (entries_.At(
+ i + SubtypeTestCache::kInstanceDelayedFunctionTypeArguments) ==
+ delayed_function_type_arguments_.raw())) {
+ cache_hit = true;
+ if (entries_.At(i + SubtypeTestCache::kTestResult) !=
+ Bool::True().raw()) {
+ ASSERT(!FLAG_identity_reload);
+ field.set_needs_load_guard(true);
+ }
+ break;
+ }
+ }
+
+ if (!cache_hit) {
+ // TODO(regis): Make type check nullability aware.
+ if (!value.IsInstanceOf(NNBDMode::kLegacy, type_,
+ instantiator_type_arguments_,
+ function_type_arguments_)) {
+ ASSERT(!FLAG_identity_reload);
+ field.set_needs_load_guard(true);
+ } else {
+ cache_.AddCheck(instance_cid_or_function_, instance_type_arguments_,
+ instantiator_type_arguments_, function_type_arguments_,
+ parent_function_type_arguments_,
+ delayed_function_type_arguments_, Bool::True());
+ }
+ }
+ }
+
+ Class& cls_;
+ Array& cls_fields_;
+ Object& entry_;
+ Instance& value_;
+ AbstractType& type_;
+ SubtypeTestCache& cache_;
+ Array& entries_;
+ TypeArguments& instantiator_type_arguments_;
+ TypeArguments& function_type_arguments_;
+ Object& instance_cid_or_function_;
+ TypeArguments& instance_type_arguments_;
+ TypeArguments& parent_function_type_arguments_;
+ TypeArguments& delayed_function_type_arguments_;
+};
+
+void IsolateReloadContext::InvalidateFields(
+ Zone* zone,
+ const GrowableArray<const Field*>& fields,
+ const GrowableArray<const Instance*>& instances) {
+ TIMELINE_SCOPE(InvalidateFields);
+ FieldInvalidator invalidator(zone);
+ invalidator.CheckStatics(fields);
+ invalidator.CheckInstances(instances);
+}
+
void IsolateReloadContext::InvalidateWorld() {
+ TIMELINE_SCOPE(InvalidateWorld);
TIR_Print("---- INVALIDATING WORLD\n");
ResetMegamorphicCaches();
if (FLAG_trace_deoptimization) {
@@ -1792,20 +2178,6 @@
RunInvalidationVisitors();
}
-RawClass* IsolateReloadContext::MappedClass(const Class& replacement_or_new) {
- UnorderedHashMap<ClassMapTraits> map(class_map_storage_);
- Class& cls = Class::Handle();
- cls ^= map.GetOrNull(replacement_or_new);
- // No need to update storage address because no mutation occurred.
- map.Release();
- return cls.raw();
-}
-
-RawLibrary* IsolateReloadContext::MappedLibrary(
- const Library& replacement_or_new) {
- return Library::null();
-}
-
RawClass* IsolateReloadContext::OldClassOrNull(
const Class& replacement_or_new) {
UnorderedHashSet<ClassMapTraits> old_classes_set(old_classes_set_storage_);
@@ -1836,8 +2208,10 @@
Library& lib = Library::Handle();
lib ^= old_libraries_set.GetOrNull(replacement_or_new);
old_libraries_set.Release();
- if (lib.IsNull() && (root_url_prefix_ != String::null()) &&
- (old_root_url_prefix_ != String::null())) {
+
+ if (lib.IsNull() &&
+ (group_reload_context_->root_url_prefix_ != String::null()) &&
+ (group_reload_context_->old_root_url_prefix_ != String::null())) {
return OldLibraryOrNullBaseMoved(replacement_or_new);
}
return lib.raw();
@@ -1847,8 +2221,10 @@
// the base url prefix has moved.
RawLibrary* IsolateReloadContext::OldLibraryOrNullBaseMoved(
const Library& replacement_or_new) {
- const String& url_prefix = String::Handle(root_url_prefix_);
- const String& old_url_prefix = String::Handle(old_root_url_prefix_);
+ const String& url_prefix =
+ String::Handle(group_reload_context_->root_url_prefix_);
+ const String& old_url_prefix =
+ String::Handle(group_reload_context_->old_root_url_prefix_);
const intptr_t prefix_length = url_prefix.Length();
const intptr_t old_prefix_length = old_url_prefix.Length();
const String& new_url = String::Handle(replacement_or_new.url());
@@ -1860,8 +2236,7 @@
Library& old = Library::Handle();
String& old_url = String::Handle();
String& old_suffix = String::Handle();
- GrowableObjectArray& saved_libs =
- GrowableObjectArray::Handle(saved_libraries());
+ const auto& saved_libs = GrowableObjectArray::Handle(saved_libraries_);
ASSERT(!saved_libs.IsNull());
for (intptr_t i = 0; i < saved_libs.Length(); i++) {
old = Library::RawCast(saved_libs.At(i));
@@ -1888,7 +2263,8 @@
Library& replacement_or_new = Library::Handle();
Library& old = Library::Handle();
- for (intptr_t i = num_saved_libs_; i < libs.Length(); i++) {
+ for (intptr_t i = group_reload_context_->num_saved_libs_; i < libs.Length();
+ i++) {
replacement_or_new = Library::RawCast(libs.At(i));
old = OldLibraryOrNull(replacement_or_new);
if (old.IsNull()) {
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index a8c0d0a..bd3f86d 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -5,6 +5,9 @@
#ifndef RUNTIME_VM_ISOLATE_RELOAD_H_
#define RUNTIME_VM_ISOLATE_RELOAD_H_
+#include <functional>
+#include <memory>
+
#include "include/dart_tools_api.h"
#include "vm/globals.h"
@@ -42,6 +45,7 @@
class GrowableObjectArray;
class Isolate;
class Library;
+class ObjectLocator;
class ObjectPointerVisitor;
class ObjectStore;
class RawError;
@@ -54,45 +58,54 @@
class InstanceMorpher : public ZoneAllocated {
public:
- InstanceMorpher(Zone* zone, const Class& from, const Class& to);
+ // Creates a new [InstanceMorpher] based on the [from]/[to] class
+ // descriptions.
+ static InstanceMorpher* CreateFromClassDescriptors(
+ Zone* zone,
+ SharedClassTable* shared_class_table,
+ const Class& from,
+ const Class& to);
+
+ InstanceMorpher(Zone* zone,
+ classid_t cid,
+ SharedClassTable* shared_class_table,
+ ZoneGrowableArray<intptr_t>* mapping,
+ ZoneGrowableArray<intptr_t>* new_fields_offsets);
virtual ~InstanceMorpher() {}
// Called on each instance that needs to be morphed.
RawInstance* Morph(const Instance& instance) const;
// Adds an object to be morphed.
- void AddObject(RawObject* object) const;
+ void AddObject(RawObject* object);
// Create the morphed objects based on the before() list.
- void CreateMorphedCopies() const;
-
- // Dump the state of the morpher.
- void Dump() const;
+ void CreateMorphedCopies();
// Append the morper info to JSON array.
void AppendTo(JSONArray* array);
// Returns the list of objects that need to be morphed.
- ZoneGrowableArray<const Instance*>* before() const { return before_; }
+ const GrowableArray<const Instance*>* before() const { return &before_; }
+
// Returns the list of morphed objects (matches order in before()).
- ZoneGrowableArray<const Instance*>* after() const { return after_; }
- // Returns the list of new fields.
- ZoneGrowableArray<const Field*>* new_fields() const { return new_fields_; }
+ const GrowableArray<const Instance*>* after() const { return &after_; }
// Returns the cid associated with the from_ and to_ class.
intptr_t cid() const { return cid_; }
- private:
- const Class& from_;
- const Class& to_;
- ZoneGrowableArray<intptr_t> mapping_;
- ZoneGrowableArray<const Instance*>* before_;
- ZoneGrowableArray<const Instance*>* after_;
- ZoneGrowableArray<const Field*>* new_fields_;
- intptr_t cid_;
+ // Dumps the field mappings for the [cid()] class.
+ void Dump() const;
- void ComputeMapping();
- void DumpFormatFor(const Class& cls) const;
+ private:
+ Zone* zone_;
+ classid_t cid_;
+ SharedClassTable* shared_class_table_;
+ ZoneGrowableArray<intptr_t>* mapping_;
+ ZoneGrowableArray<intptr_t>* new_fields_offsets_;
+
+ GrowableArray<const Instance*> before_;
+ GrowableArray<const Instance*> after_;
};
class ReasonForCancelling : public ZoneAllocated {
@@ -101,7 +114,7 @@
virtual ~ReasonForCancelling() {}
// Reports a reason for cancelling reload.
- void Report(IsolateReloadContext* context);
+ void Report(IsolateGroupReloadContext* context);
// Conversion to a VM error object.
// Default implementation calls ToString.
@@ -128,13 +141,15 @@
const Class& to_;
};
-class IsolateReloadContext {
+class IsolateGroupReloadContext {
public:
- explicit IsolateReloadContext(Isolate* isolate, JSONStream* js);
- ~IsolateReloadContext();
+ IsolateGroupReloadContext(IsolateGroup* isolate,
+ SharedClassTable* shared_class_table,
+ JSONStream* js);
+ ~IsolateGroupReloadContext();
// If kernel_buffer is provided, the VM takes ownership when Reload is called.
- void Reload(bool force_reload,
+ bool Reload(bool force_reload,
const char* root_script_url = NULL,
const char* packages_url = NULL,
const uint8_t* kernel_buffer = NULL,
@@ -143,13 +158,15 @@
// All zone allocated objects must be allocated from this zone.
Zone* zone() const { return zone_; }
- bool UseSavedClassTableForGC() const {
- return saved_class_table_.load(std::memory_order_relaxed) != nullptr;
+ bool UseSavedSizeTableForGC() const {
+ return saved_size_table_.load(std::memory_order_relaxed) != nullptr;
}
+ IsolateGroup* isolate_group() const { return isolate_group_; }
+ bool reload_aborted() const { return HasReasonsForCancelling(); }
bool reload_skipped() const { return reload_skipped_; }
- bool reload_aborted() const { return reload_aborted_; }
RawError* error() const;
+ int64_t start_time_micros() const { return start_time_micros_; }
int64_t reload_timestamp() const { return reload_timestamp_; }
static Dart_FileModifiedCallback file_modified_callback() {
@@ -159,32 +176,10 @@
file_modified_callback_ = callback;
}
- static bool IsSameField(const Field& a, const Field& b);
- static bool IsSameLibrary(const Library& a_lib, const Library& b_lib);
- static bool IsSameClass(const Class& a, const Class& b);
-
private:
- RawLibrary* saved_root_library() const;
-
- RawGrowableObjectArray* saved_libraries() const;
-
- RawClass* FindOriginalClass(const Class& cls);
-
- bool IsDirty(const Library& lib);
-
- // Prefers old classes when we are in the middle of a reload.
- RawClass* GetClassForHeapWalkAt(intptr_t cid);
- intptr_t GetClassSizeForHeapWalkAt(intptr_t cid);
+ intptr_t GetClassSizeForHeapWalkAt(classid_t cid);
void DiscardSavedClassTable(bool is_rollback);
- void RegisterClass(const Class& new_cls);
-
- // Finds the library private key for |replacement_or_new| or return null
- // if |replacement_or_new| is new.
- RawString* FindLibraryPrivateKey(const Library& replacement_or_new);
-
- int64_t start_time_micros() const { return start_time_micros_; }
-
// Tells whether there are reasons for cancelling the reload.
bool HasReasonsForCancelling() const {
return !reasons_to_cancel_reload_.is_empty();
@@ -197,106 +192,70 @@
void ReportReasonsForCancelling();
// Reports the details of a reload operation.
- void ReportOnJSON(JSONStream* stream);
+ void ReportOnJSON(JSONStream* stream, intptr_t final_library_count);
- // Store morphing operation.
- void AddInstanceMorpher(InstanceMorpher* morpher);
+ // Ensures there is a instance morpher for [cid], if not it will use
+ // [instance_morpher]
+ void EnsureHasInstanceMorpherFor(classid_t cid,
+ InstanceMorpher* instance_morpher);
// Tells whether instance in the heap must be morphed.
bool HasInstanceMorphers() const { return !instance_morphers_.is_empty(); }
- // NOTE: FinalizeLoading will be called *before* Reload() returns. This
- // function will not be called if the embedder does not call
- // Dart_FinalizeLoading.
- void FinalizeLoading();
-
- // NOTE: FinalizeFailedLoad will be called *before* Reload returns. This
- // function will not be called if the embedder calls Dart_FinalizeLoading.
- void FinalizeFailedLoad(const Error& error);
-
// Called by both FinalizeLoading and FinalizeFailedLoad.
- void CommonFinalizeTail();
+ void CommonFinalizeTail(intptr_t final_library_count);
// Report back through the observatory channels.
void ReportError(const Error& error);
void ReportSuccess();
- void set_saved_root_library(const Library& value);
-
- void set_saved_libraries(const GrowableObjectArray& value);
-
void VisitObjectPointers(ObjectPointerVisitor* visitor);
- Isolate* isolate() { return isolate_; }
- ObjectStore* object_store();
-
- void EnsuredUnoptimizedCodeForStack();
- void DeoptimizeDependentCode();
-
- void Checkpoint();
-
- void CheckpointClasses();
-
- bool ScriptModifiedSince(const Script& script, int64_t since);
- void FindModifiedSources(Thread* thread,
- bool force_reload,
+ void GetRootLibUrl(const char* root_script_url);
+ char* CompileToKernel(bool force_reload,
+ const char* packages_url,
+ const uint8_t** kernel_buffer,
+ intptr_t* kernel_buffer_size);
+ RawExternalTypedData* MakeRetainedTypedData(const uint8_t* kernel_buffer,
+ intptr_t kernel_buffer_size);
+ void FindModifiedSources(bool force_reload,
Dart_SourceFile** modified_sources,
intptr_t* count,
const char* packages_url);
+ bool ScriptModifiedSince(const Script& script, int64_t since);
- void CheckpointLibraries();
+ void CheckpointSharedClassTable();
- void MorphInstancesAndApplyNewClassTable();
+ void MorphInstancesPhase1Allocate(ObjectLocator* locator,
+ const Array& before,
+ const Array& after);
+ void MorphInstancesPhase2Become(const Array& before, const Array& after);
- bool ValidateReload();
-
- void Rollback();
-
- void RollbackClasses();
- void RollbackLibraries();
-
-#ifdef DEBUG
- void VerifyMaps();
-#endif
-
- void Commit();
-
- void PostCommit();
-
- void ClearReplacedObjectBits();
-
- // atomic_install:
- void RunInvalidationVisitors();
- void ResetUnoptimizedICsOnStack();
- void ResetMegamorphicCaches();
- void InvalidateWorld();
+ void ForEachIsolate(std::function<void(Isolate*)> callback);
// The zone used for all reload related allocations.
Zone* zone_;
- int64_t start_time_micros_;
- int64_t reload_timestamp_;
- Isolate* isolate_;
- bool reload_skipped_;
- bool reload_aborted_;
- bool reload_finalized_;
+ IsolateGroup* isolate_group_;
+ SharedClassTable* shared_class_table_;
+
+ int64_t start_time_micros_ = -1;
+ int64_t reload_timestamp_ = -1;
+ Isolate* first_isolate_ = nullptr;
+ bool reload_skipped_ = false;
+ bool reload_finalized_ = false;
JSONStream* js_;
+ intptr_t num_old_libs_ = -1;
- intptr_t saved_num_cids_;
- std::atomic<ClassAndSize*> saved_class_table_;
- intptr_t num_saved_libs_;
- intptr_t num_received_libs_;
- intptr_t bytes_received_libs_;
- intptr_t num_received_classes_;
- intptr_t num_received_procedures_;
+ intptr_t saved_num_cids_ = -1;
+ std::atomic<intptr_t*> saved_size_table_;
+ intptr_t num_received_libs_ = -1;
+ intptr_t bytes_received_libs_ = -1;
+ intptr_t num_received_classes_ = -1;
+ intptr_t num_received_procedures_ = -1;
+ intptr_t num_saved_libs_ = -1;
- // Collect the necessary instance transformation for schema changes.
- ZoneGrowableArray<InstanceMorpher*> instance_morphers_;
-
- // Collects the reasons for cancelling the reload.
- ZoneGrowableArray<ReasonForCancelling*> reasons_to_cancel_reload_;
-
- // Required trait for the cid_mapper_;
+ // Required trait for the instance_morpher_by_cid_;
struct MorpherTrait {
typedef InstanceMorpher* Value;
typedef intptr_t Key;
@@ -308,53 +267,22 @@
static bool IsKeyEqual(Pair kv, Key key) { return kv->cid() == key; }
};
- // Hash map from cid to InstanceMorpher.
- DirectChainedHashMap<MorpherTrait> cid_mapper_;
+ // Collect the necessary instance transformation for schema changes.
+ GrowableArray<InstanceMorpher*> instance_morphers_;
- struct LibraryInfo {
- bool dirty;
- };
- MallocGrowableArray<LibraryInfo> library_infos_;
+ // Collects the reasons for cancelling the reload.
+ GrowableArray<ReasonForCancelling*> reasons_to_cancel_reload_;
+
+ // Hash map from cid to InstanceMorpher.
+ DirectChainedHashMap<MorpherTrait> instance_morpher_by_cid_;
// A bit vector indicating which of the original libraries were modified.
- BitVector* modified_libs_;
+ BitVector* modified_libs_ = nullptr;
- RawClass* OldClassOrNull(const Class& replacement_or_new);
-
- RawLibrary* OldLibraryOrNull(const Library& replacement_or_new);
-
- RawLibrary* OldLibraryOrNullBaseMoved(const Library& replacement_or_new);
-
- void BuildLibraryMapping();
- void BuildRemovedClassesSet();
-
- void AddClassMapping(const Class& replacement_or_new, const Class& original);
-
- void AddLibraryMapping(const Library& replacement_or_new,
- const Library& original);
-
- void AddStaticFieldMapping(const Field& old_field, const Field& new_field);
-
- void AddBecomeMapping(const Object& old, const Object& neu);
- void AddEnumBecomeMapping(const Object& old, const Object& neu);
-
- void RebuildDirectSubclasses();
-
- RawClass* MappedClass(const Class& replacement_or_new);
- RawLibrary* MappedLibrary(const Library& replacement_or_new);
-
- RawObject** from() { return reinterpret_cast<RawObject**>(&script_url_); }
- RawString* script_url_;
- RawError* error_;
- RawArray* old_classes_set_storage_;
- RawArray* class_map_storage_;
- RawArray* removed_class_set_storage_;
- RawArray* old_libraries_set_storage_;
- RawArray* library_map_storage_;
- RawArray* become_map_storage_;
- RawGrowableObjectArray* become_enum_mappings_;
- RawLibrary* saved_root_library_;
- RawGrowableObjectArray* saved_libraries_;
+ String& root_lib_url_;
+ RawObject** from() {
+ return reinterpret_cast<RawObject**>(&root_url_prefix_);
+ }
RawString* root_url_prefix_;
RawString* old_root_url_prefix_;
RawObject** to() {
@@ -367,10 +295,136 @@
friend class ObjectLocator;
friend class MarkFunctionsForRecompilation; // IsDirty.
friend class ReasonForCancelling;
+ friend class IsolateReloadContext;
+ friend class Instance; // GetClassSizeForHeapWalkAt
static Dart_FileModifiedCallback file_modified_callback_;
};
+class IsolateReloadContext {
+ public:
+ IsolateReloadContext(
+ std::shared_ptr<IsolateGroupReloadContext> group_reload_context,
+ Isolate* isolate);
+ ~IsolateReloadContext();
+
+ // All zone allocated objects must be allocated from this zone.
+ Zone* zone() const { return zone_; }
+
+ IsolateGroupReloadContext* group_reload_context() {
+ return group_reload_context_.get();
+ }
+
+ static bool IsSameLibrary(const Library& a_lib, const Library& b_lib);
+ static bool IsSameClass(const Class& a, const Class& b);
+
+ private:
+ bool IsDirty(const Library& lib);
+
+ // Prefers old classes when we are in the middle of a reload.
+ RawClass* GetClassForHeapWalkAt(intptr_t cid);
+ void DiscardSavedClassTable(bool is_rollback);
+
+ void RegisterClass(const Class& new_cls);
+
+ // Finds the library private key for |replacement_or_new| or return null
+ // if |replacement_or_new| is new.
+ RawString* FindLibraryPrivateKey(const Library& replacement_or_new);
+
+ void VisitObjectPointers(ObjectPointerVisitor* visitor);
+
+ Isolate* isolate() { return isolate_; }
+ ObjectStore* object_store();
+
+ void EnsuredUnoptimizedCodeForStack();
+ void DeoptimizeDependentCode();
+
+ void ReloadPhase1AllocateStorageMapsAndCheckpoint();
+ void CheckpointClasses();
+ RawObject* ReloadPhase2LoadKernel(kernel::Program* program,
+ const String& root_lib_url);
+ void ReloadPhase3FinalizeLoading();
+ void ReloadPhase4CommitPrepare();
+ void ReloadPhase4CommitFinish();
+ void ReloadPhase4Rollback();
+
+ void CheckpointLibraries();
+
+ void RollbackClasses();
+ void RollbackLibraries();
+
+#ifdef DEBUG
+ void VerifyMaps();
+#endif
+
+ void CommitBeforeInstanceMorphing();
+ void CommitAfterInstanceMorphing();
+ void PostCommit();
+
+ void RunInvalidationVisitors();
+ void InvalidateKernelInfos(
+ Zone* zone,
+ const GrowableArray<const KernelProgramInfo*>& kernel_infos);
+ void InvalidateFunctions(Zone* zone,
+ const GrowableArray<const Function*>& functions);
+ void InvalidateFields(Zone* zone,
+ const GrowableArray<const Field*>& fields,
+ const GrowableArray<const Instance*>& instances);
+ void ResetUnoptimizedICsOnStack();
+ void ResetMegamorphicCaches();
+ void InvalidateWorld();
+
+ struct LibraryInfo {
+ bool dirty;
+ };
+
+ // The zone used for all reload related allocations.
+ Zone* zone_;
+ std::shared_ptr<IsolateGroupReloadContext> group_reload_context_;
+ Isolate* isolate_;
+ intptr_t saved_num_cids_ = -1;
+ std::atomic<RawClass**> saved_class_table_;
+ MallocGrowableArray<LibraryInfo> library_infos_;
+
+ RawClass* OldClassOrNull(const Class& replacement_or_new);
+ RawLibrary* OldLibraryOrNull(const Library& replacement_or_new);
+ RawLibrary* OldLibraryOrNullBaseMoved(const Library& replacement_or_new);
+
+ void BuildLibraryMapping();
+ void BuildRemovedClassesSet();
+ void ValidateReload();
+
+ void AddClassMapping(const Class& replacement_or_new, const Class& original);
+ void AddLibraryMapping(const Library& replacement_or_new,
+ const Library& original);
+ void AddStaticFieldMapping(const Field& old_field, const Field& new_field);
+ void AddBecomeMapping(const Object& old, const Object& neu);
+ void AddEnumBecomeMapping(const Object& old, const Object& neu);
+ void RebuildDirectSubclasses();
+
+ RawObject** from() {
+ return reinterpret_cast<RawObject**>(&old_classes_set_storage_);
+ }
+ RawArray* old_classes_set_storage_;
+ RawArray* class_map_storage_;
+ RawArray* removed_class_set_storage_;
+ RawArray* old_libraries_set_storage_;
+ RawArray* library_map_storage_;
+ RawArray* become_map_storage_;
+ RawGrowableObjectArray* become_enum_mappings_;
+ RawLibrary* saved_root_library_;
+ RawGrowableObjectArray* saved_libraries_;
+ RawObject** to() { return reinterpret_cast<RawObject**>(&saved_libraries_); }
+
+ friend class Isolate;
+ friend class Class; // AddStaticFieldMapping, AddEnumBecomeMapping.
+ friend class Library;
+ friend class ObjectLocator;
+ friend class MarkFunctionsForRecompilation; // IsDirty.
+ friend class ReasonForCancelling;
+ friend class IsolateGroupReloadContext;
+};
+
class CallSiteResetter : public ValueObject {
public:
explicit CallSiteResetter(Zone* zone);
diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc
index 575c061..79325d8 100644
--- a/runtime/vm/isolate_reload_test.cc
+++ b/runtime/vm/isolate_reload_test.cc
@@ -3617,7 +3617,7 @@
EXPECT_ERROR(lib, "......");
}
-TEST_CASE(IsolateReload_RunNewFieldInitialiazersSuperClass) {
+TEST_CASE(IsolateReload_RunNewFieldInitializersSuperClass) {
const char* kScript =
"class Super {\n"
" static var foo = 'right';\n"
@@ -3654,7 +3654,11 @@
EXPECT_VALID(lib);
// Verify that we ran field initializers on existing instances in the
// correct scope.
- EXPECT_STREQ("right", SimpleInvokeStr(lib, "main"));
+ const char* actual = SimpleInvokeStr(lib, "main");
+ EXPECT(actual != nullptr);
+ if (actual != nullptr) {
+ EXPECT_STREQ("right", actual);
+ }
}
TEST_CASE(IsolateReload_RunNewFieldInitializersWithConsts) {
@@ -3748,6 +3752,322 @@
SimpleInvokeStr(lib, "main"));
}
+TEST_CASE(IsolateReload_ExistingFieldChangesType) {
+ const char* kScript = R"(
+ class Foo {
+ int x = 42;
+ }
+ Foo value;
+ main() {
+ value = new Foo();
+ return 'Okay';
+ }
+ )";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("Okay", SimpleInvokeStr(lib, "main"));
+
+ const char* kReloadScript = R"(
+ class Foo {
+ double x = 42.0;
+ }
+ Foo value;
+ main() {
+ try {
+ return value.x.toString();
+ } catch (e) {
+ return e.toString();
+ }
+ }
+ )";
+
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ(
+ "type 'int' is not a subtype of type 'double' of 'function result'",
+ SimpleInvokeStr(lib, "main"));
+}
+
+TEST_CASE(IsolateReload_ExistingStaticFieldChangesType) {
+ const char* kScript = R"(
+ int value = init();
+ init() => 42;
+ main() {
+ return value.toString();
+ }
+ )";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("42", SimpleInvokeStr(lib, "main"));
+
+ const char* kReloadScript = R"(
+ double value = init();
+ init() => 42.0;
+ main() {
+ try {
+ return value.toString();
+ } catch (e) {
+ return e.toString();
+ }
+ }
+ )";
+
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ(
+ "type 'int' is not a subtype of type 'double' of 'function result'",
+ SimpleInvokeStr(lib, "main"));
+}
+
+TEST_CASE(IsolateReload_ExistingFieldChangesTypeIndirect) {
+ const char* kScript = R"(
+ class A {}
+ class B extends A {}
+ class Foo {
+ A x;
+ Foo(this.x);
+ }
+ Foo value;
+ main() {
+ value = new Foo(new B());
+ return 'Okay';
+ }
+ )";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("Okay", SimpleInvokeStr(lib, "main"));
+
+ // B is no longer a subtype of A.
+ const char* kReloadScript = R"(
+ class A {}
+ class B {}
+ class Foo {
+ A x;
+ Foo(this.x);
+ }
+ Foo value;
+ main() {
+ try {
+ return value.x.toString();
+ } catch (e) {
+ return e.toString();
+ }
+ }
+ )";
+
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("type 'B' is not a subtype of type 'A' of 'function result'",
+ SimpleInvokeStr(lib, "main"));
+}
+
+TEST_CASE(IsolateReload_ExistingStaticFieldChangesTypeIndirect) {
+ const char* kScript = R"(
+ class A {}
+ class B extends A {}
+ A value = init();
+ init() => new B();
+ main() {
+ return value.toString();
+ }
+ )";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("Instance of 'B'", SimpleInvokeStr(lib, "main"));
+
+ // B is no longer a subtype of A.
+ const char* kReloadScript = R"(
+ class A {}
+ class B {}
+ A value = init();
+ init() => new A();
+ main() {
+ try {
+ return value.toString();
+ } catch (e) {
+ return e.toString();
+ }
+ }
+ )";
+
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("type 'B' is not a subtype of type 'A' of 'function result'",
+ SimpleInvokeStr(lib, "main"));
+}
+
+TEST_CASE(IsolateReload_ExistingFieldChangesTypeIndirectGeneric) {
+ const char* kScript = R"(
+ class A {}
+ class B extends A {}
+ class Foo {
+ List<A> x;
+ Foo(this.x);
+ }
+ Foo value;
+ main() {
+ value = new Foo(new List<B>());
+ return 'Okay';
+ }
+ )";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("Okay", SimpleInvokeStr(lib, "main"));
+
+ // B is no longer a subtype of A.
+ const char* kReloadScript = R"(
+ class A {}
+ class B {}
+ class Foo {
+ List<A> x;
+ Foo(this.x);
+ }
+ Foo value;
+ main() {
+ try {
+ return value.x.toString();
+ } catch (e) {
+ return e.toString();
+ }
+ }
+ )";
+
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ(
+ "type 'List<B>' is not a subtype of type 'List<A>' of 'function result'",
+ SimpleInvokeStr(lib, "main"));
+}
+
+TEST_CASE(IsolateReload_ExistingStaticFieldChangesTypeIndirectGeneric) {
+ const char* kScript = R"(
+ class A {}
+ class B extends A {}
+ List<A> value = init();
+ init() => new List<B>();
+ main() {
+ return value.toString();
+ }
+ )";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("[]", SimpleInvokeStr(lib, "main"));
+
+ // B is no longer a subtype of A.
+ const char* kReloadScript = R"(
+ class A {}
+ class B {}
+ List<A> value = init();
+ init() => new List<A>();
+ main() {
+ try {
+ return value.toString();
+ } catch (e) {
+ return e.toString();
+ }
+ }
+ )";
+
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ(
+ "type 'List<B>' is not a subtype of type 'List<A>' of 'function result'",
+ SimpleInvokeStr(lib, "main"));
+}
+
+TEST_CASE(IsolateReload_ExistingFieldChangesTypeIndirectFunction) {
+ const char* kScript = R"(
+ class A {}
+ class B extends A {}
+ typedef bool Predicate(B b);
+ class Foo {
+ Predicate x;
+ Foo(this.x);
+ }
+ Foo value;
+ main() {
+ value = new Foo((A a) => true);
+ return 'Okay';
+ }
+ )";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("Okay", SimpleInvokeStr(lib, "main"));
+
+ // B is no longer a subtype of A.
+ const char* kReloadScript = R"(
+ class A {}
+ class B {}
+ typedef bool Predicate(B b);
+ class Foo {
+ Predicate x;
+ Foo(this.x);
+ }
+ Foo value;
+ main() {
+ try {
+ return value.x.toString();
+ } catch (e) {
+ return e.toString();
+ }
+ }
+ )";
+
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ(
+ "type '(A) => bool' is not a subtype of type '(B) => bool' of 'function "
+ "result'",
+ SimpleInvokeStr(lib, "main"));
+}
+
+TEST_CASE(IsolateReload_ExistingStaticFieldChangesTypeIndirectFunction) {
+ const char* kScript = R"(
+ class A {}
+ class B extends A {}
+ typedef bool Predicate(B b);
+ Predicate value = init();
+ init() => (A a) => true;
+ main() {
+ return value.toString();
+ }
+ )";
+
+ Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ("Closure: (A) => bool", SimpleInvokeStr(lib, "main"));
+
+ // B is no longer a subtype of A.
+ const char* kReloadScript = R"(
+ class A {}
+ class B {}
+ typedef bool Predicate(B b);
+ Predicate value = init();
+ init() => (B a) => true;
+ main() {
+ try {
+ return value.toString();
+ } catch (e) {
+ return e.toString();
+ }
+ }
+ )";
+
+ lib = TestCase::ReloadTestScript(kReloadScript);
+ EXPECT_VALID(lib);
+ EXPECT_STREQ(
+ "type '(A) => bool' is not a subtype of type '(B) => bool' of 'function "
+ "result'",
+ SimpleInvokeStr(lib, "main"));
+}
+
TEST_CASE(IsolateReload_TypedefToNotTypedef) {
const char* kScript =
"typedef bool Predicate(dynamic x);\n"
diff --git a/runtime/vm/isolate_test.cc b/runtime/vm/isolate_test.cc
index 05170a7..d4dc8f3 100644
--- a/runtime/vm/isolate_test.cc
+++ b/runtime/vm/isolate_test.cc
@@ -161,6 +161,14 @@
};
TEST_CASE(NoOOBMessageScope) {
+ // Finish any GC in progress so that no kVMInterrupt is added for GC reasons.
+ {
+ TransitionNativeToVM transition(thread);
+ GCTestHelper::CollectAllGarbage();
+ const Error& error = Error::Handle(thread->HandleInterrupts());
+ RELEASE_ASSERT(error.IsNull());
+ }
+
// EXPECT_EQ is picky about type agreement for its arguments.
const uword kZero = 0;
const uword kMessageInterrupt = Thread::kMessageInterrupt;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 3b955ff..cfca523 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -2057,7 +2057,6 @@
script.set_kernel_program_info(kernel_program_info_);
script.set_line_starts(line_starts);
script.set_debug_positions(Array::null_array());
- script.set_yield_positions(Array::null_array());
return script.raw();
}
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index a7ff77d..67a3599 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -234,7 +234,7 @@
class ReverseArgOrderBit
: public BitField<intptr_t, bool, kReverseArgOrderBit, 1> {};
friend class Api;
- friend class BootstrapNatives;
+ friend class NativeEntry;
friend class Interpreter;
friend class Simulator;
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index 3176706..8cb8001 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -111,12 +111,40 @@
uword NativeEntry::BootstrapNativeCallWrapperEntry() {
uword entry =
reinterpret_cast<uword>(NativeEntry::BootstrapNativeCallWrapper);
+#if defined(USING_SIMULATOR)
+ entry = Simulator::RedirectExternalReference(
+ entry, Simulator::kNativeCall, NativeEntry::kNumCallWrapperArguments);
+#endif
return entry;
}
void NativeEntry::BootstrapNativeCallWrapper(Dart_NativeArguments args,
Dart_NativeFunction func) {
- func(args);
+ CHECK_STACK_ALIGNMENT;
+ if (func == LinkNativeCall) {
+ func(args);
+ return;
+ }
+
+ NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+ // Tell MemorySanitizer 'arguments' is initialized by generated code.
+ MSAN_UNPOISON(arguments, sizeof(*arguments));
+ {
+ Thread* thread = arguments->thread();
+ ASSERT(thread == Thread::Current());
+ TransitionGeneratedToVM transition(thread);
+ StackZone zone(thread);
+ // Be careful holding return_value_unsafe without a handle here.
+ // A return of Object::sentinel means the return value has already
+ // been set.
+ RawObject* return_value_unsafe = reinterpret_cast<BootstrapNativeFunction>(
+ func)(thread, zone.GetZone(), arguments);
+ if (return_value_unsafe != Object::sentinel().raw()) {
+ ASSERT(return_value_unsafe->IsDartInstance());
+ arguments->SetReturnUnsafe(return_value_unsafe);
+ }
+ DEOPTIMIZE_ALOT;
+ }
}
uword NativeEntry::NoScopeNativeCallWrapperEntry() {
@@ -220,10 +248,6 @@
uword NativeEntry::LinkNativeCallEntry() {
uword entry = reinterpret_cast<uword>(NativeEntry::LinkNativeCall);
-#if defined(USING_SIMULATOR)
- entry = Simulator::RedirectExternalReference(
- entry, Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments);
-#endif
return entry;
}
@@ -286,16 +310,8 @@
const Code& current_trampoline =
Code::Handle(zone, CodePatcher::GetNativeCallAt(
caller_frame->pc(), code, ¤t_function));
-#if !defined(USING_SIMULATOR)
ASSERT(current_function ==
reinterpret_cast<NativeFunction>(LinkNativeCall));
-#else
- ASSERT(
- current_function ==
- reinterpret_cast<NativeFunction>(Simulator::RedirectExternalReference(
- reinterpret_cast<uword>(LinkNativeCall),
- Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments)));
-#endif
ASSERT(current_trampoline.raw() == StubCode::CallBootstrapNative().raw());
}
#endif
@@ -321,12 +337,6 @@
Code& trampoline = Code::Handle(zone);
if (is_bootstrap_native) {
trampoline = StubCode::CallBootstrapNative().raw();
-#if defined(USING_SIMULATOR)
- patch_target_function = reinterpret_cast<NativeFunction>(
- Simulator::RedirectExternalReference(
- reinterpret_cast<uword>(patch_target_function),
- Simulator::kBootstrapNativeCall, NativeEntry::kNumArguments));
-#endif // defined USING_SIMULATOR
} else if (is_auto_scope) {
trampoline = StubCode::CallAutoScopeNative().raw();
} else {
@@ -344,7 +354,8 @@
// Tail-call resolved target.
if (is_bootstrap_native) {
- target_function(arguments);
+ NativeEntry::BootstrapNativeCallWrapper(
+ args, reinterpret_cast<Dart_NativeFunction>(target_function));
} else if (is_auto_scope) {
// Because this call is within a compilation unit, Clang doesn't respect
// the ABI alignment here.
diff --git a/runtime/vm/native_entry.h b/runtime/vm/native_entry.h
index 52e83a5..d9d4264 100644
--- a/runtime/vm/native_entry.h
+++ b/runtime/vm/native_entry.h
@@ -33,37 +33,22 @@
} while (0)
#endif
+typedef RawObject* (*BootstrapNativeFunction)(Thread* thread,
+ Zone* zone,
+ NativeArguments* arguments);
+
#define NATIVE_ENTRY_FUNCTION(name) BootstrapNatives::DN_##name
#define DEFINE_NATIVE_ENTRY(name, type_argument_count, argument_count) \
static RawObject* DN_Helper##name(Isolate* isolate, Thread* thread, \
Zone* zone, NativeArguments* arguments); \
- void NATIVE_ENTRY_FUNCTION(name)(Dart_NativeArguments args) { \
- CHECK_STACK_ALIGNMENT; \
- NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); \
- /* Tell MemorySanitizer 'arguments' is initialized by generated code. */ \
- MSAN_UNPOISON(arguments, sizeof(*arguments)); \
+ RawObject* NATIVE_ENTRY_FUNCTION(name)(Thread * thread, Zone * zone, \
+ NativeArguments * arguments) { \
+ TRACE_NATIVE_CALL("%s", "" #name); \
ASSERT(arguments->NativeArgCount() == argument_count); \
/* Note: a longer type arguments vector may be passed */ \
ASSERT(arguments->NativeTypeArgCount() >= type_argument_count); \
- TRACE_NATIVE_CALL("%s", "" #name); \
- { \
- Thread* thread = arguments->thread(); \
- ASSERT(thread == Thread::Current()); \
- Isolate* isolate = thread->isolate(); \
- TransitionGeneratedToVM transition(thread); \
- StackZone zone(thread); \
- /* Be careful holding return_value_unsafe without a handle here. */ \
- /* A return of Object::sentinel means the return value has already */ \
- /* been set. */ \
- RawObject* return_value_unsafe = \
- DN_Helper##name(isolate, thread, zone.GetZone(), arguments); \
- if (return_value_unsafe != Object::sentinel().raw()) { \
- ASSERT(return_value_unsafe->IsDartInstance()); \
- arguments->SetReturnUnsafe(return_value_unsafe); \
- } \
- DEOPTIMIZE_ALOT; \
- } \
+ return DN_Helper##name(thread->isolate(), thread, zone, arguments); \
} \
static RawObject* DN_Helper##name(Isolate* isolate, Thread* thread, \
Zone* zone, NativeArguments* arguments)
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index faf1184..b03021b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -944,13 +944,25 @@
cls.set_is_type_finalized();
cls = dynamic_class_;
- *dynamic_type_ = Type::NewNonParameterizedType(cls);
+ *dynamic_type_ = Type::New(cls, Object::null_type_arguments(),
+ TokenPosition::kNoSource, Nullability::kNullable);
+ dynamic_type_->SetIsFinalized();
+ dynamic_type_->ComputeHash();
+ dynamic_type_->SetCanonical();
cls = void_class_;
- *void_type_ = Type::NewNonParameterizedType(cls);
+ *void_type_ = Type::New(cls, Object::null_type_arguments(),
+ TokenPosition::kNoSource, Nullability::kNullable);
+ void_type_->SetIsFinalized();
+ void_type_->ComputeHash();
+ void_type_->SetCanonical();
cls = never_class_;
- *never_type_ = Type::NewNonParameterizedType(cls);
+ *never_type_ = Type::New(cls, Object::null_type_arguments(),
+ TokenPosition::kNoSource, Nullability::kNonNullable);
+ never_type_->SetIsFinalized();
+ never_type_->ComputeHash();
+ never_type_->SetCanonical();
// Since TypeArguments objects are passed as function arguments, make them
// behave as Dart instances, although they are just VM objects.
@@ -1567,7 +1579,7 @@
cls = object_store->array_class(); // Was allocated above.
RegisterPrivateClass(cls, Symbols::_List(), core_lib);
pending_classes.Add(cls);
- // We cannot use NewNonParameterizedType(cls), because Array is
+ // We cannot use NewNonParameterizedType(), because Array is
// parameterized. Warning: class _List has not been patched yet. Its
// declared number of type parameters is still 0. It will become 1 after
// patching. The array type allocated below represents the raw type _List
@@ -1934,7 +1946,10 @@
// name is a built-in identifier (this is wrong). The corresponding types
// are stored in the object store.
cls = object_store->null_class();
- type = Type::NewNonParameterizedType(cls);
+ type = Type::New(cls, Object::null_type_arguments(),
+ TokenPosition::kNoSource, Nullability::kNullable);
+ type.SetIsFinalized();
+ type ^= type.Canonicalize();
object_store->set_null_type(type);
ASSERT(type.IsNullable());
@@ -2316,11 +2331,6 @@
}
#ifndef PRODUCT
auto class_table = thread->isolate()->shared_class_table();
- if (space == Heap::kNew) {
- class_table->UpdateAllocatedNew(cls_id, size);
- } else {
- class_table->UpdateAllocatedOld(cls_id, size);
- }
if (class_table->TraceAllocationFor(cls_id)) {
Profiler::SampleAllocation(thread, cls_id);
}
@@ -2337,7 +2347,7 @@
raw_obj->SetMarkBitUnsynchronized();
// Setting the mark bit must not be ordered after a publishing store of this
// object. Adding a barrier here is cheaper than making every store into the
- // heap a store-release.
+ // heap a store-release. Compare Scavenger::ScavengePointer.
std::atomic_thread_fence(std::memory_order_release);
heap->old_space()->AllocateBlack(size);
}
@@ -2442,6 +2452,9 @@
}
RawAbstractType* Class::RareType() const {
+ if (!IsGeneric() && !IsClosureClass() && !IsTypedefClass()) {
+ return DeclarationType();
+ }
ASSERT(is_declaration_loaded());
const Type& type = Type::Handle(Type::New(
*this, Object::null_type_arguments(), TokenPosition::kNoSource));
@@ -3294,19 +3307,22 @@
#endif
bool AbstractType::InstantiateAndTestSubtype(
+ NNBDMode mode,
AbstractType* subtype,
AbstractType* supertype,
const TypeArguments& instantiator_type_args,
const TypeArguments& function_type_args) {
if (!subtype->IsInstantiated()) {
- *subtype = subtype->InstantiateFrom(
- instantiator_type_args, function_type_args, kAllFree, NULL, Heap::kOld);
+ *subtype = subtype->InstantiateFrom(mode, instantiator_type_args,
+ function_type_args, kAllFree, NULL,
+ Heap::kOld);
}
if (!supertype->IsInstantiated()) {
- *supertype = supertype->InstantiateFrom(
- instantiator_type_args, function_type_args, kAllFree, NULL, Heap::kOld);
+ *supertype = supertype->InstantiateFrom(mode, instantiator_type_args,
+ function_type_args, kAllFree, NULL,
+ Heap::kOld);
}
- return subtype->IsSubtypeOf(*supertype, Heap::kOld);
+ return subtype->IsSubtypeOf(mode, *supertype, Heap::kOld);
}
RawArray* Class::invocation_dispatcher_cache() const {
@@ -3579,8 +3595,10 @@
InvocationMirror::kSetter);
}
parameter_type = setter.ParameterTypeAt(0);
+ // TODO(regis): Make type check nullability aware.
if (!argument_type.IsNullType() && !parameter_type.IsDynamicType() &&
- !value.IsInstanceOf(parameter_type, Object::null_type_arguments(),
+ !value.IsInstanceOf(NNBDMode::kLegacy, parameter_type,
+ Object::null_type_arguments(),
Object::null_type_arguments())) {
const String& argument_name =
String::Handle(zone, setter.ParameterNameAt(0));
@@ -3602,8 +3620,10 @@
}
parameter_type = field.type();
+ // TODO(regis): Make type check nullability aware.
if (!argument_type.IsNullType() && !parameter_type.IsDynamicType() &&
- !value.IsInstanceOf(parameter_type, Object::null_type_arguments(),
+ !value.IsInstanceOf(NNBDMode::kLegacy, parameter_type,
+ Object::null_type_arguments(),
Object::null_type_arguments())) {
const String& argument_name = String::Handle(zone, field.name());
return ThrowTypeError(field.token_pos(), value, parameter_type,
@@ -3650,25 +3670,27 @@
call_args.SetAt(i + 1, temp);
}
call_args.SetAt(0, getter_result);
- const Array& call_args_descriptor_array =
- Array::Handle(zone, ArgumentsDescriptor::New(
- kTypeArgsLen, call_args.Length(), arg_names));
+ const Array& call_args_descriptor_array = Array::Handle(
+ zone, ArgumentsDescriptor::New(kTypeArgsLen, call_args.Length(),
+ arg_names, Heap::kNew));
// Call the closure.
return DartEntry::InvokeClosure(call_args, call_args_descriptor_array);
}
}
- const Array& args_descriptor_array = Array::Handle(
- zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
+ const Array& args_descriptor_array =
+ Array::Handle(zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length(),
+ arg_names, Heap::kNew));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
const TypeArguments& type_args = Object::null_type_arguments();
- if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
+ if (function.IsNull() ||
+ !function.AreValidArguments(NNBDMode::kLegacy, args_descriptor, NULL) ||
(respect_reflectable && !function.is_reflectable())) {
return ThrowNoSuchMethod(
AbstractType::Handle(zone, RareType()), function_name, args, arg_names,
InvocationMirror::kStatic, InvocationMirror::kMethod);
}
- RawObject* type_error =
- function.DoArgumentTypesMatch(args, args_descriptor, type_args);
+ RawObject* type_error = function.DoArgumentTypesMatch(
+ NNBDMode::kLegacy, args, args_descriptor, type_args);
if (type_error != Error::null()) {
return type_error;
}
@@ -3795,34 +3817,31 @@
Smi& value = Smi::Handle(zone);
String& field_name = String::Handle(zone);
+ static const struct {
+ const char* const field_name;
+ const intptr_t cid;
+ } cid_fields[] = {
#define CLASS_LIST_WITH_NULL(V) \
V(Null) \
CLASS_LIST_NO_OBJECT(V)
-
-#define ADD_SET_FIELD(clazz) \
- field_name = Symbols::New(thread, "cid" #clazz); \
- field = Field::New(field_name, true, false, true, false, *this, \
- Type::Handle(Type::IntType()), TokenPosition::kMinSource, \
- TokenPosition::kMinSource); \
- value = Smi::New(k##clazz##Cid); \
- field.SetStaticValue(value, true); \
- AddField(field);
-
- CLASS_LIST_WITH_NULL(ADD_SET_FIELD)
+#define ADD_SET_FIELD(clazz) {"cid" #clazz, k##clazz##Cid},
+ CLASS_LIST_WITH_NULL(ADD_SET_FIELD)
#undef ADD_SET_FIELD
-
-#define ADD_SET_FIELD(clazz) \
- field_name = Symbols::New(thread, "cid" #clazz "View"); \
- field = Field::New(field_name, true, false, true, false, *this, \
- Type::Handle(Type::IntType()), TokenPosition::kMinSource, \
- TokenPosition::kMinSource); \
- value = Smi::New(kTypedData##clazz##ViewCid); \
- field.SetStaticValue(value, true); \
- AddField(field);
-
- CLASS_LIST_TYPED_DATA(ADD_SET_FIELD)
+#define ADD_SET_FIELD(clazz) {"cid" #clazz "View", kTypedData##clazz##ViewCid},
+ CLASS_LIST_TYPED_DATA(ADD_SET_FIELD)
#undef ADD_SET_FIELD
#undef CLASS_LIST_WITH_NULL
+ };
+
+ const AbstractType& field_type = Type::Handle(zone, Type::IntType());
+ for (size_t i = 0; i < ARRAY_SIZE(cid_fields); i++) {
+ field_name = Symbols::New(thread, cid_fields[i].field_name);
+ field = Field::New(field_name, true, false, true, false, *this, field_type,
+ TokenPosition::kMinSource, TokenPosition::kMinSource);
+ value = Smi::New(cid_fields[i].cid);
+ field.SetStaticValue(value, true);
+ AddField(field);
+ }
return true;
}
@@ -4329,27 +4348,51 @@
}
void Class::set_declaration_type(const Type& value) const {
+ ASSERT(!(id() >= kDynamicCid && id() <= kNeverCid));
ASSERT(!value.IsNull() && value.IsCanonical() && value.IsOld());
ASSERT((declaration_type() == Object::null()) ||
(declaration_type() == value.raw())); // Set during own finalization.
// TODO(regis): Since declaration type is used as the runtime type of
// instances of a non-generic class, the nullability should be set to
// kNonNullable instead of kLegacy.
- // For now, we set the nullability to kLegacy, except for Null.
- ASSERT(value.IsLegacy() || (value.IsNullType() && value.IsNullable()));
+ // For now, we accept any except for Null (kNullable).
+ ASSERT(!value.IsNullType() || value.IsNullable());
+ ASSERT(value.IsNullType() || value.IsLegacy());
StorePointer(&raw_ptr()->declaration_type_, value.raw());
}
-RawType* Class::DeclarationType() const {
+RawType* Class::DeclarationType(Nullability nullability) const {
ASSERT(is_declaration_loaded());
- if (declaration_type() != Type::null()) {
- return declaration_type();
+ if (IsNullClass()) {
+ // Ignore requested nullability (e.g. by mirrors).
+ return Type::NullType();
}
- Type& type = Type::Handle(
- Type::New(*this, TypeArguments::Handle(type_parameters()), token_pos()));
+ if (IsDynamicClass()) {
+ return Type::DynamicType();
+ }
+ if (IsVoidClass()) {
+ return Type::VoidType();
+ }
+ if (IsNeverClass()) {
+ return Type::NeverType();
+ }
+ Type& type = Type::Handle(declaration_type());
+ if (!type.IsNull()) {
+ return type.ToNullability(nullability, Heap::kOld);
+ }
+ // TODO(regis): We should pass nullabiity to Type::New to avoid having to
+ // clone the type to the desired nullability. This however causes issues with
+ // the runtimeType intrinsic grabbing DeclarationType without checking its
+ // nullability. Indeed, when the CFE provides a non-nullable version of the
+ // type first, this non-nullable version gets cached as the declaration type.
+ // We consistenly cache the kLegacy version of a type, unless the non-nullable
+ // experiment is enabled, in which case we store the kNonNullable version.
+ // In either cases, the exception is type Null which is stored as kNullable.
+ type = Type::New(*this, TypeArguments::Handle(type_parameters()), token_pos(),
+ Nullability::kLegacy);
type ^= ClassFinalizer::FinalizeType(*this, type);
set_declaration_type(type);
- return type.raw();
+ return type.ToNullability(nullability, Heap::kOld);
}
void Class::set_allocation_stub(const Code& value) const {
@@ -4397,11 +4440,15 @@
// type T by class 'other' parameterized with 'other_type_arguments'.
// This class and class 'other' do not need to be finalized, however, they must
// be resolved as well as their interfaces.
-bool Class::IsSubtypeOf(const Class& cls,
+bool Class::IsSubtypeOf(NNBDMode mode,
+ const Class& cls,
const TypeArguments& type_arguments,
const Class& other,
const TypeArguments& other_type_arguments,
Heap::Space space) {
+ if (mode != NNBDMode::kLegacy) {
+ UNIMPLEMENTED();
+ }
// Use the 'this_class' object as if it was the receiver of this method, but
// instead of recursing, reset it to the super class and loop.
Thread* thread = Thread::Current();
@@ -4420,8 +4467,8 @@
return true;
}
// Apply additional subtyping rules if 'other' is 'FutureOr'.
- if (Class::IsSubtypeOfFutureOr(zone, this_class, type_arguments, other,
- other_type_arguments, space)) {
+ if (Class::IsSubtypeOfFutureOr(zone, mode, this_class, type_arguments,
+ other, other_type_arguments, space)) {
return true;
}
// DynamicType is not more specific than any type.
@@ -4455,7 +4502,7 @@
// above.
return false;
}
- return type_arguments.IsSubtypeOf(other_type_arguments, from_index,
+ return type_arguments.IsSubtypeOf(mode, other_type_arguments, from_index,
num_type_params, space);
}
// Check for 'direct super type' specified in the implements clause
@@ -4490,14 +4537,14 @@
// after the type arguments of the super type of this type.
// The index of the type parameters is adjusted upon finalization.
interface_args = interface_args.InstantiateFrom(
- type_arguments, Object::null_type_arguments(), kNoneFree, NULL,
- space);
+ mode, type_arguments, Object::null_type_arguments(), kNoneFree,
+ NULL, space);
}
// In Dart 2, implementing Function has no meaning.
if (interface_class.IsDartFunctionClass()) {
continue;
}
- if (Class::IsSubtypeOf(interface_class, interface_args, other,
+ if (Class::IsSubtypeOf(mode, interface_class, interface_args, other,
other_type_arguments, space)) {
return true;
}
@@ -4513,6 +4560,7 @@
}
bool Class::IsSubtypeOfFutureOr(Zone* zone,
+ NNBDMode mode,
const Class& cls,
const TypeArguments& type_arguments,
const Class& other,
@@ -4530,12 +4578,12 @@
if (!type_arguments.IsNull() && cls.IsFutureClass()) {
const AbstractType& type_arg =
AbstractType::Handle(zone, type_arguments.TypeAt(0));
- if (type_arg.IsSubtypeOf(other_type_arg, space)) {
+ if (type_arg.IsSubtypeOf(mode, other_type_arg, space)) {
return true;
}
}
if (other_type_arg.HasTypeClass() &&
- Class::IsSubtypeOf(cls, type_arguments,
+ Class::IsSubtypeOf(mode, cls, type_arguments,
Class::Handle(zone, other_type_arg.type_class()),
TypeArguments::Handle(other_type_arg.arguments()),
space)) {
@@ -5281,7 +5329,8 @@
return true;
}
-bool TypeArguments::IsSubtypeOf(const TypeArguments& other,
+bool TypeArguments::IsSubtypeOf(NNBDMode mode,
+ const TypeArguments& other,
intptr_t from_index,
intptr_t len,
Heap::Space space) const {
@@ -5294,7 +5343,7 @@
type = TypeAt(from_index + i);
other_type = other.TypeAt(from_index + i);
if (type.IsNull() || other_type.IsNull() ||
- !type.IsSubtypeOf(other_type, space)) {
+ !type.IsSubtypeOf(mode, other_type, space)) {
return false;
}
}
@@ -5521,6 +5570,7 @@
}
RawTypeArguments* TypeArguments::InstantiateFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -5547,7 +5597,7 @@
if (!type.IsNull() &&
!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(
- instantiator_type_arguments, function_type_arguments,
+ mode, instantiator_type_arguments, function_type_arguments,
num_free_fun_type_params, instantiation_trail, space);
// A returned null type indicates a failed instantiation in dead code that
// must be propagated up to the caller, the optimizing compiler.
@@ -5561,6 +5611,7 @@
}
RawTypeArguments* TypeArguments::InstantiateAndCanonicalizeFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments) const {
ASSERT(!IsInstantiated());
@@ -5587,8 +5638,8 @@
}
// Cache lookup failed. Instantiate the type arguments.
TypeArguments& result = TypeArguments::Handle();
- result = InstantiateFrom(instantiator_type_arguments, function_type_arguments,
- kAllFree, NULL, Heap::kOld);
+ result = InstantiateFrom(mode, instantiator_type_arguments,
+ function_type_arguments, kAllFree, NULL, Heap::kOld);
// Canonicalize type arguments.
result = result.Canonicalize();
// InstantiateAndCanonicalizeFrom is not reentrant. It cannot have been called
@@ -6318,8 +6369,8 @@
const TypeArguments& signature_type_arguments =
TypeArguments::Handle(scope_class.type_parameters());
// Return the still unfinalized signature type.
- type = Type::New(scope_class, signature_type_arguments, token_pos());
- type.set_nullability(nullability);
+ type = Type::New(scope_class, signature_type_arguments, token_pos(),
+ nullability);
type.set_signature(*this);
SetSignatureType(type);
}
@@ -6854,7 +6905,8 @@
return true;
}
-bool Function::AreValidArguments(intptr_t num_type_arguments,
+bool Function::AreValidArguments(NNBDMode mode,
+ intptr_t num_type_arguments,
intptr_t num_arguments,
const Array& argument_names,
String* error_message) const {
@@ -6899,7 +6951,8 @@
return true;
}
-bool Function::AreValidArguments(const ArgumentsDescriptor& args_desc,
+bool Function::AreValidArguments(NNBDMode mode,
+ const ArgumentsDescriptor& args_desc,
String* error_message) const {
const intptr_t num_type_arguments = args_desc.TypeArgsLen();
const intptr_t num_arguments = args_desc.Count();
@@ -6909,6 +6962,10 @@
num_named_arguments, error_message)) {
return false;
}
+ if (mode != NNBDMode::kLegacy) {
+ // TODO(regis): Check required named arguments.
+ UNIMPLEMENTED();
+ }
// Verify that all argument names are valid parameter names.
Zone* zone = Thread::Current()->zone();
String& argument_name = String::Handle(zone);
@@ -6945,6 +7002,7 @@
}
RawObject* Function::DoArgumentTypesMatch(
+ NNBDMode mode,
const Array& args,
const ArgumentsDescriptor& args_desc,
const TypeArguments& instantiator_type_args) const {
@@ -6953,9 +7011,9 @@
Function& instantiated_func = Function::Handle(zone, raw());
if (!HasInstantiatedSignature()) {
- instantiated_func = InstantiateSignatureFrom(instantiator_type_args,
+ instantiated_func = InstantiateSignatureFrom(mode, instantiator_type_args,
Object::null_type_arguments(),
- kAllFree, Heap::kOld);
+ kAllFree, Heap::kNew);
}
AbstractType& argument_type = AbstractType::Handle(zone);
AbstractType& parameter_type = AbstractType::Handle(zone);
@@ -6965,14 +7023,14 @@
for (intptr_t i = args_desc.FirstArgIndex(); i < args_desc.PositionalCount();
++i) {
argument ^= args.At(i);
- argument_type = argument.GetType(Heap::kOld);
+ argument_type = argument.GetType(Heap::kNew);
parameter_type = instantiated_func.ParameterTypeAt(i);
// If the argument type is dynamic or the parameter is null, move on.
if (parameter_type.IsDynamicType() || argument_type.IsNullType()) {
continue;
}
- if (!argument.IsInstanceOf(parameter_type, instantiator_type_args,
+ if (!argument.IsInstanceOf(mode, parameter_type, instantiator_type_args,
Object::null_type_arguments())) {
String& argument_name = String::Handle(zone, ParameterNameAt(i));
return ThrowTypeError(token_pos(), argument, parameter_type,
@@ -7005,14 +7063,14 @@
if (argument_name.Equals(parameter_name)) {
found = true;
argument ^= args.At(args_desc.PositionAt(i));
- argument_type = argument.GetType(Heap::kOld);
+ argument_type = argument.GetType(Heap::kNew);
parameter_type = instantiated_func.ParameterTypeAt(j);
// If the argument type is dynamic or the parameter is null, move on.
if (parameter_type.IsDynamicType() || argument_type.IsNullType()) {
continue;
}
- if (!argument.IsInstanceOf(parameter_type, instantiator_type_args,
+ if (!argument.IsInstanceOf(mode, parameter_type, instantiator_type_args,
Object::null_type_arguments())) {
String& argument_name = String::Handle(zone, ParameterNameAt(i));
return ThrowTypeError(token_pos(), argument, parameter_type,
@@ -7118,6 +7176,7 @@
}
RawFunction* Function::InstantiateSignatureFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -7170,7 +7229,7 @@
type_param ^= type_params.TypeAt(i);
type = type_param.bound();
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
- type = type.InstantiateFrom(instantiator_type_arguments,
+ type = type.InstantiateFrom(mode, instantiator_type_arguments,
function_type_arguments,
num_free_fun_type_params, NULL, space);
// A returned null type indicates a failed instantiation in dead code
@@ -7206,7 +7265,7 @@
type = result_type();
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
- type = type.InstantiateFrom(instantiator_type_arguments,
+ type = type.InstantiateFrom(mode, instantiator_type_arguments,
function_type_arguments,
num_free_fun_type_params, NULL, space);
// A returned null type indicates a failed instantiation in dead code that
@@ -7224,7 +7283,7 @@
for (intptr_t i = 0; i < num_params; i++) {
type = ParameterTypeAt(i);
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
- type = type.InstantiateFrom(instantiator_type_arguments,
+ type = type.InstantiateFrom(mode, instantiator_type_arguments,
function_type_arguments,
num_free_fun_type_params, NULL, space);
// A returned null type indicates a failed instantiation in dead code that
@@ -7247,7 +7306,8 @@
// of the type of the specified parameter of the other function (i.e. check
// parameter contravariance).
// Note that types marked as covariant are already dealt with in the front-end.
-bool Function::IsContravariantParameter(intptr_t parameter_position,
+bool Function::IsContravariantParameter(NNBDMode mode,
+ intptr_t parameter_position,
const Function& other,
intptr_t other_parameter_position,
Heap::Space space) const {
@@ -7258,7 +7318,7 @@
}
const AbstractType& other_param_type =
AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
- return other_param_type.IsSubtypeOf(param_type, space);
+ return other_param_type.IsSubtypeOf(mode, param_type, space);
}
bool Function::HasSameTypeParametersAndBounds(const Function& other) const {
@@ -7295,7 +7355,13 @@
return true;
}
-bool Function::IsSubtypeOf(const Function& other, Heap::Space space) const {
+bool Function::IsSubtypeOf(NNBDMode mode,
+ const Function& other,
+ Heap::Space space) const {
+ if (mode != NNBDMode::kLegacy) {
+ // TODO(regis): Check required named parameters.
+ UNIMPLEMENTED();
+ }
const intptr_t num_fixed_params = num_fixed_parameters();
const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
const intptr_t num_opt_named_params = NumOptionalNamedParameters();
@@ -7328,7 +7394,7 @@
// 'void Function()' is a subtype of 'Object Function()'.
if (!other_res_type.IsTopType()) {
const AbstractType& res_type = AbstractType::Handle(zone, result_type());
- if (!res_type.IsSubtypeOf(other_res_type, space)) {
+ if (!res_type.IsSubtypeOf(mode, other_res_type, space)) {
return false;
}
}
@@ -7336,7 +7402,7 @@
for (intptr_t i = 0; i < (other_num_fixed_params - other_num_ignored_params +
other_num_opt_pos_params);
i++) {
- if (!IsContravariantParameter(i + num_ignored_params, other,
+ if (!IsContravariantParameter(mode, i + num_ignored_params, other,
i + other_num_ignored_params, space)) {
return false;
}
@@ -7363,7 +7429,7 @@
ASSERT(String::Handle(zone, ParameterNameAt(j)).IsSymbol());
if (ParameterNameAt(j) == other_param_name.raw()) {
found_param_name = true;
- if (!IsContravariantParameter(j, other, i, space)) {
+ if (!IsContravariantParameter(mode, j, other, i, space)) {
return false;
}
break;
@@ -9290,8 +9356,8 @@
for (intptr_t i = path.length() - 2; (i >= 0) && !type.IsInstantiated();
i--) {
args = path[i]->arguments();
- type = type.InstantiateFrom(args, TypeArguments::null_type_arguments(),
- kAllFree,
+ type = type.InstantiateFrom(NNBDMode::kLegacy, args,
+ TypeArguments::null_type_arguments(), kAllFree,
/*instantiation_trail=*/nullptr, Heap::kNew);
}
@@ -9477,6 +9543,12 @@
DeoptimizeDependentCode();
}
+#if !defined(DART_PRECOMPILED_RUNTIME)
+void Field::set_type_test_cache(const SubtypeTestCache& cache) const {
+ StorePointer(&raw_ptr()->type_test_cache_, cache.raw());
+}
+#endif
+
bool Script::HasSource() const {
return raw_ptr()->source_ != String::null();
}
@@ -9627,33 +9699,6 @@
StorePointer(&raw_ptr()->debug_positions_, value.raw());
}
-void Script::set_yield_positions(const Array& value) const {
- StorePointer(&raw_ptr()->yield_positions_, value.raw());
-}
-
-RawArray* Script::yield_positions() const {
- return raw_ptr()->yield_positions_;
-}
-
-RawGrowableObjectArray* Script::GetYieldPositions(
- const Function& function) const {
- if (!function.IsAsyncClosure() && !function.IsAsyncGenClosure())
- return GrowableObjectArray::null();
- ASSERT(!function.is_declared_in_bytecode());
- Compiler::ComputeYieldPositions(function);
- UnorderedHashMap<SmiTraits> function_map(raw_ptr()->yield_positions_);
- const auto& key = Smi::Handle(Smi::New(function.token_pos().value()));
- intptr_t entry = function_map.FindKey(key);
- GrowableObjectArray& array = GrowableObjectArray::Handle();
- if (entry < 0) {
- array ^= GrowableObjectArray::null();
- } else {
- array ^= function_map.GetPayload(entry, 0);
- }
- function_map.Release();
- return array.raw();
-}
-
RawTypedData* Script::line_starts() const {
return raw_ptr()->line_starts_;
}
@@ -10201,9 +10246,10 @@
intptr_t bytecode_offset) const {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- AddMetadata(Object::Handle(zone, field.RawOwner()),
- String::Handle(zone, MakeFieldMetaName(thread, zone, field)),
- token_pos, kernel_offset, bytecode_offset);
+ const auto& owner = Object::Handle(zone, field.RawOwner());
+ const auto& name =
+ String::Handle(zone, MakeFieldMetaName(thread, zone, field));
+ AddMetadata(owner, name, token_pos, kernel_offset, bytecode_offset);
}
void Library::AddFunctionMetadata(const Function& func,
@@ -10212,19 +10258,20 @@
intptr_t bytecode_offset) const {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- AddMetadata(Object::Handle(zone, func.RawOwner()),
- String::Handle(zone, MakeFunctionMetaName(thread, zone, func)),
- token_pos, kernel_offset, bytecode_offset);
+ const auto& owner = Object::Handle(zone, func.RawOwner());
+ const auto& name =
+ String::Handle(zone, MakeFunctionMetaName(thread, zone, func));
+ AddMetadata(owner, name, token_pos, kernel_offset, bytecode_offset);
}
void Library::AddTypeParameterMetadata(const TypeParameter& param,
TokenPosition token_pos) const {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- AddMetadata(
- Class::Handle(zone, param.parameterized_class()),
- String::Handle(zone, MakeTypeParameterMetaName(thread, zone, param)),
- token_pos, 0, 0);
+ const auto& owner = Class::Handle(zone, param.parameterized_class());
+ const auto& name =
+ String::Handle(zone, MakeTypeParameterMetaName(thread, zone, param));
+ AddMetadata(owner, name, token_pos, 0, 0);
}
void Library::AddLibraryMetadata(const Object& tl_owner,
@@ -10308,9 +10355,8 @@
// There is no metadata for this object.
return Object::empty_array().raw();
}
- Object& metadata = Object::Handle();
- metadata = field.StaticValue();
- if (field.StaticValue() == Object::empty_array().raw()) {
+ Object& metadata = Object::Handle(field.StaticValue());
+ if (metadata.raw() == Object::empty_array().raw()) {
if (field.is_declared_in_bytecode()) {
metadata = kernel::BytecodeReader::ReadAnnotation(field);
} else {
@@ -10320,9 +10366,11 @@
}
if (metadata.IsArray() || metadata.IsNull()) {
ASSERT(metadata.raw() != Object::empty_array().raw());
- field.SetStaticValue(
- metadata.IsNull() ? Object::null_array() : Array::Cast(metadata),
- true);
+ if (!Compiler::IsBackgroundCompilation()) {
+ field.SetStaticValue(
+ metadata.IsNull() ? Object::null_array() : Array::Cast(metadata),
+ true);
+ }
}
}
if (metadata.IsNull()) {
@@ -11246,13 +11294,14 @@
// Note "args" is already the internal arguments with the receiver as the
// first element.
ArgumentsDescriptor args_descriptor(args_descriptor_array);
- if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
+ if (function.IsNull() ||
+ !function.AreValidArguments(NNBDMode::kLegacy, args_descriptor, NULL) ||
(respect_reflectable && !function.is_reflectable())) {
return DartEntry::InvokeNoSuchMethod(receiver, target_name, args,
args_descriptor_array);
}
- RawObject* type_error = function.DoArgumentTypesMatch(args, args_descriptor,
- instantiator_type_args);
+ RawObject* type_error = function.DoArgumentTypesMatch(
+ NNBDMode::kLegacy, args, args_descriptor, instantiator_type_args);
if (type_error != Error::null()) {
return type_error;
}
@@ -11343,7 +11392,8 @@
}
setter_type = field.type();
if (!argument_type.IsNullType() && !setter_type.IsDynamicType() &&
- !value.IsInstanceOf(setter_type, Object::null_type_arguments(),
+ !value.IsInstanceOf(NNBDMode::kLegacy, setter_type,
+ Object::null_type_arguments(),
Object::null_type_arguments())) {
return ThrowTypeError(field.token_pos(), value, setter_type, setter_name);
}
@@ -11383,7 +11433,8 @@
setter_type = setter.ParameterTypeAt(0);
if (!argument_type.IsNullType() && !setter_type.IsDynamicType() &&
- !value.IsInstanceOf(setter_type, Object::null_type_arguments(),
+ !value.IsInstanceOf(NNBDMode::kLegacy, setter_type,
+ Object::null_type_arguments(),
Object::null_type_arguments())) {
return ThrowTypeError(setter.token_pos(), value, setter_type, setter_name);
}
@@ -11428,25 +11479,26 @@
call_args.SetAt(0, getter_result);
const Array& call_args_descriptor_array =
Array::Handle(ArgumentsDescriptor::New(
- kTypeArgsLen, call_args.Length(), arg_names));
+ kTypeArgsLen, call_args.Length(), arg_names, Heap::kNew));
// Call closure.
return DartEntry::InvokeClosure(call_args, call_args_descriptor_array);
}
}
- const Array& args_descriptor_array = Array::Handle(
- ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
+ const Array& args_descriptor_array = Array::Handle(ArgumentsDescriptor::New(
+ kTypeArgsLen, args.Length(), arg_names, Heap::kNew));
ArgumentsDescriptor args_descriptor(args_descriptor_array);
const TypeArguments& type_args = Object::null_type_arguments();
- if (function.IsNull() || !function.AreValidArguments(args_descriptor, NULL) ||
+ if (function.IsNull() ||
+ !function.AreValidArguments(NNBDMode::kLegacy, args_descriptor, NULL) ||
(respect_reflectable && !function.is_reflectable())) {
return ThrowNoSuchMethod(
AbstractType::Handle(Class::Handle(toplevel_class()).RareType()),
function_name, args, arg_names, InvocationMirror::kTopLevel,
InvocationMirror::kMethod);
}
- RawObject* type_error =
- function.DoArgumentTypesMatch(args, args_descriptor, type_args);
+ RawObject* type_error = function.DoArgumentTypesMatch(
+ NNBDMode::kLegacy, args, args_descriptor, type_args);
if (type_error != Error::null()) {
return type_error;
}
@@ -11565,8 +11617,9 @@
real_arguments.SetAt(i + 1, arg);
}
- const Array& args_desc = Array::Handle(
- zone, ArgumentsDescriptor::New(num_type_args, arguments.Length()));
+ const Array& args_desc =
+ Array::Handle(zone, ArgumentsDescriptor::New(
+ num_type_args, arguments.Length(), Heap::kNew));
result = DartEntry::InvokeFunction(callee, real_arguments, args_desc);
}
@@ -11630,7 +11683,7 @@
Isolate* isolate = thread->isolate();
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
- if (FLAG_support_reload && isolate->IsReloading()) {
+ if (FLAG_support_reload && isolate->group()->IsReloading()) {
// When reloading, we need to make sure we use the original private key
// if this library previously existed.
IsolateReloadContext* reload_context = isolate->reload_context();
@@ -11864,75 +11917,6 @@
set_num_imports(num_current_imports + 1);
}
-RawObject* LibraryPrefix::LookupObject(const String& name) const {
- Array& imports = Array::Handle(this->imports());
- Object& obj = Object::Handle();
- Namespace& import = Namespace::Handle();
- Library& import_lib = Library::Handle();
- String& import_lib_url = String::Handle();
- String& first_import_lib_url = String::Handle();
- Object& found_obj = Object::Handle();
- String& found_obj_name = String::Handle();
- for (intptr_t i = 0; i < num_imports(); i++) {
- import ^= imports.At(i);
- obj = import.Lookup(name);
- if (!obj.IsNull()) {
- import_lib = import.library();
- import_lib_url = import_lib.url();
- if (found_obj.raw() != obj.raw()) {
- if (first_import_lib_url.IsNull() ||
- first_import_lib_url.StartsWith(Symbols::DartScheme())) {
- // This is the first object we found, or the
- // previously found object is exported from a Dart
- // system library. The newly found object hides the one
- // from the Dart library.
- first_import_lib_url = import_lib.url();
- found_obj = obj.raw();
- found_obj_name = found_obj.DictionaryName();
- } else if (import_lib_url.StartsWith(Symbols::DartScheme())) {
- // The newly found object is exported from a Dart system
- // library. It is hidden by the previously found object.
- // We continue to search.
- } else if (Field::IsSetterName(found_obj_name) &&
- !Field::IsSetterName(name)) {
- // We are looking for an unmangled name or a getter, but
- // the first object we found is a setter. Replace the first
- // object with the one we just found.
- first_import_lib_url = import_lib.url();
- found_obj = obj.raw();
- found_obj_name = found_obj.DictionaryName();
- } else {
- // We found two different objects with the same name.
- // Note that we need to compare the names again because
- // looking up an unmangled name can return a getter or a
- // setter. A getter name is the same as the unmangled name,
- // but a setter name is different from an unmangled name or a
- // getter name.
- if (Field::IsGetterName(found_obj_name)) {
- found_obj_name = Field::NameFromGetter(found_obj_name);
- }
- String& second_obj_name = String::Handle(obj.DictionaryName());
- if (Field::IsGetterName(second_obj_name)) {
- second_obj_name = Field::NameFromGetter(second_obj_name);
- }
- if (found_obj_name.Equals(second_obj_name)) {
- return Object::null();
- }
- }
- }
- }
- }
- return found_obj.raw();
-}
-
-RawClass* LibraryPrefix::LookupClass(const String& class_name) const {
- const Object& obj = Object::Handle(LookupObject(class_name));
- if (obj.IsClass()) {
- return Class::Cast(obj).raw();
- }
- return Class::null();
-}
-
RawLibraryPrefix* LibraryPrefix::New() {
RawObject* raw = Object::Allocate(LibraryPrefix::kClassId,
LibraryPrefix::InstanceSize(), Heap::kOld);
@@ -12817,13 +12801,14 @@
const int addr_width = (kBitsPerWord / 4) + 2;
// "*" in a printf format specifier tells it to read the field width from
// the printf argument list.
- THR_Print("%-*s\tkind \tdeopt-id\ttok-ix\ttry-ix\n", addr_width, "pc");
+ THR_Print("%-*s\tkind \tdeopt-id\ttok-ix\ttry-ix\tyield-idx\n", addr_width,
+ "pc");
}
const char* PcDescriptors::ToCString() const {
// "*" in a printf format specifier tells it to read the field width from
// the printf argument list.
-#define FORMAT "%#-*" Px "\t%s\t%" Pd "\t\t%s\t%" Pd "\n"
+#define FORMAT "%#-*" Px "\t%s\t%" Pd "\t\t%s\t%" Pd "\t%" Pd "\n"
if (Length() == 0) {
return "empty PcDescriptors\n";
}
@@ -12836,7 +12821,8 @@
while (iter.MoveNext()) {
len += Utils::SNPrint(NULL, 0, FORMAT, addr_width, iter.PcOffset(),
KindAsStr(iter.Kind()), iter.DeoptId(),
- iter.TokenPos().ToCString(), iter.TryIndex());
+ iter.TokenPos().ToCString(), iter.TryIndex(),
+ iter.YieldIndex());
}
}
// Allocate the buffer.
@@ -12845,10 +12831,10 @@
intptr_t index = 0;
Iterator iter(*this, RawPcDescriptors::kAnyKind);
while (iter.MoveNext()) {
- index +=
- Utils::SNPrint((buffer + index), (len - index), FORMAT, addr_width,
- iter.PcOffset(), KindAsStr(iter.Kind()), iter.DeoptId(),
- iter.TokenPos().ToCString(), iter.TryIndex());
+ index += Utils::SNPrint((buffer + index), (len - index), FORMAT, addr_width,
+ iter.PcOffset(), KindAsStr(iter.Kind()),
+ iter.DeoptId(), iter.TokenPos().ToCString(),
+ iter.TryIndex(), iter.YieldIndex());
}
return buffer;
#undef FORMAT
@@ -12920,22 +12906,23 @@
return "CodeSourceMap";
}
-intptr_t CompressedStackMaps::Hash() const {
- uint32_t hash = 0;
- for (intptr_t i = 0; i < payload_size(); i++) {
- uint8_t byte = Payload()[i];
+intptr_t CompressedStackMaps::Hashcode() const {
+ uint32_t hash = payload_size();
+ for (uintptr_t i = 0; i < payload_size(); i++) {
+ uint8_t byte = PayloadByte(i);
hash = CombineHashes(hash, byte);
}
return FinalizeHash(hash, kHashBits);
}
RawCompressedStackMaps* CompressedStackMaps::New(
- const GrowableArray<uint8_t>& payload) {
+ const GrowableArray<uint8_t>& payload,
+ RawCompressedStackMaps::Kind kind) {
ASSERT(Object::compressed_stackmaps_class() != Class::null());
auto& result = CompressedStackMaps::Handle();
const uintptr_t payload_size = payload.length();
- if (payload_size > kMaxInt32) {
+ if (!RawCompressedStackMaps::SizeField::is_valid(payload_size)) {
FATAL1(
"Fatal error in CompressedStackMaps::New: "
"invalid payload size %" Pu "\n",
@@ -12949,7 +12936,7 @@
CompressedStackMaps::InstanceSize(payload_size), Heap::kOld);
NoSafepointScope no_safepoint;
result ^= raw;
- result.set_payload_size(payload_size);
+ result.set_payload_size(payload_size, kind);
}
result.SetPayload(payload);
@@ -12958,19 +12945,24 @@
void CompressedStackMaps::SetPayload(
const GrowableArray<uint8_t>& payload) const {
- auto const array_length = payload.length();
+ const uintptr_t array_length = payload.length();
ASSERT(array_length <= payload_size());
NoSafepointScope no_safepoint;
uint8_t* payload_start = UnsafeMutableNonPointer(raw_ptr()->data());
- for (intptr_t i = 0; i < array_length; i++) {
+ for (uintptr_t i = 0; i < array_length; i++) {
payload_start[i] = payload.At(i);
}
}
const char* CompressedStackMaps::ToCString() const {
- ZoneTextBuffer b(Thread::Current()->zone(), 100);
- CompressedStackMapsIterator it(*this);
+ ASSERT(!IsGlobalTable());
+ auto const t = Thread::Current();
+ auto zone = t->zone();
+ ZoneTextBuffer b(zone, 100);
+ const auto& global_table = CompressedStackMaps::Handle(
+ zone, t->isolate()->object_store()->canonicalized_stack_map_entries());
+ CompressedStackMapsIterator it(*this, global_table);
bool first_entry = true;
while (it.MoveNext()) {
if (first_entry) {
@@ -12979,7 +12971,7 @@
b.AddString("\n");
}
b.Printf("0x%08x: ", it.pc_offset());
- for (intptr_t i = 0, n = it.length(); i < n; i++) {
+ for (intptr_t i = 0, n = it.Length(); i < n; i++) {
b.AddString(it.IsObject(i) ? "1" : "0");
}
}
@@ -13015,25 +13007,28 @@
const RawLocalVarDescriptors::VarInfoKind kind = info.kind();
const int32_t index = info.index();
if (kind == RawLocalVarDescriptors::kContextLevel) {
- return Utils::SNPrint(buffer, len, "%2" Pd
- " %-13s level=%-3d"
- " begin=%-3d end=%d\n",
+ return Utils::SNPrint(buffer, len,
+ "%2" Pd
+ " %-13s level=%-3d"
+ " begin=%-3d end=%d\n",
i, LocalVarDescriptors::KindToCString(kind), index,
static_cast<int>(info.begin_pos.value()),
static_cast<int>(info.end_pos.value()));
} else if (kind == RawLocalVarDescriptors::kContextVar) {
return Utils::SNPrint(
- buffer, len, "%2" Pd
- " %-13s level=%-3d index=%-3d"
- " begin=%-3d end=%-3d name=%s\n",
+ buffer, len,
+ "%2" Pd
+ " %-13s level=%-3d index=%-3d"
+ " begin=%-3d end=%-3d name=%s\n",
i, LocalVarDescriptors::KindToCString(kind), info.scope_id, index,
static_cast<int>(info.begin_pos.Pos()),
static_cast<int>(info.end_pos.Pos()), var_name.ToCString());
} else {
return Utils::SNPrint(
- buffer, len, "%2" Pd
- " %-13s scope=%-3d index=%-3d"
- " begin=%-3d end=%-3d name=%s\n",
+ buffer, len,
+ "%2" Pd
+ " %-13s scope=%-3d index=%-3d"
+ " begin=%-3d end=%-3d name=%s\n",
i, LocalVarDescriptors::KindToCString(kind), info.scope_id, index,
static_cast<int>(info.begin_pos.Pos()),
static_cast<int>(info.end_pos.Pos()), var_name.ToCString());
@@ -14552,13 +14547,28 @@
StorePointer(&raw_ptr()->compressed_stackmaps_, maps.raw());
}
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
-void Code::set_variables(const Smi& smi) const {
- StorePointer(&raw_ptr()->catch_entry_.variables_, smi.raw());
+#if !defined(DART_PRECOMPILED_RUNTIME)
+intptr_t Code::num_variables() const {
+ ASSERT(!FLAG_precompiled_mode);
+ return Smi::Value(Smi::RawCast(raw_ptr()->catch_entry_));
}
-#else
+void Code::set_num_variables(intptr_t num_variables) const {
+ ASSERT(!FLAG_precompiled_mode);
+ // Object::RawCast is needed for StorePointer template argument resolution.
+ StorePointer(&raw_ptr()->catch_entry_,
+ Object::RawCast(Smi::New(num_variables)));
+}
+#endif
+
+#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
+RawTypedData* Code::catch_entry_moves_maps() const {
+ ASSERT(FLAG_precompiled_mode);
+ return TypedData::RawCast(raw_ptr()->catch_entry_);
+}
void Code::set_catch_entry_moves_maps(const TypedData& maps) const {
- StorePointer(&raw_ptr()->catch_entry_.catch_entry_moves_maps_, maps.raw());
+ ASSERT(FLAG_precompiled_mode);
+ // Object::RawCast is needed for StorePointer template argument resolution.
+ StorePointer(&raw_ptr()->catch_entry_, Object::RawCast(maps.raw()));
}
#endif
@@ -15191,6 +15201,18 @@
StoreNonPointer(&raw_ptr()->unchecked_entry_point_, raw_ptr()->entry_point_);
}
+void Code::InitializeCachedEntryPointsFrom(RawCode* code,
+ RawInstructions* instructions) {
+ NoSafepointScope _;
+ code->ptr()->entry_point_ = Instructions::EntryPoint(instructions);
+ code->ptr()->monomorphic_entry_point_ =
+ Instructions::MonomorphicEntryPoint(instructions);
+ code->ptr()->unchecked_entry_point_ =
+ Instructions::UncheckedEntryPoint(instructions);
+ code->ptr()->monomorphic_unchecked_entry_point_ =
+ Instructions::MonomorphicUncheckedEntryPoint(instructions);
+}
+
void Code::SetActiveInstructions(const Instructions& instructions) const {
#if defined(DART_PRECOMPILED_RUNTIME)
UNREACHABLE();
@@ -15199,15 +15221,7 @@
// RawInstructions are never allocated in New space and hence a
// store buffer update is not needed here.
StorePointer(&raw_ptr()->active_instructions_, instructions.raw());
- StoreNonPointer(&raw_ptr()->entry_point_,
- Instructions::EntryPoint(instructions.raw()));
- StoreNonPointer(&raw_ptr()->monomorphic_entry_point_,
- Instructions::MonomorphicEntryPoint(instructions.raw()));
- StoreNonPointer(&raw_ptr()->unchecked_entry_point_,
- Instructions::UncheckedEntryPoint(instructions.raw()));
- StoreNonPointer(
- &raw_ptr()->monomorphic_unchecked_entry_point_,
- Instructions::MonomorphicUncheckedEntryPoint(instructions.raw()));
+ Code::InitializeCachedEntryPointsFrom(raw(), instructions.raw());
#endif
}
@@ -15253,7 +15267,7 @@
reader.DumpInlineIntervals(PayloadStart());
}
-void Code::DumpSourcePositions() const {
+void Code::DumpSourcePositions(bool relative_addresses) const {
const CodeSourceMap& map = CodeSourceMap::Handle(code_source_map());
if (map.IsNull()) {
// Stub code.
@@ -15262,7 +15276,7 @@
const Array& id_map = Array::Handle(inlined_id_to_function());
const Function& root = Function::Handle(function());
CodeSourceMapReader reader(map, id_map, root);
- reader.DumpSourcePositions(PayloadStart());
+ reader.DumpSourcePositions(relative_addresses ? 0 : PayloadStart());
}
bool Code::VerifyBSSRelocations() const {
@@ -16308,7 +16322,7 @@
const Array& args = Array::Handle(zone, Array::New(kNumArgs));
args.SetAt(0, *this);
const Array& args_descriptor = Array::Handle(
- zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length()));
+ zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), Heap::kNew));
return InvokeInstanceFunction(*this, function, internal_getter_name, args,
args_descriptor, respect_reflectable,
@@ -16354,7 +16368,7 @@
args.SetAt(0, *this);
args.SetAt(1, value);
const Array& args_descriptor = Array::Handle(
- zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length()));
+ zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), Heap::kNew));
return InvokeInstanceFunction(*this, setter, internal_setter_name, args,
args_descriptor, respect_reflectable,
@@ -16379,8 +16393,9 @@
// TODO(regis): Support invocation of generic functions with type arguments.
const int kTypeArgsLen = 0;
- const Array& args_descriptor = Array::Handle(
- zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length(), arg_names));
+ const Array& args_descriptor =
+ Array::Handle(zone, ArgumentsDescriptor::New(kTypeArgsLen, args.Length(),
+ arg_names, Heap::kNew));
TypeArguments& type_args = TypeArguments::Handle(zone);
if (klass.NumTypeArguments() > 0) {
@@ -16402,7 +16417,8 @@
const Array& getter_args = Array::Handle(zone, Array::New(kNumArgs));
getter_args.SetAt(0, *this);
const Array& getter_args_descriptor = Array::Handle(
- zone, ArgumentsDescriptor::New(kTypeArgsLen, getter_args.Length()));
+ zone, ArgumentsDescriptor::New(kTypeArgsLen, getter_args.Length(),
+ Heap::kNew));
const Object& getter_result = Object::Handle(
zone, InvokeInstanceFunction(*this, function, getter_name,
getter_args, getter_args_descriptor,
@@ -16656,7 +16672,10 @@
if (cls.NumTypeArguments() > 0) {
type_arguments = GetTypeArguments();
}
- type = Type::New(cls, type_arguments, TokenPosition::kNoSource, space);
+ // TODO(regis): The runtime type of a non-null instance should be
+ // non-nullable instead of legacy. Revisit.
+ type = Type::New(cls, type_arguments, TokenPosition::kNoSource,
+ Nullability::kLegacy, space);
type.SetIsFinalized();
type ^= type.Canonicalize();
}
@@ -16683,12 +16702,16 @@
}
bool Instance::IsInstanceOf(
+ NNBDMode mode,
const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments) const {
ASSERT(other.IsFinalized());
ASSERT(!other.IsDynamicType());
ASSERT(!other.IsTypeRef()); // Must be dereferenced at compile time.
+ if (mode != NNBDMode::kLegacy) {
+ UNIMPLEMENTED();
+ }
if (other.IsVoidType()) {
return true;
}
@@ -16703,8 +16726,8 @@
AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
if (!other.IsInstantiated()) {
instantiated_other = other.InstantiateFrom(
- other_instantiator_type_arguments, other_function_type_arguments,
- kAllFree, NULL, Heap::kOld);
+ mode, other_instantiator_type_arguments,
+ other_function_type_arguments, kAllFree, NULL, Heap::kOld);
if (instantiated_other.IsTypeRef()) {
instantiated_other = TypeRef::Cast(instantiated_other).type();
}
@@ -16713,7 +16736,7 @@
return true;
}
}
- if (IsFutureOrInstanceOf(zone, instantiated_other)) {
+ if (IsFutureOrInstanceOf(zone, mode, instantiated_other)) {
return true;
}
if (!instantiated_other.IsFunctionType()) {
@@ -16723,7 +16746,7 @@
Function::Handle(zone, Type::Cast(instantiated_other).signature());
const Function& sig_fun =
Function::Handle(Closure::Cast(*this).GetInstantiatedSignature(zone));
- return sig_fun.IsSubtypeOf(other_signature, Heap::kOld);
+ return sig_fun.IsSubtypeOf(mode, other_signature, Heap::kOld);
}
TypeArguments& type_arguments = TypeArguments::Handle(zone);
if (cls.NumTypeArguments() > 0) {
@@ -16745,7 +16768,7 @@
AbstractType& instantiated_other = AbstractType::Handle(zone, other.raw());
if (!other.IsInstantiated()) {
instantiated_other = other.InstantiateFrom(
- other_instantiator_type_arguments, other_function_type_arguments,
+ mode, other_instantiator_type_arguments, other_function_type_arguments,
kAllFree, NULL, Heap::kOld);
if (instantiated_other.IsTypeRef()) {
instantiated_other = TypeRef::Cast(instantiated_other).type();
@@ -16763,16 +16786,17 @@
ASSERT(cls.IsNullClass());
// As of Dart 2.0, the null instance and Null type are handled differently.
// We already checked other for dynamic and void.
- if (IsFutureOrInstanceOf(zone, instantiated_other)) {
+ if (IsFutureOrInstanceOf(zone, mode, instantiated_other)) {
return true;
}
return other_class.IsNullClass() || other_class.IsObjectClass();
}
- return Class::IsSubtypeOf(cls, type_arguments, other_class,
+ return Class::IsSubtypeOf(mode, cls, type_arguments, other_class,
other_type_arguments, Heap::kOld);
}
bool Instance::IsFutureOrInstanceOf(Zone* zone,
+ NNBDMode mode,
const AbstractType& other) const {
if (other.IsType() &&
Class::Handle(zone, other.type_class()).IsFutureOrClass()) {
@@ -16792,13 +16816,13 @@
if (!type_arguments.IsNull()) {
const AbstractType& type_arg =
AbstractType::Handle(zone, type_arguments.TypeAt(0));
- if (type_arg.IsSubtypeOf(other_type_arg, Heap::kOld)) {
+ if (type_arg.IsSubtypeOf(mode, other_type_arg, Heap::kOld)) {
return true;
}
}
}
// Retry the IsInstanceOf function after unwrapping type arg of FutureOr.
- if (IsInstanceOf(other_type_arg, Object::null_type_arguments(),
+ if (IsInstanceOf(mode, other_type_arg, Object::null_type_arguments(),
Object::null_type_arguments())) {
return true;
}
@@ -16896,6 +16920,14 @@
return reinterpret_cast<RawInstance*>(raw);
}
+RawInstance* Instance::NewFromCidAndSize(SharedClassTable* shared_class_table,
+ classid_t cid) {
+ const intptr_t instance_size = shared_class_table->SizeAt(cid);
+ ASSERT(instance_size > 0);
+ RawObject* raw = Object::Allocate(cid, instance_size, Heap::kNew);
+ return reinterpret_cast<RawInstance*>(raw);
+}
+
bool Instance::IsValidFieldOffset(intptr_t offset) const {
Thread* thread = Thread::Current();
REUSABLE_CLASS_HANDLESCOPE(thread);
@@ -17010,7 +17042,62 @@
Nullability AbstractType::nullability() const {
// AbstractType is an abstract class.
UNREACHABLE();
- return kNullable;
+ return Nullability::kNullable;
+}
+
+RawAbstractType* AbstractType::CheckInstantiatedNullability(
+ NNBDMode mode,
+ const TypeParameter& type_param,
+ Heap::Space space) const {
+ Nullability result_nullability;
+ const Nullability arg_nullability = nullability();
+ if (mode == NNBDMode::kOptedIn) {
+ const Nullability var_nullability = type_param.nullability();
+ // Adjust nullability of result 'arg' instantiated from 'var' (x throws).
+ // arg/var ! ? * %
+ // ! ! ? * !
+ // ? x ? ? ?
+ // * * ? * *
+ // % x ? * %
+ if (var_nullability == Nullability::kNonNullable &&
+ (arg_nullability == Nullability::kNullable ||
+ arg_nullability == Nullability::kUndetermined)) {
+ const String& error =
+ String::Handle(String::New("non-nullable type parameter"));
+ Exceptions::CreateAndThrowTypeError(TokenPosition::kNoSource, *this,
+ type_param, error);
+ UNREACHABLE();
+ }
+ if (var_nullability == Nullability::kNullable ||
+ arg_nullability == Nullability::kNullable) {
+ result_nullability = Nullability::kNullable;
+ } else if (var_nullability == Nullability::kLegacy ||
+ arg_nullability == Nullability::kLegacy) {
+ result_nullability = Nullability::kLegacy;
+ } else {
+ result_nullability = arg_nullability;
+ }
+ } else {
+ const classid_t cid = type_class_id();
+ if (cid == kDynamicCid || cid == kVoidCid || cid == kNeverCid ||
+ cid == kNullCid) {
+ // Do not force result to kLegacy.
+ return raw();
+ }
+ result_nullability = Nullability::kLegacy;
+ }
+ if (arg_nullability == result_nullability) {
+ return raw();
+ }
+ if (IsType()) {
+ return Type::Cast(*this).ToNullability(result_nullability, space);
+ }
+ if (IsTypeParameter()) {
+ return TypeParameter::Cast(*this).ToNullability(result_nullability, space);
+ }
+ // TODO(regis): TypeRefs are problematic, since changing the nullability of
+ // a type by cloning it may break the graph of a recursive type.
+ UNREACHABLE();
}
bool AbstractType::IsInstantiated(Genericity genericity,
@@ -17056,6 +17143,7 @@
}
RawAbstractType* AbstractType::InstantiateFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -17192,8 +17280,21 @@
return Symbols::FromConcatAll(thread, pieces);
}
-// Keep in sync with Nullability enum in runtime/vm/object.h.
-static const char* nullability_suffix[4] = {"%", "?", "", "*"};
+static const String& NullabilitySuffix(Nullability value) {
+ // Keep in sync with Nullability enum in runtime/vm/object.h.
+ switch (value) {
+ case Nullability::kUndetermined:
+ return Symbols::Percent();
+ case Nullability::kNullable:
+ return Symbols::QuestionMark();
+ case Nullability::kNonNullable:
+ return Symbols::Empty();
+ case Nullability::kLegacy:
+ return Symbols::Star();
+ default:
+ UNREACHABLE();
+ }
+}
RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
ASSERT(name_visibility != kScrubbedName);
@@ -17203,7 +17304,7 @@
if (FLAG_show_nullability) {
return Symbols::FromConcat(
thread, String::Handle(zone, TypeParameter::Cast(*this).name()),
- String::Handle(zone, String::New(nullability_suffix[nullability()])));
+ NullabilitySuffix(nullability()));
}
return TypeParameter::Cast(*this).name();
}
@@ -17221,8 +17322,7 @@
return Symbols::FromConcat(
thread,
String::Handle(zone, signature_function.UserVisibleSignature()),
- String::Handle(zone,
- String::New(nullability_suffix[nullability()])));
+ NullabilitySuffix(nullability()));
}
return signature_function.UserVisibleSignature();
}
@@ -17232,10 +17332,9 @@
if (!IsFinalized() || IsBeingFinalized()) {
// TODO(regis): Check if this is dead code.
if (FLAG_show_nullability) {
- return Symbols::FromConcat(
- thread, String::Handle(zone, class_name.raw()),
- String::Handle(zone,
- String::New(nullability_suffix[nullability()])));
+ return Symbols::FromConcat(thread,
+ String::Handle(zone, class_name.raw()),
+ NullabilitySuffix(nullability()));
}
return class_name.raw();
}
@@ -17278,8 +17377,7 @@
pieces.Add(args_name);
}
if (FLAG_show_nullability) {
- pieces.Add(
- String::Handle(zone, String::New(nullability_suffix[nullability()])));
+ pieces.Add(NullabilitySuffix(nullability()));
}
// The name is only used for type checking and debugging purposes.
// Unless profiling data shows otherwise, it is not worth caching the name in
@@ -17296,29 +17394,13 @@
return IsTypeRef() && (TypeRef::Cast(*this).type() == AbstractType::null());
}
-bool AbstractType::IsDynamicType() const {
- return type_class_id() == kDynamicCid;
-}
-
-bool AbstractType::IsVoidType() const {
- return type_class_id() == kVoidCid;
-}
-
-bool AbstractType::IsNeverType() const {
- return type_class_id() == kNeverCid;
-}
-
-bool AbstractType::IsObjectType() const {
- return type_class_id() == kInstanceCid;
-}
-
-bool AbstractType::IsTopType(NNBDMode mode) const {
+// TODO(regis): IsTopType is not yet nullability aware.
+bool AbstractType::IsTopType() const {
const classid_t cid = type_class_id();
if (cid == kIllegalCid) {
return false;
}
- if (cid == kDynamicCid || cid == kVoidCid ||
- (cid == kInstanceCid && (mode != kStrong || IsNullable()))) {
+ if (cid == kDynamicCid || cid == kVoidCid || cid == kInstanceCid) {
return true;
}
// FutureOr<T> where T is a top type behaves as a top type.
@@ -17332,21 +17414,13 @@
TypeArguments::Handle(zone, arguments());
const AbstractType& type_arg =
AbstractType::Handle(zone, type_arguments.TypeAt(0));
- if (type_arg.IsTopType(mode)) {
+ if (type_arg.IsTopType()) {
return true;
}
}
return false;
}
-bool AbstractType::IsNullType() const {
- return type_class_id() == kNullCid;
-}
-
-bool AbstractType::IsBoolType() const {
- return type_class_id() == kBoolCid;
-}
-
bool AbstractType::IsIntType() const {
return HasTypeClass() &&
(type_class() == Type::Handle(Type::IntType()).type_class());
@@ -17375,14 +17449,6 @@
(type_class() == Type::Handle(Type::Int32x4()).type_class());
}
-bool AbstractType::IsNumberType() const {
- return type_class_id() == kNumberCid;
-}
-
-bool AbstractType::IsSmiType() const {
- return type_class_id() == kSmiCid;
-}
-
bool AbstractType::IsStringType() const {
return HasTypeClass() &&
(type_class() == Type::Handle(Type::StringType()).type_class());
@@ -17403,22 +17469,23 @@
return HasTypeClass() && type_class_id() == kFfiPointerCid;
}
-bool AbstractType::IsSubtypeOf(const AbstractType& other,
+bool AbstractType::IsSubtypeOf(NNBDMode mode,
+ const AbstractType& other,
Heap::Space space) const {
ASSERT(IsFinalized());
ASSERT(other.IsFinalized());
- // Any type is a subtype of (and is more specific than) Object and dynamic.
- // As of Dart 2.0, the Null type is a subtype of (and is more specific than)
- // any type.
- if (other.IsTopType() || IsNullType()) {
+ if (FLAG_strong_non_nullable_type_checks) {
+ UNIMPLEMENTED();
+ }
+ if (other.IsTopType() || IsNullType() || IsNeverType()) {
return true;
}
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
// Type parameters cannot be handled by Class::IsSubtypeOf().
// When comparing two uninstantiated function types, one returning type
- // parameter K, the other returning type parameter V, we cannot assume that K
- // is a subtype of V, or vice versa. We only return true if K equals V, as
+ // parameter K, the other returning type parameter V, we cannot assume that
+ // K is a subtype of V, or vice versa. We only return true if K equals V, as
// defined by TypeParameter::Equals.
// The same rule applies when checking the upper bound of a still
// uninstantiated type at compile time. Returning false will defer the test
@@ -17437,11 +17504,11 @@
if (type_param.IsFunctionTypeParameter() &&
other_type_param.IsFunctionTypeParameter() &&
type_param.IsFinalized() && other_type_param.IsFinalized()) {
- // To be compatible, the function type parameters should be declared at
- // the same position in the generic function. Their index therefore
+ // To be compatible, the function type parameters should be declared
+ // at the same position in the generic function. Their index therefore
// needs adjustement before comparison.
- // Example: 'foo<F>(bar<B>(B b)) { }' and 'baz<Z>(Z z) { }', baz can be
- // assigned to bar, although B has index 1 and Z index 0.
+ // Example: 'foo<F>(bar<B>(B b)) { }' and 'baz<Z>(Z z) { }', baz can
+ // be assigned to bar, although B has index 1 and Z index 0.
const Function& sig_fun =
Function::Handle(zone, type_param.parameterized_function());
const Function& other_sig_fun =
@@ -17455,22 +17522,22 @@
}
}
const AbstractType& bound = AbstractType::Handle(zone, type_param.bound());
- // We may be checking bounds at finalization time and can encounter
- // a still unfinalized bound. Finalizing the bound here may lead to cycles.
+ // We may be checking bounds at finalization time and can encounter a
+ // still unfinalized bound. Finalizing the bound here may lead to cycles.
if (!bound.IsFinalized()) {
- return false; // TODO(regis): Return "maybe after instantiation".
+ return false;
}
- if (bound.IsSubtypeOf(other, space)) {
+ if (bound.IsSubtypeOf(mode, other, space)) {
return true;
}
// Apply additional subtyping rules if 'other' is 'FutureOr'.
- if (IsSubtypeOfFutureOr(zone, other, space)) {
+ if (IsSubtypeOfFutureOr(zone, mode, other, space)) {
return true;
}
- return false; // TODO(regis): We should return "maybe after instantiation".
+ return false;
}
if (other.IsTypeParameter()) {
- return false; // TODO(regis): We should return "maybe after instantiation".
+ return false;
}
const Class& type_cls = Class::Handle(zone, type_class());
const Class& other_type_cls = Class::Handle(zone, other.type_class());
@@ -17486,14 +17553,14 @@
// Check for two function types.
const Function& fun =
Function::Handle(zone, Type::Cast(*this).signature());
- return fun.IsSubtypeOf(other_fun, space);
+ return fun.IsSubtypeOf(mode, other_fun, space);
}
if (other.IsFunctionType() && !other_type_cls.IsTypedefClass()) {
// [this] is not a function type. Therefore, non-function type [this]
// cannot be a subtype of function type [other], unless [other] is not
// only a function type, but also a named typedef.
- // Indeed a typedef also behaves as a regular class-based type (with type
- // arguments when generic).
+ // Indeed a typedef also behaves as a regular class-based type (with
+ // type arguments when generic).
// This check is needed to avoid falling through to class-based type
// tests, which yield incorrect result if [this] = _Closure class,
// and [other] is a function type, because class of a function type is
@@ -17503,17 +17570,18 @@
}
if (IsFunctionType()) {
// Apply additional subtyping rules if 'other' is 'FutureOr'.
- if (IsSubtypeOfFutureOr(zone, other, space)) {
+ if (IsSubtypeOfFutureOr(zone, mode, other, space)) {
return true;
}
return false;
}
return Class::IsSubtypeOf(
- type_cls, TypeArguments::Handle(zone, arguments()), other_type_cls,
+ mode, type_cls, TypeArguments::Handle(zone, arguments()), other_type_cls,
TypeArguments::Handle(zone, other.arguments()), space);
}
bool AbstractType::IsSubtypeOfFutureOr(Zone* zone,
+ NNBDMode mode,
const AbstractType& other,
Heap::Space space) const {
if (other.IsType() &&
@@ -17533,7 +17601,7 @@
return true;
}
// Retry the IsSubtypeOf check after unwrapping type arg of FutureOr.
- if (IsSubtypeOf(other_type_arg, space)) {
+ if (IsSubtypeOf(mode, other_type_arg, space)) {
return true;
}
}
@@ -17640,20 +17708,35 @@
return Isolate::Current()->object_store()->type_type();
}
-RawType* Type::NewNonParameterizedType(const Class& type_class) {
+RawType* Type::NewNonParameterizedType(const Class& type_class,
+ Nullability nullability) {
ASSERT(type_class.NumTypeArguments() == 0);
+ if (type_class.IsNullClass()) {
+ // Ignore requested nullability (e.g. by mirrors).
+ return Type::NullType();
+ }
+ if (type_class.IsDynamicClass()) {
+ return Type::DynamicType();
+ }
+ if (type_class.IsVoidClass()) {
+ return Type::VoidType();
+ }
+ if (type_class.IsNeverClass()) {
+ return Type::NeverType();
+ }
// It is too early to use the class finalizer, as type_class may not be named
// yet, so do not call DeclarationType().
Type& type = Type::Handle(type_class.declaration_type());
if (type.IsNull()) {
type = Type::New(Class::Handle(type_class.raw()),
- Object::null_type_arguments(), TokenPosition::kNoSource);
+ Object::null_type_arguments(), TokenPosition::kNoSource,
+ Nullability::kLegacy);
type.SetIsFinalized();
type ^= type.Canonicalize();
type_class.set_declaration_type(type);
}
ASSERT(type.IsFinalized());
- return type.raw();
+ return type.ToNullability(nullability, Heap::kOld);
}
void Type::SetIsFinalized() const {
@@ -17757,6 +17840,7 @@
}
RawAbstractType* Type::InstantiateFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -17779,7 +17863,7 @@
// parameterization of a generic typedef. They are otherwise ignored.
ASSERT(type_arguments.Length() == cls.NumTypeArguments());
type_arguments = type_arguments.InstantiateFrom(
- instantiator_type_arguments, function_type_arguments,
+ mode, instantiator_type_arguments, function_type_arguments,
num_free_fun_type_params, instantiation_trail, space);
// A returned empty_type_arguments indicates a failed instantiation in dead
// code that must be propagated up to the caller, the optimizing compiler.
@@ -17789,8 +17873,8 @@
}
// This uninstantiated type is not modified, as it can be instantiated
// with different instantiators. Allocate a new instantiated version of it.
- const Type& instantiated_type =
- Type::Handle(zone, Type::New(cls, type_arguments, token_pos(), space));
+ const Type& instantiated_type = Type::Handle(
+ zone, Type::New(cls, type_arguments, token_pos(), nullability(), space));
// For a function type, possibly instantiate and set its signature.
if (!sig_fun.IsNull()) {
// If we are finalizing a typedef, do not yet instantiate its signature,
@@ -17801,7 +17885,7 @@
// A generic typedef may actually declare an instantiated signature.
if (!sig_fun.HasInstantiatedSignature(kAny, num_free_fun_type_params)) {
sig_fun = sig_fun.InstantiateSignatureFrom(
- instantiator_type_arguments, function_type_arguments,
+ mode, instantiator_type_arguments, function_type_arguments,
num_free_fun_type_params, space);
// A returned null signature indicates a failed instantiation in dead
// code that must be propagated up to the caller, the optimizing
@@ -17991,17 +18075,18 @@
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
- if ((type_class_id() == kVoidCid) && (isolate != Dart::vm_isolate())) {
- ASSERT(Object::void_type().IsCanonical());
- return Object::void_type().raw();
- }
-
- if ((type_class_id() == kDynamicCid) && (isolate != Dart::vm_isolate())) {
+ const classid_t cid = type_class_id();
+ if (cid == kDynamicCid) {
ASSERT(Object::dynamic_type().IsCanonical());
return Object::dynamic_type().raw();
}
- if ((type_class_id() == kNeverCid) && (isolate != Dart::vm_isolate())) {
+ if (cid == kVoidCid) {
+ ASSERT(Object::void_type().IsCanonical());
+ return Object::void_type().raw();
+ }
+
+ if (cid == kNeverCid) {
ASSERT(Object::never_type().IsCanonical());
return Object::never_type().raw();
}
@@ -18009,8 +18094,8 @@
const Class& cls = Class::Handle(zone, type_class());
// Fast canonical lookup/registry for simple types.
- if (IsNullType() || (IsLegacy() && !cls.IsGeneric() &&
- !cls.IsClosureClass() && !cls.IsTypedefClass())) {
+ if ((IsNullType() || IsLegacy()) && !cls.IsGeneric() &&
+ !cls.IsClosureClass() && !cls.IsTypedefClass()) {
ASSERT(!IsFunctionType());
ASSERT(!IsNullType() || IsNullable());
Type& type = Type::Handle(zone, cls.declaration_type());
@@ -18127,20 +18212,27 @@
if (IsRecursive()) {
return true;
}
- if (type_class_id() == kDynamicCid) {
+ const classid_t cid = type_class_id();
+ if (cid == kDynamicCid) {
return (raw() == Object::dynamic_type().raw());
}
+ if (cid == kVoidCid) {
+ return (raw() == Object::void_type().raw());
+ }
+ if (cid == kNeverCid) {
+ return (raw() == Object::never_type().raw());
+ }
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
AbstractType& type = Type::Handle(zone);
const Class& cls = Class::Handle(zone, type_class());
// Fast canonical lookup/registry for simple types.
- if (IsNullType() || (IsLegacy() && !cls.IsGeneric() &&
- !cls.IsClosureClass() && !cls.IsTypedefClass())) {
+ if ((IsNullType() || IsLegacy()) && !cls.IsGeneric() &&
+ !cls.IsClosureClass() && !cls.IsTypedefClass()) {
ASSERT(!IsFunctionType());
- ASSERT(!IsNullType() || IsNullable());
type = cls.declaration_type();
+ ASSERT(type.IsCanonical());
return (raw() == type.raw());
}
@@ -18234,6 +18326,7 @@
RawType* Type::New(const Class& clazz,
const TypeArguments& arguments,
TokenPosition token_pos,
+ Nullability nullability,
Heap::Space space) {
Zone* Z = Thread::Current()->zone();
const Type& result = Type::Handle(Z, Type::New(space));
@@ -18242,11 +18335,7 @@
result.SetHash(0);
result.set_token_pos(token_pos);
result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated);
- if (clazz.id() == kNullCid) {
- result.set_nullability(kNullable);
- } else {
- result.set_nullability(kLegacy);
- }
+ result.set_nullability(nullability);
result.SetTypeTestingStub(
Code::Handle(Z, TypeTestingStubGenerator::DefaultCodeForType(result)));
@@ -18323,6 +18412,7 @@
}
RawTypeRef* TypeRef::InstantiateFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -18340,7 +18430,7 @@
ASSERT(!ref_type.IsNull() && !ref_type.IsTypeRef());
AbstractType& instantiated_ref_type = AbstractType::Handle();
instantiated_ref_type = ref_type.InstantiateFrom(
- instantiator_type_arguments, function_type_arguments,
+ mode, instantiator_type_arguments, function_type_arguments,
num_free_fun_type_params, instantiation_trail, space);
// A returned null type indicates a failed instantiation in dead code that
// must be propagated up to the caller, the optimizing compiler.
@@ -18454,7 +18544,7 @@
}
void TypeParameter::set_nullability(Nullability value) const {
- StoreNonPointer(&raw_ptr()->nullability_, value);
+ StoreNonPointer(&raw_ptr()->nullability_, static_cast<int8_t>(value));
}
RawTypeParameter* TypeParameter::ToNullability(Nullability value,
@@ -18554,6 +18644,7 @@
}
RawAbstractType* TypeParameter::InstantiateFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -18568,7 +18659,9 @@
if (function_type_arguments.IsNull()) {
return Type::DynamicType();
}
- return function_type_arguments.TypeAt(index());
+ const AbstractType& result =
+ AbstractType::Handle(function_type_arguments.TypeAt(index()));
+ return result.CheckInstantiatedNullability(mode, *this, space);
}
ASSERT(IsClassTypeParameter());
if (instantiator_type_arguments.IsNull()) {
@@ -18583,7 +18676,9 @@
// (see AssertAssignableInstr::Canonicalize).
return AbstractType::null();
}
- return instantiator_type_arguments.TypeAt(index());
+ const AbstractType& result =
+ AbstractType::Handle(instantiator_type_arguments.TypeAt(index()));
+ return result.CheckInstantiatedNullability(mode, *this, space);
// There is no need to canonicalize the instantiated type parameter, since all
// type arguments are canonicalized at type finalization time. It would be too
// early to canonicalize the returned type argument here, since instantiation
@@ -18653,7 +18748,7 @@
result.set_name(name);
result.set_bound(bound);
result.set_flags(0);
- result.set_nullability(kLegacy);
+ result.set_nullability(Nullability::kLegacy);
result.SetGenericCovariantImpl(is_generic_covariant_impl);
result.SetHash(0);
result.set_token_pos(token_pos);
@@ -21861,12 +21956,23 @@
}
if (num_free_params == kCurrentAndEnclosingFree ||
!sig_fun.HasInstantiatedSignature(kAny)) {
- return sig_fun.InstantiateSignatureFrom(inst_type_args, fn_type_args,
- num_free_params, Heap::kOld);
+ // TODO(regis): Instead of NNBDMode::kLegacy, use the NNBDMode of the
+ // closure's function's owner's library.
+ return sig_fun.InstantiateSignatureFrom(NNBDMode::kLegacy, inst_type_args,
+ fn_type_args, num_free_params,
+ Heap::kOld);
}
return sig_fun.raw();
}
+bool StackTrace::skip_sync_start_in_parent_stack() const {
+ return raw_ptr()->skip_sync_start_in_parent_stack;
+}
+
+void StackTrace::set_skip_sync_start_in_parent_stack(bool value) const {
+ StoreNonPointer(&raw_ptr()->skip_sync_start_in_parent_stack, value);
+}
+
intptr_t StackTrace::Length() const {
const Array& code_array = Array::Handle(raw_ptr()->code_array_);
return code_array.Length();
@@ -21927,12 +22033,14 @@
result.set_code_array(code_array);
result.set_pc_offset_array(pc_offset_array);
result.set_expand_inlined(true); // default.
+ result.set_skip_sync_start_in_parent_stack(false);
return result.raw();
}
RawStackTrace* StackTrace::New(const Array& code_array,
const Array& pc_offset_array,
const StackTrace& async_link,
+ bool skip_sync_start_in_parent_stack,
Heap::Space space) {
StackTrace& result = StackTrace::Handle();
{
@@ -21945,6 +22053,7 @@
result.set_code_array(code_array);
result.set_pc_offset_array(pc_offset_array);
result.set_expand_inlined(true); // default.
+ result.set_skip_sync_start_in_parent_stack(skip_sync_start_in_parent_stack);
return result.raw();
}
@@ -22003,8 +22112,9 @@
// Iterate through the stack frames and create C string description
// for each frame.
intptr_t frame_index = 0;
+ uint32_t frame_skip = 0;
do {
- for (intptr_t i = 0; i < stack_trace.Length(); i++) {
+ for (intptr_t i = frame_skip; i < stack_trace.Length(); i++) {
code_object = stack_trace.CodeAtFrame(i);
if (code_object.IsNull()) {
// Check for a null function, which indicates a gap in a StackOverflow
@@ -22064,6 +22174,9 @@
}
}
// Follow the link.
+ frame_skip = stack_trace.skip_sync_start_in_parent_stack()
+ ? StackTrace::kSyncAsyncCroppedFrames
+ : 0;
stack_trace = stack_trace.async_link();
} while (!stack_trace.IsNull());
@@ -22091,8 +22204,9 @@
buffer.Printf("pid: %" Pd ", tid: %" Pd ", name %s\n", OS::ProcessId(),
OSThread::ThreadIdToIntPtr(thread->id()), thread->name());
intptr_t frame_index = 0;
+ uint32_t frame_skip = 0;
do {
- for (intptr_t i = 0; i < stack_trace.Length(); i++) {
+ for (intptr_t i = frame_skip; i < stack_trace.Length(); i++) {
code = stack_trace.CodeAtFrame(i);
if (code.IsNull()) {
// Check for a null function, which indicates a gap in a StackOverflow
@@ -22134,6 +22248,9 @@
}
}
// Follow the link.
+ frame_skip = stack_trace.skip_sync_start_in_parent_stack()
+ ? StackTrace::kSyncAsyncCroppedFrames
+ : 0;
stack_trace = stack_trace.async_link();
} while (!stack_trace.IsNull());
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 4f9f92b..ba6dfb7 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -63,6 +63,7 @@
class HierarchyInfo;
class LocalScope;
class CodeStatistics;
+class IsolateGroupReloadContext;
#define REUSABLE_FORWARD_DECLARATION(name) class Reusable##name##HandleScope;
REUSABLE_HANDLE_LIST(REUSABLE_FORWARD_DECLARATION)
@@ -837,6 +838,21 @@
// The third string in the triplet is "print" if the triplet should be printed.
typedef ZoneGrowableHandlePtrArray<const String> URIs;
+// Keep in sync with package:kernel/lib/ast.dart
+enum class Nullability {
+ kUndetermined = 0,
+ kNullable = 1,
+ kNonNullable = 2,
+ kLegacy = 3,
+};
+
+// NNBD modes reflecting the status of the library performing type reification
+// or subtype tests. Weak or strong mode is independent of this mode.
+enum class NNBDMode {
+ kLegacy,
+ kOptedIn,
+};
+
class Class : public Object {
public:
enum InvocationDispatcherEntry {
@@ -935,7 +951,12 @@
// class B<T, S>
// class C<R> extends B<R, int>
// C.DeclarationType() --> C [R, int, R]
- RawType* DeclarationType() const;
+ // The declaration type is legacy by default, but another nullability
+ // variant may be requested. The first requested type gets cached in the class
+ // and subsequent nullability variants get cached in the object store.
+ // TODO(regis): Is this caching still useful or should we eliminate it?
+ RawType* DeclarationType(
+ Nullability nullability = Nullability::kLegacy) const;
static intptr_t declaration_type_offset() {
return OFFSET_OF(RawClass, declaration_type_);
@@ -1075,7 +1096,8 @@
// Returns true if the type specified by cls and type_arguments is a
// subtype of the type specified by other class and other_type_arguments.
- static bool IsSubtypeOf(const Class& cls,
+ static bool IsSubtypeOf(NNBDMode mode,
+ const Class& cls,
const TypeArguments& type_arguments,
const Class& other,
const TypeArguments& other_type_arguments,
@@ -1085,6 +1107,7 @@
// subtype of FutureOr<T> specified by other class and other_type_arguments.
// Returns false if other class is not a FutureOr.
static bool IsSubtypeOfFutureOr(Zone* zone,
+ NNBDMode mode,
const Class& cls,
const TypeArguments& type_arguments,
const Class& other,
@@ -2130,21 +2153,6 @@
friend class SnapshotWriter;
};
-// Keep in sync with package:kernel/lib/ast.dart
-enum Nullability {
- kUndetermined = 0,
- kNullable = 1,
- kNonNullable = 2,
- kLegacy = 3,
-};
-
-// Nullability aware subtype checking modes.
-enum NNBDMode {
- kUnaware,
- kWeak,
- kStrong,
-};
-
// Often used constants for number of free function type parameters.
enum {
kNoneFree = 0,
@@ -2185,7 +2193,8 @@
// function type with uninstantiated type arguments 'T' and 'R' as elements of
// its type argument vector.
// A function type is non-nullable by default.
- RawType* SignatureType(Nullability nullability = kNonNullable) const;
+ RawType* SignatureType(
+ Nullability nullability = Nullability::kNonNullable) const;
RawType* ExistingSignatureType() const;
// Update the signature type (with a canonical version).
@@ -2222,6 +2231,7 @@
// Return a new function with instantiated result and parameter types.
RawFunction* InstantiateSignatureFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -2784,6 +2794,7 @@
// Returns a TypeError if the provided arguments don't match the function
// parameter types, NULL otherwise. Assumes AreValidArguments is called first.
RawObject* DoArgumentTypesMatch(
+ NNBDMode mode,
const Array& args,
const ArgumentsDescriptor& arg_names,
const TypeArguments& instantiator_type_args) const;
@@ -2791,11 +2802,13 @@
// Returns true if the type argument count, total argument count and the names
// of optional arguments are valid for calling this function.
// Otherwise, it returns false and the reason (if error_message is not NULL).
- bool AreValidArguments(intptr_t num_type_arguments,
+ bool AreValidArguments(NNBDMode mode,
+ intptr_t num_type_arguments,
intptr_t num_arguments,
const Array& argument_names,
String* error_message) const;
- bool AreValidArguments(const ArgumentsDescriptor& args_desc,
+ bool AreValidArguments(NNBDMode mode,
+ const ArgumentsDescriptor& args_desc,
String* error_message) const;
// Fully qualified name uniquely identifying the function under gdb and during
@@ -2808,7 +2821,9 @@
// Returns true if the type of this function is a subtype of the type of
// the other function.
- bool IsSubtypeOf(const Function& other, Heap::Space space) const;
+ bool IsSubtypeOf(NNBDMode mode,
+ const Function& other,
+ Heap::Space space) const;
bool IsDispatcherOrImplicitAccessor() const {
switch (kind()) {
@@ -2909,24 +2924,24 @@
}
bool IsFfiLoad() const {
- const auto kind = MethodRecognizer::RecognizeKind(*this);
+ const auto kind = recognized_kind();
return MethodRecognizer::kFfiLoadInt8 <= kind &&
kind <= MethodRecognizer::kFfiLoadPointer;
}
bool IsFfiStore() const {
- const auto kind = MethodRecognizer::RecognizeKind(*this);
+ const auto kind = recognized_kind();
return MethodRecognizer::kFfiStoreInt8 <= kind &&
kind <= MethodRecognizer::kFfiStorePointer;
}
bool IsFfiFromAddress() const {
- const auto kind = MethodRecognizer::RecognizeKind(*this);
+ const auto kind = recognized_kind();
return kind == MethodRecognizer::kFfiFromAddress;
}
bool IsFfiGetAddress() const {
- const auto kind = MethodRecognizer::RecognizeKind(*this);
+ const auto kind = recognized_kind();
return kind == MethodRecognizer::kFfiGetAddress;
}
@@ -3253,7 +3268,8 @@
// Returns true if the type of the formal parameter at the given position in
// this function is contravariant with the type of the other formal parameter
// at the given position in the other function.
- bool IsContravariantParameter(intptr_t parameter_position,
+ bool IsContravariantParameter(NNBDMode mode,
+ intptr_t parameter_position,
const Function& other,
intptr_t other_parameter_position,
Heap::Space space) const;
@@ -3818,6 +3834,13 @@
static bool IsSetterName(const String& function_name);
static bool IsInitName(const String& function_name);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ RawSubtypeTestCache* type_test_cache() const {
+ return raw_ptr()->type_test_cache_;
+ }
+ void set_type_test_cache(const SubtypeTestCache& cache) const;
+#endif
+
private:
static void InitializeNew(const Field& result,
const String& name,
@@ -3962,12 +3985,6 @@
void set_debug_positions(const Array& value) const;
- void set_yield_positions(const Array& value) const;
-
- RawArray* yield_positions() const;
-
- RawGrowableObjectArray* GetYieldPositions(const Function& function) const;
-
RawLibrary* FindLibrary() const;
RawString* GetLine(intptr_t line_number,
Heap::Space space = Heap::kNew) const;
@@ -4268,6 +4285,10 @@
set_flags(RawLibrary::NnbdBit::update(value, raw_ptr()->flags_));
}
+ NNBDMode nnbd_mode() const {
+ return is_nnbd() ? NNBDMode::kOptedIn : NNBDMode::kLegacy;
+ }
+
RawString* PrivateName(const String& name) const;
intptr_t index() const { return raw_ptr()->index_; }
@@ -5033,16 +5054,20 @@
cur_kind_(0),
cur_deopt_id_(0),
cur_token_pos_(0),
- cur_try_index_(0) {}
+ cur_try_index_(0),
+ cur_yield_index_(RawPcDescriptors::kInvalidYieldIndex) {}
bool MoveNext() {
// Moves to record that matches kind_mask_.
while (byte_index_ < descriptors_.Length()) {
- int32_t merged_kind_try = descriptors_.DecodeInteger(&byte_index_);
+ const int32_t kind_and_metadata =
+ descriptors_.DecodeInteger(&byte_index_);
cur_kind_ =
- RawPcDescriptors::MergedKindTry::DecodeKind(merged_kind_try);
- cur_try_index_ =
- RawPcDescriptors::MergedKindTry::DecodeTryIndex(merged_kind_try);
+ RawPcDescriptors::KindAndMetadata::DecodeKind(kind_and_metadata);
+ cur_try_index_ = RawPcDescriptors::KindAndMetadata::DecodeTryIndex(
+ kind_and_metadata);
+ cur_yield_index_ = RawPcDescriptors::KindAndMetadata::DecodeYieldIndex(
+ kind_and_metadata);
cur_pc_offset_ += descriptors_.DecodeInteger(&byte_index_);
@@ -5062,6 +5087,7 @@
intptr_t DeoptId() const { return cur_deopt_id_; }
TokenPosition TokenPos() const { return TokenPosition(cur_token_pos_); }
intptr_t TryIndex() const { return cur_try_index_; }
+ intptr_t YieldIndex() const { return cur_yield_index_; }
RawPcDescriptors::Kind Kind() const {
return static_cast<RawPcDescriptors::Kind>(cur_kind_);
}
@@ -5079,7 +5105,8 @@
cur_kind_(iter.cur_kind_),
cur_deopt_id_(iter.cur_deopt_id_),
cur_token_pos_(iter.cur_token_pos_),
- cur_try_index_(iter.cur_try_index_) {}
+ cur_try_index_(iter.cur_try_index_),
+ cur_yield_index_(iter.cur_yield_index_) {}
const PcDescriptors& descriptors_;
const intptr_t kind_mask_;
@@ -5090,6 +5117,7 @@
intptr_t cur_deopt_id_;
intptr_t cur_token_pos_;
intptr_t cur_try_index_;
+ intptr_t cur_yield_index_;
};
intptr_t Length() const;
@@ -5164,18 +5192,24 @@
public:
static const intptr_t kHashBits = 30;
- intptr_t payload_size() const { return raw_ptr()->payload_size_; }
+ uintptr_t payload_size() const { return raw_ptr()->payload_size(); }
bool Equals(const CompressedStackMaps& other) const {
- if (payload_size() != other.payload_size()) return false;
+ // Both the payload size and the kind of table must match.
+ if (raw_ptr()->flags_and_size_ != other.raw_ptr()->flags_and_size_) {
+ return false;
+ }
NoSafepointScope no_safepoint;
return memcmp(raw_ptr(), other.raw_ptr(), InstanceSize(payload_size())) ==
0;
}
- intptr_t Hash() const;
+
+ // Methods to allow use with PointerKeyValueTrait to create sets of CSMs.
+ bool Equals(const CompressedStackMaps* other) const { return Equals(*other); }
+ intptr_t Hashcode() const;
static intptr_t UnroundedSize(RawCompressedStackMaps* maps) {
- return UnroundedSize(maps->ptr()->payload_size_);
+ return UnroundedSize(maps->ptr()->payload_size());
}
static intptr_t UnroundedSize(intptr_t length) {
return sizeof(RawCompressedStackMaps) + length;
@@ -5190,22 +5224,49 @@
}
private:
- // The encoding logic for CompressedStackMaps entries is in
- // CompressedStackMapsBuilder, and the decoding logic is in
- // CompressedStackMapsIterator.
- static RawCompressedStackMaps* New(const GrowableArray<uint8_t>& bytes);
+ static RawCompressedStackMaps* New(const GrowableArray<uint8_t>& bytes,
+ RawCompressedStackMaps::Kind kind);
- void set_payload_size(intptr_t payload_size) const {
- StoreNonPointer(&raw_ptr()->payload_size_, payload_size);
+ static RawCompressedStackMaps* NewInlined(
+ const GrowableArray<uint8_t>& bytes) {
+ return New(bytes, RawCompressedStackMaps::kInlined);
}
+ static RawCompressedStackMaps* NewUsingTable(
+ const GrowableArray<uint8_t>& bytes) {
+ return New(bytes, RawCompressedStackMaps::kUsesTable);
+ }
+ static RawCompressedStackMaps* NewGlobalTable(
+ const GrowableArray<uint8_t>& bytes) {
+ return New(bytes, RawCompressedStackMaps::kGlobalTable);
+ }
+
+ void set_payload_size(intptr_t payload_size,
+ RawCompressedStackMaps::Kind kind) const {
+ ASSERT(RawCompressedStackMaps::SizeField::is_valid(payload_size));
+ const uint32_t encoded_fields =
+ RawCompressedStackMaps::KindField::encode(kind) |
+ RawCompressedStackMaps::SizeField::encode(payload_size);
+ StoreNonPointer(&raw_ptr()->flags_and_size_, encoded_fields);
+ }
+
+ bool UsesGlobalTable() const {
+ return !IsNull() && raw_ptr()->UsesGlobalTable();
+ }
+ bool IsGlobalTable() const { return !IsNull() && raw_ptr()->IsGlobalTable(); }
const uint8_t* Payload() const { return raw_ptr()->data(); }
void SetPayload(const GrowableArray<uint8_t>& payload) const;
+ uint8_t PayloadByte(uintptr_t offset) const {
+ ASSERT(offset >= 0 && offset < payload_size());
+ return raw_ptr()->data()[offset];
+ }
FINAL_HEAP_OBJECT_IMPLEMENTATION(CompressedStackMaps, Object);
friend class Class;
friend class CompressedStackMapsBuilder;
friend class CompressedStackMapsIterator;
+ friend class ProgramVisitor;
+ friend class StackMapEntry;
};
class ExceptionHandlers : public Object {
@@ -5398,13 +5459,13 @@
}
void set_deopt_info_array(const Array& array) const;
-#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
- RawSmi* variables() const { return raw_ptr()->catch_entry_.variables_; }
- void set_variables(const Smi& smi) const;
-#else
- RawTypedData* catch_entry_moves_maps() const {
- return raw_ptr()->catch_entry_.catch_entry_moves_maps_;
- }
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ intptr_t num_variables() const;
+ void set_num_variables(intptr_t num_variables) const;
+#endif
+
+#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
+ RawTypedData* catch_entry_moves_maps() const;
void set_catch_entry_moves_maps(const TypedData& maps) const;
#endif
@@ -5540,7 +5601,7 @@
NOT_IN_PRODUCT(void PrintJSONInlineIntervals(JSONObject* object) const);
void DumpInlineIntervals() const;
- void DumpSourcePositions() const;
+ void DumpSourcePositions(bool relative_addresses = false) const;
RawLocalVarDescriptors* var_descriptors() const {
#if defined(PRODUCT)
@@ -5737,6 +5798,10 @@
#endif
}
+ // Initializes 4 cached entrypoint addresses in 'code' from 'instructions'.
+ static void InitializeCachedEntryPointsFrom(RawCode* code,
+ RawInstructions* instructions);
+
void SetActiveInstructions(const Instructions& instructions) const;
void set_instructions(const Instructions& instructions) const {
@@ -5777,6 +5842,7 @@
friend class Precompiler; // for set_object_pool
friend class FunctionSerializationCluster;
friend class CodeSerializationCluster;
+ friend class CodeDeserializationCluster;
friend class StubCode; // for set_object_pool
friend class MegamorphicCacheTable; // for set_object_pool
friend class CodePatcher; // for set_instructions
@@ -6196,12 +6262,12 @@
static void Init();
static void Cleanup();
+ RawArray* cache() const { return raw_ptr()->cache_; }
+
private:
// A VM heap allocated preinitialized empty subtype entry array.
static RawArray* cached_array_;
- RawArray* cache() const { return raw_ptr()->cache_; }
-
void set_cache(const Array& value) const;
intptr_t TestEntryLength() const;
@@ -6424,14 +6490,17 @@
// Check if the type of this instance is a subtype of the given other type.
// The type argument vectors are used to instantiate the other type if needed.
- bool IsInstanceOf(const AbstractType& other,
+ bool IsInstanceOf(NNBDMode mode,
+ const AbstractType& other,
const TypeArguments& other_instantiator_type_arguments,
const TypeArguments& other_function_type_arguments) const;
// Returns true if the type of this instance is a subtype of FutureOr<T>
// specified by instantiated type 'other'.
// Returns false if other type is not a FutureOr.
- bool IsFutureOrInstanceOf(Zone* zone, const AbstractType& other) const;
+ bool IsFutureOrInstanceOf(Zone* zone,
+ NNBDMode mode,
+ const AbstractType& other) const;
bool IsValidNativeIndex(int index) const {
return ((index >= 0) && (index < clazz()->ptr()->num_native_fields_));
@@ -6537,6 +6606,9 @@
StorePointer(RawFieldAddrAtOffset(offset), value.raw());
}
+ static RawInstance* NewFromCidAndSize(SharedClassTable* shared_class_table,
+ classid_t cid);
+
// TODO(iposva): Determine if this gets in the way of Smi.
HEAP_OBJECT_IMPLEMENTATION(Instance, Object);
friend class ByteBuffer;
@@ -6566,8 +6638,6 @@
RawLibrary* GetLibrary(int index) const;
void AddImport(const Namespace& import) const;
- RawObject* LookupObject(const String& name) const;
- RawClass* LookupClass(const String& class_name) const;
bool is_deferred_load() const { return raw_ptr()->is_deferred_load_; }
@@ -6661,7 +6731,8 @@
// Check the subtype relationship, considering only a subvector of length
// 'len' starting at 'from_index'.
- bool IsSubtypeOf(const TypeArguments& other,
+ bool IsSubtypeOf(NNBDMode mode,
+ const TypeArguments& other,
intptr_t from_index,
intptr_t len,
Heap::Space space) const;
@@ -6719,6 +6790,7 @@
// type from the various type argument vectors (class instantiator, function,
// or parent functions via the current context).
RawTypeArguments* InstantiateFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -6728,6 +6800,7 @@
// Runtime instantiation with canonicalization. Not to be used during type
// finalization at compile time.
RawTypeArguments* InstantiateAndCanonicalizeFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments) const;
@@ -6815,10 +6888,22 @@
virtual void SetIsBeingFinalized() const;
virtual Nullability nullability() const;
- virtual bool IsUndetermined() const { return nullability() == kUndetermined; }
- virtual bool IsNullable() const { return nullability() == kNullable; }
- virtual bool IsNonNullable() const { return nullability() == kNonNullable; }
- virtual bool IsLegacy() const { return nullability() == kLegacy; }
+ virtual bool IsUndetermined() const {
+ return nullability() == Nullability::kUndetermined;
+ }
+ virtual bool IsNullable() const {
+ return nullability() == Nullability::kNullable;
+ }
+ virtual bool IsNonNullable() const {
+ return nullability() == Nullability::kNonNullable;
+ }
+ virtual bool IsLegacy() const {
+ return nullability() == Nullability::kLegacy;
+ }
+ virtual RawAbstractType* CheckInstantiatedNullability(
+ NNBDMode mode,
+ const TypeParameter& type_param,
+ Heap::Space space) const;
virtual bool HasTypeClass() const { return type_class_id() != kIllegalCid; }
virtual classid_t type_class_id() const;
@@ -6854,6 +6939,7 @@
//
// Return a new type, or return 'this' if it is already instantiated.
virtual RawAbstractType* InstantiateFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -6924,26 +7010,25 @@
bool IsNullTypeRef() const;
// Check if this type represents the 'dynamic' type.
- bool IsDynamicType() const;
+ bool IsDynamicType() const { return type_class_id() == kDynamicCid; }
// Check if this type represents the 'void' type.
- bool IsVoidType() const;
+ bool IsVoidType() const { return type_class_id() == kVoidCid; }
// Check if this type represents the 'Null' type.
- bool IsNullType() const;
+ bool IsNullType() const { return type_class_id() == kNullCid; }
// Check if this type represents the 'Never' type.
- bool IsNeverType() const;
+ bool IsNeverType() const { return type_class_id() == kNeverCid; }
// Check if this type represents the 'Object' type.
- bool IsObjectType() const;
+ bool IsObjectType() const { return type_class_id() == kInstanceCid; }
// Check if this type represents a top type.
- // TODO(regis): Remove default kUnaware mode as implementation progresses.
- bool IsTopType(NNBDMode mode = kUnaware) const;
+ bool IsTopType() const;
// Check if this type represents the 'bool' type.
- bool IsBoolType() const;
+ bool IsBoolType() const { return type_class_id() == kBoolCid; }
// Check if this type represents the 'int' type.
bool IsIntType() const;
@@ -6961,10 +7046,10 @@
bool IsInt32x4Type() const;
// Check if this type represents the 'num' type.
- bool IsNumberType() const;
+ bool IsNumberType() const { return type_class_id() == kNumberCid; }
// Check if this type represents the '_Smi' type.
- bool IsSmiType() const;
+ bool IsSmiType() const { return type_class_id() == kSmiCid; }
// Check if this type represents the 'String' type.
bool IsStringType() const;
@@ -6979,11 +7064,14 @@
bool IsFfiPointerType() const;
// Check the subtype relationship.
- bool IsSubtypeOf(const AbstractType& other, Heap::Space space) const;
+ bool IsSubtypeOf(NNBDMode mode,
+ const AbstractType& other,
+ Heap::Space space) const;
// Returns true iff subtype is a subtype of supertype, false otherwise or if
// an error occurred.
static bool InstantiateAndTestSubtype(
+ NNBDMode mode,
AbstractType* subtype,
AbstractType* supertype,
const TypeArguments& instantiator_type_args,
@@ -7004,6 +7092,7 @@
// Returns true if this type is a subtype of FutureOr<T> specified by 'other'.
// Returns false if other type is not a FutureOr.
bool IsSubtypeOfFutureOr(Zone* zone,
+ NNBDMode mode,
const AbstractType& other,
Heap::Space space) const;
@@ -7053,8 +7142,8 @@
}
void set_nullability(Nullability value) const {
ASSERT(!IsCanonical());
- ASSERT(value != kUndetermined);
- StoreNonPointer(&raw_ptr()->nullability_, value);
+ ASSERT(value != Nullability::kUndetermined);
+ StoreNonPointer(&raw_ptr()->nullability_, static_cast<int8_t>(value));
}
RawType* ToNullability(Nullability value, Heap::Space space) const;
virtual classid_t type_class_id() const;
@@ -7080,6 +7169,7 @@
return signature() != Function::null();
}
virtual RawAbstractType* InstantiateFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -7093,6 +7183,7 @@
virtual void EnumerateURIs(URIs* uris) const;
virtual intptr_t Hash() const;
+ intptr_t ComputeHash() const;
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(RawType));
@@ -7153,15 +7244,17 @@
static RawType* DartTypeType();
// The finalized type of the given non-parameterized class.
- static RawType* NewNonParameterizedType(const Class& type_class);
+ static RawType* NewNonParameterizedType(
+ const Class& type_class,
+ Nullability nullability = Nullability::kLegacy);
static RawType* New(const Class& clazz,
const TypeArguments& arguments,
TokenPosition token_pos,
+ Nullability nullability = Nullability::kLegacy,
Heap::Space space = Heap::kOld);
private:
- intptr_t ComputeHash() const;
void SetHash(intptr_t value) const;
void set_token_pos(TokenPosition token_pos) const;
@@ -7224,6 +7317,7 @@
return !ref_type.IsNull() && ref_type.IsFunctionType();
}
virtual RawTypeRef* InstantiateFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -7302,6 +7396,7 @@
virtual bool IsEquivalent(const Instance& other, TrailPtr trail = NULL) const;
virtual bool IsRecursive() const { return false; }
virtual RawAbstractType* InstantiateFrom(
+ NNBDMode mode,
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
intptr_t num_free_fun_type_params,
@@ -9070,6 +9165,7 @@
FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedData, TypedDataBase);
friend class Class;
+ friend class CompressedStackMapsIterator;
friend class ExternalTypedData;
friend class TypedDataView;
};
@@ -9642,6 +9738,23 @@
RawSmi* PcOffsetAtFrame(intptr_t frame_index) const;
void SetPcOffsetAtFrame(intptr_t frame_index, const Smi& pc_offset) const;
+ bool skip_sync_start_in_parent_stack() const;
+ void set_skip_sync_start_in_parent_stack(bool value) const;
+
+ // The number of frames that should be cut off the top of an async stack trace
+ // if it's appended to a synchronous stack trace along a sync-async call.
+ //
+ // Without cropping, the border would look like:
+ //
+ // <async function>
+ // ---------------------------
+ // <asynchronous gap marker>
+ // <async function>
+ //
+ // Since it's not actually an async call, we crop off the last two
+ // frames when concatenating the sync and async stacktraces.
+ static constexpr intptr_t kSyncAsyncCroppedFrames = 2;
+
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(RawStackTrace));
}
@@ -9652,6 +9765,7 @@
static RawStackTrace* New(const Array& code_array,
const Array& pc_offset_array,
const StackTrace& async_link,
+ bool skip_sync_start_in_parent_stack,
Heap::Space space = Heap::kNew);
private:
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 432a6a0..280ca5d 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -1011,6 +1011,51 @@
Flush(true);
}
+CountObjectsVisitor::CountObjectsVisitor(Thread* thread, intptr_t class_count)
+ : ObjectVisitor(),
+ HandleVisitor(thread),
+ new_count_(new intptr_t[class_count]),
+ new_size_(new intptr_t[class_count]),
+ new_external_size_(new intptr_t[class_count]),
+ old_count_(new intptr_t[class_count]),
+ old_size_(new intptr_t[class_count]),
+ old_external_size_(new intptr_t[class_count]) {
+ memset(new_count_.get(), 0, class_count * sizeof(intptr_t));
+ memset(new_size_.get(), 0, class_count * sizeof(intptr_t));
+ memset(new_external_size_.get(), 0, class_count * sizeof(intptr_t));
+ memset(old_count_.get(), 0, class_count * sizeof(intptr_t));
+ memset(old_size_.get(), 0, class_count * sizeof(intptr_t));
+ memset(old_external_size_.get(), 0, class_count * sizeof(intptr_t));
+}
+
+void CountObjectsVisitor::VisitObject(RawObject* obj) {
+ intptr_t cid = obj->GetClassId();
+ intptr_t size = obj->HeapSize();
+ if (obj->IsNewObject()) {
+ new_count_[cid] += 1;
+ new_size_[cid] += size;
+ } else {
+ old_count_[cid] += 1;
+ old_size_[cid] += size;
+ }
+}
+
+void CountObjectsVisitor::VisitHandle(uword addr) {
+ FinalizablePersistentHandle* handle =
+ reinterpret_cast<FinalizablePersistentHandle*>(addr);
+ RawObject* obj = handle->raw();
+ if (!obj->IsHeapObject()) {
+ return;
+ }
+ intptr_t cid = obj->GetClassId();
+ intptr_t size = handle->external_size();
+ if (obj->IsNewObject()) {
+ new_external_size_[cid] += size;
+ } else {
+ old_external_size_[cid] += size;
+ }
+}
+
#endif // !defined(PRODUCT)
} // namespace dart
diff --git a/runtime/vm/object_graph.h b/runtime/vm/object_graph.h
index 8be3382..681c31f 100644
--- a/runtime/vm/object_graph.h
+++ b/runtime/vm/object_graph.h
@@ -5,7 +5,10 @@
#ifndef RUNTIME_VM_OBJECT_GRAPH_H_
#define RUNTIME_VM_OBJECT_GRAPH_H_
+#include <memory>
+
#include "vm/allocation.h"
+#include "vm/dart_api_state.h"
#include "vm/thread_stack_resource.h"
namespace dart {
@@ -200,6 +203,24 @@
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotWriter);
};
+class CountObjectsVisitor : public ObjectVisitor, public HandleVisitor {
+ public:
+ CountObjectsVisitor(Thread* thread, intptr_t class_count);
+ ~CountObjectsVisitor() {}
+
+ void VisitObject(RawObject* obj);
+ void VisitHandle(uword addr);
+
+ std::unique_ptr<intptr_t[]> new_count_;
+ std::unique_ptr<intptr_t[]> new_size_;
+ std::unique_ptr<intptr_t[]> new_external_size_;
+ std::unique_ptr<intptr_t[]> old_count_;
+ std::unique_ptr<intptr_t[]> old_size_;
+ std::unique_ptr<intptr_t[]> old_external_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(CountObjectsVisitor);
+};
+
#endif // !defined(PRODUCT)
} // namespace dart
diff --git a/runtime/vm/object_id_ring_test.cc b/runtime/vm/object_id_ring_test.cc
index 23d47a6..1b70a92 100644
--- a/runtime/vm/object_id_ring_test.cc
+++ b/runtime/vm/object_id_ring_test.cc
@@ -137,7 +137,6 @@
EXPECT_EQ(3, list_length);
Isolate* isolate = thread->isolate();
- Heap* heap = isolate->heap();
ObjectIdRing* ring = isolate->object_id_ring();
ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid;
@@ -167,7 +166,7 @@
EXPECT_EQ(RawObject::ToAddr(raw_obj), RawObject::ToAddr(raw_obj1));
EXPECT_EQ(RawObject::ToAddr(raw_obj), RawObject::ToAddr(raw_obj2));
// Force a scavenge.
- heap->CollectGarbage(Heap::kNew);
+ GCTestHelper::CollectNewSpace();
RawObject* raw_object_moved1 = ring->GetObjectForId(raw_obj_id1, &kind);
EXPECT_EQ(ObjectIdRing::kValid, kind);
RawObject* raw_object_moved2 = ring->GetObjectForId(raw_obj_id2, &kind);
@@ -197,7 +196,6 @@
// Test that the ring table is updated with nulls when the old GC collects.
ISOLATE_UNIT_TEST_CASE(ObjectIdRingOldGCTest) {
Isolate* isolate = thread->isolate();
- Heap* heap = isolate->heap();
ObjectIdRing* ring = isolate->object_id_ring();
ObjectIdRing::LookupResult kind = ObjectIdRing::kInvalid;
@@ -230,7 +228,7 @@
// Force a GC. No reference exist to the old string anymore. It should be
// collected and the object id ring will now return the null object for
// those ids.
- heap->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectOldSpace();
RawObject* raw_object_moved1 = ring->GetObjectForId(raw_obj_id1, &kind);
EXPECT_EQ(ObjectIdRing::kCollected, kind);
EXPECT_EQ(Object::null(), raw_object_moved1);
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 22591a2..c2c29dc 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -683,15 +683,17 @@
// Class cannot change enum property.
if (is_enum_class() != replacement.is_enum_class()) {
- context->AddReasonForCancelling(new (context->zone()) EnumClassConflict(
- context->zone(), *this, replacement));
+ context->group_reload_context()->AddReasonForCancelling(
+ new (context->zone())
+ EnumClassConflict(context->zone(), *this, replacement));
return;
}
// Class cannot change typedef property.
if (IsTypedefClass() != replacement.IsTypedefClass()) {
- context->AddReasonForCancelling(new (context->zone()) TypedefClassConflict(
- context->zone(), *this, replacement));
+ context->group_reload_context()->AddReasonForCancelling(
+ new (context->zone())
+ TypedefClassConflict(context->zone(), *this, replacement));
return;
}
@@ -700,7 +702,7 @@
const Error& error =
Error::Handle(replacement.EnsureIsFinalized(Thread::Current()));
if (!error.IsNull()) {
- context->AddReasonForCancelling(
+ context->group_reload_context()->AddReasonForCancelling(
new (context->zone())
EnsureFinalizedError(context->zone(), *this, replacement, error));
return; // No reason to check other properties.
@@ -711,8 +713,9 @@
// Native field count cannot change.
if (num_native_fields() != replacement.num_native_fields()) {
- context->AddReasonForCancelling(new (context->zone()) NativeFieldsConflict(
- context->zone(), *this, replacement));
+ context->group_reload_context()->AddReasonForCancelling(
+ new (context->zone())
+ NativeFieldsConflict(context->zone(), *this, replacement));
return;
}
@@ -770,14 +773,23 @@
IsolateReloadContext* context) const {
// Make sure the declaration types argument count matches for the two classes.
// ex. class A<int,B> {} cannot be replace with class A<B> {}.
+ auto group_context = context->group_reload_context();
if (NumTypeArguments() != replacement.NumTypeArguments()) {
- context->AddReasonForCancelling(new (context->zone()) TypeParametersChanged(
- context->zone(), *this, replacement));
+ group_context->AddReasonForCancelling(
+ new (context->zone())
+ TypeParametersChanged(context->zone(), *this, replacement));
return false;
}
if (RequiresInstanceMorphing(replacement)) {
- context->AddInstanceMorpher(new (context->zone()) InstanceMorpher(
- context->zone(), *this, replacement));
+ ASSERT(id() == replacement.id());
+ const classid_t cid = id();
+
+ // We unconditionally create an instance morpher. As a side effect of
+ // building the morpher, we will mark all new fields as late.
+ auto instance_morpher = InstanceMorpher::CreateFromClassDescriptors(
+ context->zone(), context->isolate()->shared_class_table(), *this,
+ replacement);
+ group_context->EnsureHasInstanceMorpherFor(cid, instance_morpher);
}
return true;
}
@@ -786,14 +798,16 @@
IsolateReloadContext* context) const {
// The replacement class must also prefinalized.
if (!replacement.is_prefinalized()) {
- context->AddReasonForCancelling(new (context->zone()) PreFinalizedConflict(
- context->zone(), *this, replacement));
+ context->group_reload_context()->AddReasonForCancelling(
+ new (context->zone())
+ PreFinalizedConflict(context->zone(), *this, replacement));
return false;
}
// Check the instance sizes are equal.
if (instance_size() != replacement.instance_size()) {
- context->AddReasonForCancelling(new (context->zone()) InstanceSizeConflict(
- context->zone(), *this, replacement));
+ context->group_reload_context()->AddReasonForCancelling(
+ new (context->zone())
+ InstanceSizeConflict(context->zone(), *this, replacement));
return false;
}
return true;
@@ -880,7 +894,7 @@
args_desc_array_ = ic.arguments_descriptor();
ArgumentsDescriptor args_desc(args_desc_array_);
if (new_target_.IsNull() ||
- !new_target_.AreValidArguments(args_desc, NULL)) {
+ !new_target_.AreValidArguments(NNBDMode::kLegacy, args_desc, NULL)) {
// TODO(rmacnak): Patch to a NSME stub.
VTIR_Print("Cannot rebind static call to %s from %s\n",
old_target_.ToCString(),
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 7685888..0e52082 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -164,14 +164,6 @@
}
}
}
- {
- ClassTable* class_table = Isolate::Current()->class_table();
- const ClassHeapStats* stats = class_table->StatsWithUpdatedSize(id());
- if (stats != NULL) {
- JSONObject allocation_stats(&jsobj, "_allocationStats");
- stats->PrintToJSONObject(*this, &allocation_stats, /*internal*/ true);
- }
- }
}
void TypeArguments::PrintJSONImpl(JSONStream* stream, bool ref) const {
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 684e06b..373f1fc 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -129,6 +129,7 @@
RW(GrowableObjectArray, llvm_constant_pool) \
RW(GrowableObjectArray, llvm_function_pool) \
RW(Array, llvm_constant_hash_table) \
+ RW(CompressedStackMaps, canonicalized_stack_map_entries) \
RW(ObjectPool, global_object_pool) \
RW(Array, unique_dynamic_targets) \
RW(GrowableObjectArray, megamorphic_cache_table) \
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 41a77bc..1b66b14 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2129,11 +2129,11 @@
array.Add(value);
}
Heap* heap = Isolate::Current()->heap();
- heap->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
intptr_t capacity_before = heap->CapacityInWords(Heap::kOld);
new_array = Array::MakeFixedLength(array);
EXPECT_EQ(1, new_array.Length());
- heap->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
intptr_t capacity_after = heap->CapacityInWords(Heap::kOld);
// Page should shrink.
EXPECT_LT(capacity_after, capacity_before);
@@ -2702,14 +2702,19 @@
ISOLATE_UNIT_TEST_CASE(PcDescriptors) {
DescriptorList* builder = new DescriptorList(0);
- // kind, pc_offset, deopt_id, token_pos, try_index
- builder->AddDescriptor(RawPcDescriptors::kOther, 10, 1, TokenPosition(20), 1);
- builder->AddDescriptor(RawPcDescriptors::kDeopt, 20, 2, TokenPosition(30), 0);
- builder->AddDescriptor(RawPcDescriptors::kOther, 30, 3, TokenPosition(40), 1);
- builder->AddDescriptor(RawPcDescriptors::kOther, 10, 4, TokenPosition(40), 2);
- builder->AddDescriptor(RawPcDescriptors::kOther, 10, 5, TokenPosition(80), 3);
- builder->AddDescriptor(RawPcDescriptors::kOther, 80, 6, TokenPosition(150),
- 3);
+ // kind, pc_offset, deopt_id, token_pos, try_index, yield_index
+ builder->AddDescriptor(RawPcDescriptors::kOther, 10, 1, TokenPosition(20), 1,
+ 1);
+ builder->AddDescriptor(RawPcDescriptors::kDeopt, 20, 2, TokenPosition(30), 0,
+ -1);
+ builder->AddDescriptor(RawPcDescriptors::kOther, 30, 3, TokenPosition(40), 1,
+ 10);
+ builder->AddDescriptor(RawPcDescriptors::kOther, 10, 4, TokenPosition(40), 2,
+ 20);
+ builder->AddDescriptor(RawPcDescriptors::kOther, 10, 5, TokenPosition(80), 3,
+ 30);
+ builder->AddDescriptor(RawPcDescriptors::kOther, 80, 6, TokenPosition(150), 3,
+ 30);
PcDescriptors& descriptors = PcDescriptors::Handle();
descriptors ^= builder->FinalizePcDescriptors(0);
@@ -2728,6 +2733,7 @@
PcDescriptors::Iterator iter(pc_descs, RawPcDescriptors::kAnyKind);
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(1, iter.YieldIndex());
EXPECT_EQ(20, iter.TokenPos().value());
EXPECT_EQ(1, iter.TryIndex());
EXPECT_EQ(static_cast<uword>(10), iter.PcOffset());
@@ -2735,19 +2741,24 @@
EXPECT_EQ(RawPcDescriptors::kOther, iter.Kind());
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(-1, iter.YieldIndex());
EXPECT_EQ(30, iter.TokenPos().value());
EXPECT_EQ(RawPcDescriptors::kDeopt, iter.Kind());
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(10, iter.YieldIndex());
EXPECT_EQ(40, iter.TokenPos().value());
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(20, iter.YieldIndex());
EXPECT_EQ(40, iter.TokenPos().value());
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(30, iter.YieldIndex());
EXPECT_EQ(80, iter.TokenPos().value());
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(30, iter.YieldIndex());
EXPECT_EQ(150, iter.TokenPos().value());
EXPECT_EQ(3, iter.TryIndex());
@@ -2763,16 +2774,17 @@
// kind, pc_offset, deopt_id, token_pos, try_index
builder->AddDescriptor(RawPcDescriptors::kOther, 100, 1, TokenPosition(200),
- 1);
+ 1, 10);
builder->AddDescriptor(RawPcDescriptors::kDeopt, 200, 2, TokenPosition(300),
- 0);
+ 0, -1);
builder->AddDescriptor(RawPcDescriptors::kOther, 300, 3, TokenPosition(400),
- 1);
- builder->AddDescriptor(RawPcDescriptors::kOther, 100, 4, TokenPosition(0), 2);
+ 1, 10);
+ builder->AddDescriptor(RawPcDescriptors::kOther, 100, 4, TokenPosition(0), 2,
+ 20);
builder->AddDescriptor(RawPcDescriptors::kOther, 100, 5, TokenPosition(800),
- 3);
+ 3, 30);
builder->AddDescriptor(RawPcDescriptors::kOther, 800, 6, TokenPosition(150),
- 3);
+ 3, 30);
PcDescriptors& descriptors = PcDescriptors::Handle();
descriptors ^= builder->FinalizePcDescriptors(0);
@@ -2791,6 +2803,7 @@
PcDescriptors::Iterator iter(pc_descs, RawPcDescriptors::kAnyKind);
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(10, iter.YieldIndex());
EXPECT_EQ(200, iter.TokenPos().value());
EXPECT_EQ(1, iter.TryIndex());
EXPECT_EQ(static_cast<uword>(100), iter.PcOffset());
@@ -2798,19 +2811,24 @@
EXPECT_EQ(RawPcDescriptors::kOther, iter.Kind());
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(-1, iter.YieldIndex());
EXPECT_EQ(300, iter.TokenPos().value());
EXPECT_EQ(RawPcDescriptors::kDeopt, iter.Kind());
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(10, iter.YieldIndex());
EXPECT_EQ(400, iter.TokenPos().value());
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(20, iter.YieldIndex());
EXPECT_EQ(0, iter.TokenPos().value());
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(30, iter.YieldIndex());
EXPECT_EQ(800, iter.TokenPos().value());
EXPECT_EQ(true, iter.MoveNext());
+ EXPECT_EQ(30, iter.YieldIndex());
EXPECT_EQ(150, iter.TokenPos().value());
EXPECT_EQ(3, iter.TryIndex());
@@ -3217,7 +3235,6 @@
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveCrossGen) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak = WeakProperty::Handle();
{
// Weak property and value in new. Key in old.
@@ -3232,8 +3249,8 @@
key ^= OneByteString::null();
value ^= OneByteString::null();
}
- isolate->heap()->CollectGarbage(Heap::kNew);
- isolate->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectNewSpace();
+ GCTestHelper::CollectOldSpace();
// Weak property key and value should survive due to cross-generation
// pointers.
EXPECT(weak.key() != Object::null());
@@ -3251,8 +3268,8 @@
key ^= OneByteString::null();
value ^= OneByteString::null();
}
- isolate->heap()->CollectGarbage(Heap::kNew);
- isolate->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectNewSpace();
+ GCTestHelper::CollectOldSpace();
// Weak property key and value should survive due to cross-generation
// pointers.
EXPECT(weak.key() != Object::null());
@@ -3270,7 +3287,7 @@
key ^= Integer::null();
value ^= OneByteString::null();
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
// Weak property key and value should survive due implicit liveness of
// non-heap objects.
EXPECT(weak.key() != Object::null());
@@ -3288,7 +3305,7 @@
key ^= OneByteString::null();
value ^= OneByteString::null();
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
// Weak property key and value should survive due implicit liveness of
// non-heap objects.
EXPECT(weak.key() != Object::null());
@@ -3305,8 +3322,8 @@
key ^= OneByteString::null();
value ^= OneByteString::null();
}
- isolate->heap()->CollectGarbage(Heap::kNew);
- isolate->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectNewSpace();
+ GCTestHelper::CollectOldSpace();
// Weak property key and value should survive due to cross-generation
// pointers.
EXPECT(weak.key() != Object::null());
@@ -3323,8 +3340,8 @@
key ^= OneByteString::null();
value ^= OneByteString::null();
}
- isolate->heap()->CollectGarbage(Heap::kNew);
- isolate->heap()->CollectGarbage(Heap::kOld);
+ GCTestHelper::CollectNewSpace();
+ GCTestHelper::CollectOldSpace();
// Weak property key and value should survive due to cross-generation
// pointers.
EXPECT(weak.key() != Object::null());
@@ -3334,7 +3351,6 @@
ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveRecurse) {
// This used to end in an infinite recursion. Caused by scavenging the weak
// property before scavenging the key.
- Isolate* isolate = Isolate::Current();
WeakProperty& weak = WeakProperty::Handle();
Array& arr = Array::Handle(Array::New(1));
{
@@ -3348,13 +3364,12 @@
weak.set_key(key);
weak.set_value(value);
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak.key() != Object::null());
EXPECT(weak.value() != Object::null());
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveOne_NewSpace) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak = WeakProperty::Handle();
String& key = String::Handle();
key ^= OneByteString::New("key");
@@ -3366,13 +3381,12 @@
weak.set_key(key);
weak.set_value(value);
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak.key() != Object::null());
EXPECT(weak.value() != Object::null());
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveTwo_NewSpace) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak1 = WeakProperty::Handle();
String& key1 = String::Handle();
key1 ^= OneByteString::New("key1");
@@ -3392,7 +3406,7 @@
weak2.set_key(key2);
weak2.set_value(value2);
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak1.key() != Object::null());
EXPECT(weak1.value() != Object::null());
EXPECT(weak2.key() != Object::null());
@@ -3400,7 +3414,6 @@
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveTwoShared_NewSpace) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak1 = WeakProperty::Handle();
WeakProperty& weak2 = WeakProperty::Handle();
String& key = String::Handle();
@@ -3418,7 +3431,7 @@
weak2.set_key(key);
weak2.set_value(value2);
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak1.key() != Object::null());
EXPECT(weak1.value() != Object::null());
EXPECT(weak2.key() != Object::null());
@@ -3426,7 +3439,6 @@
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveOne_OldSpace) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak = WeakProperty::Handle();
String& key = String::Handle();
key ^= OneByteString::New("key", Heap::kOld);
@@ -3438,13 +3450,12 @@
weak.set_key(key);
weak.set_value(value);
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak.key() != Object::null());
EXPECT(weak.value() != Object::null());
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveTwo_OldSpace) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak1 = WeakProperty::Handle();
String& key1 = String::Handle();
key1 ^= OneByteString::New("key1", Heap::kOld);
@@ -3464,7 +3475,7 @@
weak2.set_key(key2);
weak2.set_value(value2);
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak1.key() != Object::null());
EXPECT(weak1.value() != Object::null());
EXPECT(weak2.key() != Object::null());
@@ -3472,7 +3483,6 @@
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_PreserveTwoShared_OldSpace) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak1 = WeakProperty::Handle();
WeakProperty& weak2 = WeakProperty::Handle();
String& key = String::Handle();
@@ -3490,7 +3500,7 @@
weak2.set_key(key);
weak2.set_value(value2);
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak1.key() != Object::null());
EXPECT(weak1.value() != Object::null());
EXPECT(weak2.key() != Object::null());
@@ -3498,7 +3508,6 @@
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_ClearOne_NewSpace) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak = WeakProperty::Handle();
{
HANDLESCOPE(thread);
@@ -3512,13 +3521,12 @@
key ^= OneByteString::null();
value ^= OneByteString::null();
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak.key() == Object::null());
EXPECT(weak.value() == Object::null());
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_ClearTwoShared_NewSpace) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak1 = WeakProperty::Handle();
WeakProperty& weak2 = WeakProperty::Handle();
{
@@ -3536,7 +3544,7 @@
weak2.set_key(key);
weak2.set_value(value2);
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak1.key() == Object::null());
EXPECT(weak1.value() == Object::null());
EXPECT(weak2.key() == Object::null());
@@ -3544,7 +3552,6 @@
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_ClearOne_OldSpace) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak = WeakProperty::Handle();
{
HANDLESCOPE(thread);
@@ -3558,13 +3565,12 @@
key ^= OneByteString::null();
value ^= OneByteString::null();
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak.key() == Object::null());
EXPECT(weak.value() == Object::null());
}
ISOLATE_UNIT_TEST_CASE(WeakProperty_ClearTwoShared_OldSpace) {
- Isolate* isolate = Isolate::Current();
WeakProperty& weak1 = WeakProperty::Handle();
WeakProperty& weak2 = WeakProperty::Handle();
{
@@ -3582,7 +3588,7 @@
weak2.set_key(key);
weak2.set_value(value2);
}
- isolate->heap()->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
EXPECT(weak1.key() == Object::null());
EXPECT(weak1.value() == Object::null());
EXPECT(weak2.key() == Object::null());
@@ -4005,8 +4011,7 @@
bin::VmService::SetNativeResolver();
}
- Heap* heap = Isolate::Current()->heap();
- heap->CollectAllGarbage();
+ GCTestHelper::CollectAllGarbage();
GrowableArray<Object*> objects;
{
HeapIterationScope iteration(Thread::Current());
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index 5edf8e3..41d2e31 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -199,84 +199,303 @@
}
}
-class CompressedStackMapsKeyValueTrait {
+class StackMapEntry : public ZoneAllocated {
public:
- // Typedefs needed for the DirectChainedHashMap template.
- typedef const CompressedStackMaps* Key;
- typedef const CompressedStackMaps* Value;
- typedef const CompressedStackMaps* Pair;
-
- static Key KeyOf(Pair kv) { return kv; }
-
- static Value ValueOf(Pair kv) { return kv; }
-
- static inline intptr_t Hashcode(Key key) { return key->Hash(); }
-
- static inline bool IsKeyEqual(Pair pair, Key key) {
- return pair->Equals(*key);
+ StackMapEntry(Zone* zone, const CompressedStackMapsIterator& it)
+ : maps_(CompressedStackMaps::Handle(zone, it.maps_.raw())),
+ bits_container_(
+ CompressedStackMaps::Handle(zone, it.bits_container_.raw())),
+ spill_slot_bit_count_(it.current_spill_slot_bit_count_),
+ non_spill_slot_bit_count_(it.current_non_spill_slot_bit_count_),
+ bits_offset_(it.current_bits_offset_) {
+ ASSERT(!maps_.IsNull() && !maps_.IsGlobalTable());
+ ASSERT(!bits_container_.IsNull());
+ ASSERT(!maps_.UsesGlobalTable() || bits_container_.IsGlobalTable());
+ // Check that the iterator was fully loaded when we ran the initializing
+ // expressions above. By this point we enter the body of the constructor,
+ // it's too late to run EnsureFullyLoadedEntry().
+ ASSERT(it.HasLoadedEntry());
+ ASSERT(it.current_spill_slot_bit_count_ >= 0);
}
+
+ static const intptr_t kHashBits = 30;
+
+ intptr_t Hashcode() {
+ if (hash_ != 0) return hash_;
+ uint32_t hash = 0;
+ hash = CombineHashes(hash, spill_slot_bit_count_);
+ hash = CombineHashes(hash, non_spill_slot_bit_count_);
+ for (intptr_t i = 0; i < PayloadLength(); i++) {
+ hash = CombineHashes(hash, PayloadByte(i));
+ }
+ hash_ = FinalizeHash(hash, kHashBits);
+ return hash_;
+ }
+
+ bool Equals(const StackMapEntry* other) const {
+ if (spill_slot_bit_count_ != other->spill_slot_bit_count_ ||
+ non_spill_slot_bit_count_ != other->non_spill_slot_bit_count_) {
+ return false;
+ }
+ // Since we ensure that bits in the payload that are not part of the
+ // actual stackmap data are cleared, we can just compare payloads by byte
+ // instead of calling IsObject for each bit.
+ for (intptr_t i = 0; i < PayloadLength(); i++) {
+ if (PayloadByte(i) != other->PayloadByte(i)) return false;
+ }
+ return true;
+ }
+
+ // Encodes this StackMapEntry to the given array of bytes and returns the
+ // initial offset of the entry in the array.
+ intptr_t EncodeTo(GrowableArray<uint8_t>* array) {
+ auto const current_offset = array->length();
+ CompressedStackMapsBuilder::EncodeLEB128(array, spill_slot_bit_count_);
+ CompressedStackMapsBuilder::EncodeLEB128(array, non_spill_slot_bit_count_);
+ for (intptr_t i = 0; i < PayloadLength(); i++) {
+ array->Add(PayloadByte(i));
+ }
+ return current_offset;
+ }
+
+ intptr_t UsageCount() const { return uses_; }
+ void IncrementUsageCount() { uses_ += 1; }
+
+ private:
+ intptr_t Length() const {
+ return spill_slot_bit_count_ + non_spill_slot_bit_count_;
+ }
+ intptr_t PayloadLength() const {
+ return Utils::RoundUp(Length(), kBitsPerByte) >> kBitsPerByteLog2;
+ }
+ intptr_t PayloadByte(intptr_t offset) const {
+ return bits_container_.PayloadByte(bits_offset_ + offset);
+ }
+
+ const CompressedStackMaps& maps_;
+ const CompressedStackMaps& bits_container_;
+ const intptr_t spill_slot_bit_count_;
+ const intptr_t non_spill_slot_bit_count_;
+ const intptr_t bits_offset_;
+
+ intptr_t uses_ = 1;
+ intptr_t hash_ = 0;
};
-typedef DirectChainedHashMap<CompressedStackMapsKeyValueTrait>
+// Used for maps of indices and offsets. These are non-negative, and so the
+// value for entries may be 0. Since 0 is kNoValue for
+// RawPointerKeyValueTrait<const StackMapEntry, intptr_t>, we can't just use it.
+class StackMapEntryKeyIntValueTrait {
+ public:
+ typedef StackMapEntry* Key;
+ typedef intptr_t Value;
+
+ struct Pair {
+ Key key;
+ Value value;
+ Pair() : key(nullptr), value(-1) {}
+ Pair(const Key key, const Value& value)
+ : key(ASSERT_NOTNULL(key)), value(value) {}
+ Pair(const Pair& other) : key(other.key), value(other.value) {}
+ };
+
+ static Key KeyOf(Pair kv) { return kv.key; }
+ static Value ValueOf(Pair kv) { return kv.value; }
+ static intptr_t Hashcode(Key key) { return key->Hashcode(); }
+ static bool IsKeyEqual(Pair kv, Key key) { return key->Equals(kv.key); }
+};
+
+typedef DirectChainedHashMap<StackMapEntryKeyIntValueTrait> StackMapEntryIntMap;
+
+typedef DirectChainedHashMap<PointerKeyValueTrait<const CompressedStackMaps>>
CompressedStackMapsSet;
-void ProgramVisitor::DedupCompressedStackMaps() {
- class DedupCompressedStackMapsVisitor : public FunctionVisitor {
+void ProgramVisitor::NormalizeAndDedupCompressedStackMaps() {
+ // Walks all the CSMs in Code objects and collects their entry information
+ // for consolidation.
+ class CollectStackMapEntriesVisitor : public FunctionVisitor {
public:
- explicit DedupCompressedStackMapsVisitor(Zone* zone)
+ CollectStackMapEntriesVisitor(Zone* zone,
+ const CompressedStackMaps& global_table)
: zone_(zone),
- canonical_compressed_stackmaps_set_(),
+ old_global_table_(global_table),
code_(Code::Handle(zone)),
- compressed_stackmaps_(CompressedStackMaps::Handle(zone)) {}
-
- void AddCompressedStackMaps(const CompressedStackMaps& maps) {
- canonical_compressed_stackmaps_set_.Insert(
- &CompressedStackMaps::ZoneHandle(zone_, maps.raw()));
+ compressed_stackmaps_(CompressedStackMaps::Handle(zone)),
+ collected_entries_(zone, 2),
+ entry_indices_(zone),
+ entry_offset_(zone) {
+ ASSERT(old_global_table_.IsNull() || old_global_table_.IsGlobalTable());
}
void Visit(const Function& function) {
- if (!function.HasCode()) {
- return;
- }
+ if (!function.HasCode()) return;
code_ = function.CurrentCode();
compressed_stackmaps_ = code_.compressed_stackmaps();
- if (compressed_stackmaps_.IsNull()) return;
- compressed_stackmaps_ = DedupCompressedStackMaps(compressed_stackmaps_);
- code_.set_compressed_stackmaps(compressed_stackmaps_);
+ CompressedStackMapsIterator it(compressed_stackmaps_, old_global_table_);
+ while (it.MoveNext()) {
+ it.EnsureFullyLoadedEntry();
+ auto const entry = new (zone_) StackMapEntry(zone_, it);
+ auto const index = entry_indices_.LookupValue(entry);
+ if (index < 0) {
+ auto new_index = collected_entries_.length();
+ collected_entries_.Add(entry);
+ entry_indices_.Insert({entry, new_index});
+ } else {
+ collected_entries_.At(index)->IncrementUsageCount();
+ }
+ }
}
- RawCompressedStackMaps* DedupCompressedStackMaps(
- const CompressedStackMaps& maps) {
- auto const canonical_maps =
- canonical_compressed_stackmaps_set_.LookupValue(&maps);
- if (canonical_maps == nullptr) {
- AddCompressedStackMaps(maps);
- return maps.raw();
- } else {
- return canonical_maps->raw();
+ // Creates a new global table of stack map information. Also adds the
+ // offsets of encoded StackMapEntry objects to entry_offsets for use
+ // when normalizing CompressedStackMaps.
+ RawCompressedStackMaps* CreateGlobalTable(
+ StackMapEntryIntMap* entry_offsets) {
+ ASSERT(entry_offsets->IsEmpty());
+ if (collected_entries_.length() == 0) return CompressedStackMaps::null();
+ // First, sort the entries from most used to least used. This way,
+ // the most often used CSMs will have the lowest offsets, which means
+ // they will be smaller when LEB128 encoded.
+ collected_entries_.Sort(
+ [](StackMapEntry* const* e1, StackMapEntry* const* e2) {
+ return static_cast<int>((*e2)->UsageCount() - (*e1)->UsageCount());
+ });
+ GrowableArray<uint8_t> bytes;
+ // Encode the entries and record their offset in the payload. Sorting the
+ // entries may have changed their indices, so update those as well.
+ for (intptr_t i = 0, n = collected_entries_.length(); i < n; i++) {
+ auto const entry = collected_entries_.At(i);
+ entry_indices_.Update({entry, i});
+ entry_offsets->Insert({entry, entry->EncodeTo(&bytes)});
}
+ const auto& data = CompressedStackMaps::Handle(
+ zone_, CompressedStackMaps::NewGlobalTable(bytes));
+ return data.raw();
}
private:
- Zone* zone_;
+ Zone* const zone_;
+ const CompressedStackMaps& old_global_table_;
+
+ Code& code_;
+ CompressedStackMaps& compressed_stackmaps_;
+ GrowableArray<StackMapEntry*> collected_entries_;
+ StackMapEntryIntMap entry_indices_;
+ StackMapEntryIntMap entry_offset_;
+ };
+
+ // Walks all the CSMs in Code objects, normalizes them, and then dedups them.
+ //
+ // We use normalized to refer to CSMs whose entries are references to the
+ // new global table created during stack map collection, and non-normalized
+ // for CSMs that either have inlined entry information or whose entries are
+ // references to the _old_ global table in the object store, if any.
+ class NormalizeAndDedupCompressedStackMapsVisitor : public FunctionVisitor {
+ public:
+ NormalizeAndDedupCompressedStackMapsVisitor(
+ Zone* zone,
+ const CompressedStackMaps& global_table,
+ const StackMapEntryIntMap& entry_offsets)
+ : zone_(zone),
+ old_global_table_(global_table),
+ entry_offsets_(entry_offsets),
+ canonical_compressed_stackmaps_set_(),
+ code_(Code::Handle(zone)),
+ compressed_stackmaps_(CompressedStackMaps::Handle(zone)),
+ current_normalized_maps_(CompressedStackMaps::Handle(zone)) {
+ ASSERT(old_global_table_.IsNull() || old_global_table_.IsGlobalTable());
+ }
+
+ // Creates a normalized CSM from the given non-normalized CSM.
+ RawCompressedStackMaps* NormalizeEntries(const CompressedStackMaps& maps) {
+ GrowableArray<uint8_t> new_payload;
+ CompressedStackMapsIterator it(maps, old_global_table_);
+ intptr_t last_offset = 0;
+ while (it.MoveNext()) {
+ it.EnsureFullyLoadedEntry();
+ StackMapEntry entry(zone_, it);
+ auto const entry_offset = entry_offsets_.LookupValue(&entry);
+ auto const pc_delta = it.pc_offset() - last_offset;
+ CompressedStackMapsBuilder::EncodeLEB128(&new_payload, pc_delta);
+ CompressedStackMapsBuilder::EncodeLEB128(&new_payload, entry_offset);
+ last_offset = it.pc_offset();
+ }
+ return CompressedStackMaps::NewUsingTable(new_payload);
+ }
+
+ RawCompressedStackMaps* NormalizeAndDedupCompressedStackMaps(
+ const CompressedStackMaps& maps) {
+ ASSERT(!maps.IsNull());
+ // First check is to make sure [maps] hasn't already been normalized,
+ // since any normalized map already has a canonical entry in the set.
+ auto canonical_maps =
+ canonical_compressed_stackmaps_set_.LookupValue(&maps);
+ if (canonical_maps != nullptr) return canonical_maps->raw();
+ current_normalized_maps_ = NormalizeEntries(compressed_stackmaps_);
+ // Use the canonical entry for the newly normalized CSM, if one exists.
+ canonical_maps = canonical_compressed_stackmaps_set_.LookupValue(
+ ¤t_normalized_maps_);
+ if (canonical_maps != nullptr) return canonical_maps->raw();
+ canonical_compressed_stackmaps_set_.Insert(
+ &CompressedStackMaps::ZoneHandle(zone_,
+ current_normalized_maps_.raw()));
+ return current_normalized_maps_.raw();
+ }
+
+ void Visit(const Function& function) {
+ if (!function.HasCode()) return;
+ code_ = function.CurrentCode();
+ compressed_stackmaps_ = code_.compressed_stackmaps();
+ // We represent empty CSMs as the null value, and thus those don't need to
+ // be normalized or deduped.
+ if (compressed_stackmaps_.IsNull()) return;
+ compressed_stackmaps_ =
+ NormalizeAndDedupCompressedStackMaps(compressed_stackmaps_);
+ code_.set_compressed_stackmaps(compressed_stackmaps_);
+ }
+
+ private:
+ Zone* const zone_;
+ const CompressedStackMaps& old_global_table_;
+ const StackMapEntryIntMap& entry_offsets_;
CompressedStackMapsSet canonical_compressed_stackmaps_set_;
Code& code_;
CompressedStackMaps& compressed_stackmaps_;
+ CompressedStackMaps& current_normalized_maps_;
};
- DedupCompressedStackMapsVisitor visitor(Thread::Current()->zone());
- if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) {
- // Prefer existing objects in the VM isolate.
- const Array& object_table = Object::vm_isolate_snapshot_object_table();
- Object& object = Object::Handle();
- for (intptr_t i = 0; i < object_table.Length(); i++) {
- object = object_table.At(i);
- if (object.IsCompressedStackMaps()) {
- visitor.AddCompressedStackMaps(CompressedStackMaps::Cast(object));
- }
- }
- }
- ProgramVisitor::VisitFunctions(&visitor);
+ // The stack map deduplication happens in two phases:
+ // 1) Visit all CompressedStackMaps (CSM) objects and collect individual entry
+ // info as canonicalized StackMapEntries (SMEs). Also record the number of
+ // times the same entry info was seen across all CSMs in each SME.
+ //
+ // The results of phase 1 are used to create a new global table with entries
+ // sorted by decreasing frequency, so that entries that appear more often in
+ // CSMs have smaller payload offsets (less bytes used in the LEB128 encoding).
+ //
+ // 2) Visit all CSMs and replace each with a canonicalized normalized version
+ // that uses the new global table for non-PC offset entry information.
+ Thread* const t = Thread::Current();
+ StackZone temp_zone(t);
+ HandleScope temp_handles(t);
+ Zone* zone = temp_zone.GetZone();
+ auto object_store = t->isolate()->object_store();
+ const auto& old_global_table = CompressedStackMaps::Handle(
+ zone, object_store->canonicalized_stack_map_entries());
+ CollectStackMapEntriesVisitor collect_visitor(zone, old_global_table);
+ ProgramVisitor::VisitFunctions(&collect_visitor);
+
+ // We retrieve the new offsets for CSM entries by creating the new global
+ // table now. We go ahead and put it in place, as we already have a handle
+ // on the old table that we can pass to the normalizing visitor.
+ StackMapEntryIntMap entry_offsets(zone);
+ const auto& new_global_table = CompressedStackMaps::Handle(
+ zone, collect_visitor.CreateGlobalTable(&entry_offsets));
+ object_store->set_canonicalized_stack_map_entries(new_global_table);
+
+ NormalizeAndDedupCompressedStackMapsVisitor dedup_visitor(
+ zone, old_global_table, entry_offsets);
+ ProgramVisitor::VisitFunctions(&dedup_visitor);
}
class PcDescriptorsKeyValueTrait {
@@ -887,7 +1106,7 @@
BindStaticCalls();
ShareMegamorphicBuckets();
- DedupCompressedStackMaps();
+ NormalizeAndDedupCompressedStackMaps();
DedupPcDescriptors();
NOT_IN_PRECOMPILED(DedupDeoptEntries());
#if defined(DART_PRECOMPILER)
diff --git a/runtime/vm/program_visitor.h b/runtime/vm/program_visitor.h
index d18b60d..e66f6a6 100644
--- a/runtime/vm/program_visitor.h
+++ b/runtime/vm/program_visitor.h
@@ -33,7 +33,7 @@
#if !defined(DART_PRECOMPILED_RUNTIME)
static void BindStaticCalls();
static void ShareMegamorphicBuckets();
- static void DedupCompressedStackMaps();
+ static void NormalizeAndDedupCompressedStackMaps();
static void DedupPcDescriptors();
static void DedupDeoptEntries();
#if defined(DART_PRECOMPILER)
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 624b55b..15b17fd 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -179,7 +179,7 @@
case kCompressedStackMapsCid: {
const RawCompressedStackMaps* maps =
reinterpret_cast<const RawCompressedStackMaps*>(this);
- intptr_t length = maps->ptr()->payload_size_;
+ intptr_t length = maps->ptr()->payload_size();
instance_size = CompressedStackMaps::InstanceSize(length);
break;
}
@@ -216,9 +216,9 @@
#if defined(DEBUG)
auto class_table = isolate->shared_class_table();
#if !defined(DART_PRECOMPILED_RUNTIME)
- auto reload_context = isolate->reload_context();
+ auto reload_context = isolate->group()->reload_context();
const bool use_saved_class_table =
- reload_context != nullptr ? reload_context->UseSavedClassTableForGC()
+ reload_context != nullptr ? reload_context->UseSavedSizeTableForGC()
: false;
#else
const bool use_saved_class_table = false;
@@ -532,7 +532,7 @@
VARIABLE_NULL_VISITOR(Instructions, Instructions::Size(raw_obj))
VARIABLE_NULL_VISITOR(PcDescriptors, raw_obj->ptr()->length_)
VARIABLE_NULL_VISITOR(CodeSourceMap, raw_obj->ptr()->length_)
-VARIABLE_NULL_VISITOR(CompressedStackMaps, raw_obj->ptr()->payload_size_)
+VARIABLE_NULL_VISITOR(CompressedStackMaps, raw_obj->ptr()->payload_size())
VARIABLE_NULL_VISITOR(OneByteString, Smi::Value(raw_obj->ptr()->length_))
VARIABLE_NULL_VISITOR(TwoByteString, Smi::Value(raw_obj->ptr()->length_))
// Abstract types don't have their visitor called.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index d3dd8b9..23d384a 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -16,7 +16,6 @@
#include "vm/compiler/runtime_api.h"
#include "vm/exceptions.h"
#include "vm/globals.h"
-#include "vm/object_graph.h"
#include "vm/pointer_tagging.h"
#include "vm/snapshot.h"
#include "vm/token.h"
@@ -1153,7 +1152,6 @@
RawArray* compile_time_constants_;
RawTypedData* line_starts_;
RawArray* debug_positions_;
- RawArray* yield_positions_;
RawKernelProgramInfo* kernel_program_info_;
RawString* source_;
VISIT_TO(RawObject*, source_);
@@ -1349,10 +1347,11 @@
RawObject* owner_; // Function, Null, or a Class.
RawExceptionHandlers* exception_handlers_;
RawPcDescriptors* pc_descriptors_;
- union {
- RawTypedData* catch_entry_moves_maps_;
- RawSmi* variables_;
- } catch_entry_;
+ // If FLAG_precompiled_mode, then this field contains
+ // RawTypedData* catch_entry_moves_maps
+ // Otherwise, it is
+ // RawSmi* num_variables
+ RawObject* catch_entry_;
RawCompressedStackMaps* compressed_stackmaps_;
RawArray* inlined_id_to_function_;
RawCodeSourceMap* code_source_map_;
@@ -1520,25 +1519,42 @@
static const char* KindToCString(Kind k);
static bool ParseKind(const char* cstr, Kind* out);
- class MergedKindTry {
+ // Used to represent the absense of a yield index in PcDescriptors.
+ static constexpr intptr_t kInvalidYieldIndex = -1;
+
+ class KindAndMetadata {
public:
// Most of the time try_index will be small and merged field will fit into
// one byte.
- static int32_t Encode(intptr_t kind, intptr_t try_index) {
- intptr_t kind_shift = Utils::ShiftForPowerOfTwo(kind);
+ static int32_t Encode(intptr_t kind,
+ intptr_t try_index,
+ intptr_t yield_index) {
+ const intptr_t kind_shift = Utils::ShiftForPowerOfTwo(kind);
ASSERT(Utils::IsUint(kKindShiftSize, kind_shift));
ASSERT(Utils::IsInt(kTryIndexSize, try_index));
- return (try_index << kTryIndexPos) | (kind_shift << kKindShiftPos);
+ ASSERT(Utils::IsInt(kYieldIndexSize, yield_index));
+ return (yield_index << kYieldIndexPos) | (try_index << kTryIndexPos) |
+ (kind_shift << kKindShiftPos);
}
- static intptr_t DecodeKind(int32_t merged_kind_try) {
+ static intptr_t DecodeKind(int32_t kind_and_metadata) {
const intptr_t kKindShiftMask = (1 << kKindShiftSize) - 1;
- return 1 << (merged_kind_try & kKindShiftMask);
+ return 1 << (kind_and_metadata & kKindShiftMask);
}
- static intptr_t DecodeTryIndex(int32_t merged_kind_try) {
+ static intptr_t DecodeTryIndex(int32_t kind_and_metadata) {
// Arithmetic shift.
- return merged_kind_try >> kTryIndexPos;
+ return static_cast<int32_t>(static_cast<uint32_t>(kind_and_metadata)
+ << (32 - (kTryIndexPos + kTryIndexSize))) >>
+ (32 - kTryIndexSize);
+ }
+
+ static intptr_t DecodeYieldIndex(int32_t kind_and_metadata) {
+ // Arithmetic shift.
+ return static_cast<int32_t>(
+ static_cast<uint32_t>(kind_and_metadata)
+ << (32 - (kYieldIndexPos + kYieldIndexSize))) >>
+ (32 - kYieldIndexSize);
}
private:
@@ -1547,8 +1563,13 @@
// Is kKindShiftSize enough bits?
COMPILE_ASSERT(kLastKind <= 1 << ((1 << kKindShiftSize) - 1));
- static const intptr_t kTryIndexPos = kKindShiftSize;
- static const intptr_t kTryIndexSize = 32 - kKindShiftSize;
+ static const intptr_t kTryIndexPos = kKindShiftPos + kKindShiftSize;
+ static const intptr_t kTryIndexSize = 10;
+
+ static const intptr_t kYieldIndexPos = kTryIndexPos + kTryIndexSize;
+ static const intptr_t kYieldIndexSize = 32 - kYieldIndexPos;
+
+ COMPILE_ASSERT((kYieldIndexPos + kYieldIndexSize) == 32);
};
private:
@@ -1594,31 +1615,75 @@
RAW_HEAP_OBJECT_IMPLEMENTATION(CompressedStackMaps);
VISIT_NOTHING();
- uint32_t payload_size_; // Length of the encoded payload, in bytes.
+ // The most significant bits are the length of the encoded payload, in bytes.
+ // The low bits determine the expected payload contents, as described below.
+ uint32_t flags_and_size_;
- // Variable length data follows here. The payload consists of entries with
- // the following information:
+ // Variable length data follows here. There are three types of
+ // CompressedStackMaps (CSM):
//
- // * A header containing the following three pieces of information:
- // * An unsigned integer representing the PC offset as a delta from the
- // PC offset of the previous entry (from 0 for the first entry).
- // * An unsigned integer representing the number of bits used for
- // register entries.
- // * An unsigned integer representing the number of bits used for spill
- // slot entries.
- // * The body containing the bits for the stack map. The length of the body
- // in bits is the sum of the register and spill slot bit counts.
+ // 1) kind == kInlined: CSMs that include all information about the stack
+ // maps. The payload for these contain tightly packed entries with the
+ // following information:
//
- // Each unsigned integer is LEB128 encoded, as generally they tend to fit in
- // a single byte or two. Thus, entry headers are not a fixed length, and
- // currently there is no random access of entries. In addition, PC offsets
- // are currently encoded as deltas, which also inhibits random access without
- // accessing previous entries. That means to find an entry for a given PC
- // offset, a linear search must be done where the payload is decoded
- // up to the entry whose PC offset is >= the given PC.
+ // * A header containing the following three pieces of information:
+ // * An unsigned integer representing the PC offset as a delta from the
+ // PC offset of the previous entry (from 0 for the first entry).
+ // * An unsigned integer representing the number of bits used for
+ // spill slot entries.
+ // * An unsigned integer representing the number of bits used for other
+ // entries.
+ // * The body containing the bits for the stack map. The length of the body
+ // in bits is the sum of the spill slot and non-spill slot bit counts.
+ //
+ // 2) kind == kUsesTable: CSMs where the majority of the stack map information
+ // has been offloaded and canonicalized into a global table. The payload
+ // contains tightly packed entries with the following information:
+ //
+ // * A header containing just an unsigned integer representing the PC offset
+ // delta as described above.
+ // * The body is just an unsigned integer containing the offset into the
+ // payload for the global table.
+ //
+ // 3) kind == kGlobalTable: A CSM implementing the global table. Here, the
+ // payload contains tightly packed entries with the following information:
+ // * A header containing the following two pieces of information:
+ // * An unsigned integer representing the number of bits used for
+ // spill slot entries.
+ // * An unsigned integer representing the number of bits used for other
+ // entries.
+ // * The body containing the bits for the stack map. The length of the body
+ // in bits is the sum of the spill slot and non-spill slot bit counts.
+ //
+ // In all types of CSM, each unsigned integer is LEB128 encoded, as generally
+ // they tend to fit in a single byte or two. Thus, entry headers are not a
+ // fixed length, and currently there is no random access of entries. In
+ // addition, PC offsets are currently encoded as deltas, which also inhibits
+ // random access without accessing previous entries. That means to find an
+ // entry for a given PC offset, a linear search must be done where the payload
+ // is decoded up to the entry whose PC offset is >= the given PC.
+
uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
+ enum Kind {
+ kInlined = 0b00,
+ kUsesTable = 0b01,
+ kGlobalTable = 0b10,
+ };
+
+ static const uintptr_t kKindBits = 2;
+ using KindField = BitField<uint32_t, Kind, 0, kKindBits>;
+ using SizeField = BitField<uint32_t, uint32_t, kKindBits, 32 - kKindBits>;
+
+ uint32_t payload_size() const { return SizeField::decode(flags_and_size_); }
+ bool UsesGlobalTable() const {
+ return KindField::decode(flags_and_size_) == kUsesTable;
+ }
+ bool IsGlobalTable() const {
+ return KindField::decode(flags_and_size_) == kGlobalTable;
+ }
+
friend class ImageWriter;
};
@@ -2519,6 +2584,10 @@
// False for pre-allocated stack trace (used in OOM and Stack overflow).
bool expand_inlined_;
+ // Whether the link between the stack and the async-link represents a
+ // synchronous start to an asynchronous function. In this case, we omit the
+ // <asynchronous suspension> marker when concatenating the stacks.
+ bool skip_sync_start_in_parent_stack;
};
// VM type for capturing JS regular expressions.
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index c818091..079cbe7 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -61,7 +61,6 @@
F(Script, compile_time_constants_) \
F(Script, line_starts_) \
F(Script, debug_positions_) \
- F(Script, yield_positions_) \
F(Script, kernel_program_info_) \
F(Script, source_) \
F(Library, name_) \
@@ -99,6 +98,7 @@
F(Code, owner_) \
F(Code, exception_handlers_) \
F(Code, pc_descriptors_) \
+ F(Code, catch_entry_) \
F(Code, compressed_stackmaps_) \
F(Code, inlined_id_to_function_) \
F(Code, code_source_map_) \
diff --git a/runtime/vm/resolver.cc b/runtime/vm/resolver.cc
index 9dec549..82dadf3 100644
--- a/runtime/vm/resolver.cc
+++ b/runtime/vm/resolver.cc
@@ -42,7 +42,8 @@
zone,
ResolveDynamicAnyArgs(zone, receiver_class, function_name, allow_add));
- if (function.IsNull() || !function.AreValidArguments(args_desc, NULL)) {
+ if (function.IsNull() ||
+ !function.AreValidArguments(NNBDMode::kLegacy, args_desc, NULL)) {
// Return a null function to signal to the upper levels to dispatch to
// "noSuchMethod" function.
if (FLAG_trace_resolving) {
@@ -50,7 +51,8 @@
String::Handle(zone, Symbols::New(thread, "function not found"));
if (!function.IsNull()) {
// Obtain more detailed error message.
- function.AreValidArguments(args_desc, &error_message);
+ function.AreValidArguments(NNBDMode::kLegacy, args_desc,
+ &error_message);
}
THR_Print("ResolveDynamic error '%s': %s.\n", function_name.ToCString(),
error_message.ToCString());
@@ -149,13 +151,14 @@
const Object& object = Object::Handle(library.ResolveName(function_name));
if (!object.IsNull() && object.IsFunction()) {
function ^= object.raw();
- if (!function.AreValidArguments(type_args_len, num_arguments,
- argument_names, NULL)) {
+ if (!function.AreValidArguments(NNBDMode::kLegacy, type_args_len,
+ num_arguments, argument_names, NULL)) {
if (FLAG_trace_resolving) {
String& error_message = String::Handle();
// Obtain more detailed error message.
- function.AreValidArguments(type_args_len, num_arguments,
- argument_names, &error_message);
+ function.AreValidArguments(NNBDMode::kLegacy, type_args_len,
+ num_arguments, argument_names,
+ &error_message);
THR_Print("ResolveStatic error '%s': %s.\n",
function_name.ToCString(), error_message.ToCString());
}
@@ -196,15 +199,16 @@
const Function& function =
Function::Handle(cls.LookupStaticFunction(function_name));
if (function.IsNull() ||
- !function.AreValidArguments(type_args_len, num_arguments, argument_names,
- NULL)) {
+ !function.AreValidArguments(NNBDMode::kLegacy, type_args_len,
+ num_arguments, argument_names, NULL)) {
// Return a null function to signal to the upper levels to throw a
// resolution error or maybe throw the error right here.
if (FLAG_trace_resolving) {
String& error_message = String::Handle(String::New("function not found"));
if (!function.IsNull()) {
// Obtain more detailed error message.
- function.AreValidArguments(type_args_len, num_arguments, argument_names,
+ function.AreValidArguments(NNBDMode::kLegacy, type_args_len,
+ num_arguments, argument_names,
&error_message);
}
THR_Print("ResolveStatic error '%s': %s.\n", function_name.ToCString(),
@@ -227,15 +231,16 @@
const Function& function =
Function::Handle(cls.LookupStaticFunctionAllowPrivate(function_name));
if (function.IsNull() ||
- !function.AreValidArguments(type_args_len, num_arguments, argument_names,
- NULL)) {
+ !function.AreValidArguments(NNBDMode::kLegacy, type_args_len,
+ num_arguments, argument_names, NULL)) {
// Return a null function to signal to the upper levels to throw a
// resolution error or maybe throw the error right here.
if (FLAG_trace_resolving) {
String& error_message = String::Handle(String::New("function not found"));
if (!function.IsNull()) {
// Obtain more detailed error message.
- function.AreValidArguments(type_args_len, num_arguments, argument_names,
+ function.AreValidArguments(NNBDMode::kLegacy, type_args_len,
+ num_arguments, argument_names,
&error_message);
}
THR_Print("ResolveStaticAllowPrivate error '%s': %s.\n",
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 1bca9a1..076e818 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -385,8 +385,8 @@
ASSERT(function_type_arguments.IsNull() ||
function_type_arguments.IsInstantiated());
type =
- type.InstantiateFrom(instantiator_type_arguments, function_type_arguments,
- kAllFree, NULL, Heap::kOld);
+ type.InstantiateFrom(NNBDMode::kLegacy, instantiator_type_arguments,
+ function_type_arguments, kAllFree, NULL, Heap::kOld);
if (type.IsTypeRef()) {
type = TypeRef::Cast(type).type();
ASSERT(!type.IsTypeRef());
@@ -417,7 +417,7 @@
// instantiator can be reused as type argument vector.
ASSERT(!type_arguments.IsUninstantiatedIdentity());
type_arguments = type_arguments.InstantiateAndCanonicalizeFrom(
- instantiator_type_arguments, function_type_arguments);
+ NNBDMode::kLegacy, instantiator_type_arguments, function_type_arguments);
ASSERT(type_arguments.IsNull() || type_arguments.IsInstantiated());
arguments.SetReturn(type_arguments);
}
@@ -444,7 +444,8 @@
// The supertype or subtype may not be instantiated.
if (AbstractType::InstantiateAndTestSubtype(
- &subtype, &supertype, instantiator_type_args, function_type_args)) {
+ NNBDMode::kLegacy, &subtype, &supertype, instantiator_type_args,
+ function_type_args)) {
return;
}
@@ -537,7 +538,8 @@
do {
call_function = cls.LookupDynamicFunction(Symbols::Call());
if (!call_function.IsNull()) {
- if (!call_function.AreValidArguments(args_desc, NULL)) {
+ if (!call_function.AreValidArguments(NNBDMode::kLegacy, args_desc,
+ NULL)) {
call_function = Function::null();
}
break;
@@ -573,9 +575,9 @@
} else {
// Instantiate type before printing.
const AbstractType& instantiated_type =
- AbstractType::Handle(type.InstantiateFrom(instantiator_type_arguments,
- function_type_arguments,
- kAllFree, NULL, Heap::kOld));
+ AbstractType::Handle(type.InstantiateFrom(
+ NNBDMode::kLegacy, instantiator_type_arguments,
+ function_type_arguments, kAllFree, NULL, Heap::kOld));
OS::PrintErr("%s: '%s' %s '%s' instantiated from '%s' (pc: %#" Px ").\n",
message, String::Handle(instance_type.Name()).ToCString(),
(result.raw() == Bool::True().raw()) ? "is" : "is !",
@@ -698,9 +700,9 @@
if (FLAG_trace_type_checks) {
AbstractType& test_type = AbstractType::Handle(zone, type.raw());
if (!test_type.IsInstantiated()) {
- test_type = type.InstantiateFrom(instantiator_type_arguments,
- function_type_arguments, kAllFree, NULL,
- Heap::kNew);
+ test_type = type.InstantiateFrom(
+ NNBDMode::kLegacy, instantiator_type_arguments,
+ function_type_arguments, kAllFree, NULL, Heap::kNew);
}
const auto& type_class = Class::Handle(zone, test_type.type_class());
const auto& instance_class_name =
@@ -751,7 +753,8 @@
ASSERT(type.IsFinalized());
ASSERT(!type.IsDynamicType()); // No need to check assignment.
const Bool& result = Bool::Get(instance.IsInstanceOf(
- type, instantiator_type_arguments, function_type_arguments));
+ NNBDMode::kLegacy, type, instantiator_type_arguments,
+ function_type_arguments));
if (FLAG_trace_type_checks) {
PrintTypeCheck("InstanceOf", instance, type, instantiator_type_arguments,
function_type_arguments, result);
@@ -800,7 +803,8 @@
ASSERT(!src_instance.IsNull()); // Already checked in inlined code.
const bool is_instance_of = src_instance.IsInstanceOf(
- dst_type, instantiator_type_arguments, function_type_arguments);
+ NNBDMode::kLegacy, dst_type, instantiator_type_arguments,
+ function_type_arguments);
if (FLAG_trace_type_checks) {
PrintTypeCheck("TypeCheck", src_instance, dst_type,
@@ -814,9 +818,9 @@
AbstractType::Handle(zone, src_instance.GetType(Heap::kNew));
if (!dst_type.IsInstantiated()) {
// Instantiate dst_type before reporting the error.
- dst_type = dst_type.InstantiateFrom(instantiator_type_arguments,
- function_type_arguments, kAllFree,
- NULL, Heap::kNew);
+ dst_type = dst_type.InstantiateFrom(
+ NNBDMode::kLegacy, instantiator_type_arguments,
+ function_type_arguments, kAllFree, NULL, Heap::kNew);
// Note that instantiated dst_type may be malbounded.
}
if (dst_name.IsNull()) {
@@ -1221,7 +1225,8 @@
static RawFunction* ComputeTypeCheckTarget(const Instance& receiver,
const AbstractType& type,
const ArgumentsDescriptor& desc) {
- bool result = receiver.IsInstanceOf(type, Object::null_type_arguments(),
+ bool result = receiver.IsInstanceOf(NNBDMode::kLegacy, type,
+ Object::null_type_arguments(),
Object::null_type_arguments());
ObjectStore* store = Isolate::Current()->object_store();
const Function& target =
@@ -2086,7 +2091,7 @@
while (!cls.IsNull()) {
function = cls.LookupDynamicFunction(target_name);
if (!function.IsNull()) {
- ASSERT(!function.AreValidArguments(args_desc, NULL));
+ ASSERT(!function.AreValidArguments(NNBDMode::kLegacy, args_desc, NULL));
break; // mismatch, invoke noSuchMethod
}
function = cls.LookupDynamicFunction(getter_name);
@@ -2281,8 +2286,8 @@
}
// Issue a reload.
- bool success =
- isolate->ReloadSources(&js, true /* force_reload */, script_uri);
+ bool success = isolate->group()->ReloadSources(&js, true /* force_reload */,
+ script_uri);
if (!success) {
FATAL1("*** Isolate reload failed:\n%s\n", js.ToCString());
}
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 69eec8e..a90b073 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -3201,12 +3201,15 @@
return true;
}
- Isolate* isolate = thread->isolate();
- if (!isolate->HasTagHandler()) {
+ IsolateGroup* isolate_group = thread->isolate_group();
+ if (isolate_group->library_tag_handler() == nullptr) {
js->PrintError(kFeatureDisabled,
"A library tag handler must be installed.");
return true;
}
+ // TODO(dartbug.com/36097): We need to change the "reloadSources" service-api
+ // call to accept an isolate group instead of an isolate.
+ Isolate* isolate = thread->isolate();
if ((isolate->sticky_error() != Error::null()) ||
(Thread::Current()->sticky_error() != Error::null())) {
js->PrintError(kIsolateReloadBarred,
@@ -3214,7 +3217,7 @@
"was an unhandled exception error. Restart the isolate.");
return true;
}
- if (isolate->IsReloading()) {
+ if (isolate_group->IsReloading()) {
js->PrintError(kIsolateIsReloading, "This isolate is being reloaded.");
return true;
}
@@ -3226,8 +3229,8 @@
const bool force_reload =
BoolParameter::Parse(js->LookupParam("force"), false);
- isolate->ReloadSources(js, force_reload, js->LookupParam("rootLibUri"),
- js->LookupParam("packagesUri"));
+ isolate_group->ReloadSources(js, force_reload, js->LookupParam("rootLibUri"),
+ js->LookupParam("packagesUri"));
Service::CheckForPause(isolate, js);
@@ -3961,7 +3964,6 @@
Isolate* isolate = thread->isolate();
if (should_reset_accumulator) {
isolate->UpdateLastAllocationProfileAccumulatorResetTimestamp();
- isolate->shared_class_table()->ResetAllocationAccumulators();
}
if (should_collect) {
isolate->UpdateLastAllocationProfileGCTimestamp();
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index f283627..f2ca26a 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -8,7 +8,6 @@
#include "include/dart_tools_api.h"
#include "vm/allocation.h"
-#include "vm/object_graph.h"
#include "vm/object_id_ring.h"
#include "vm/os_thread.h"
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index b2ad52a..ec71428 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -276,7 +276,10 @@
// on the stack map.
CompressedStackMaps maps;
maps = code.compressed_stackmaps();
- CompressedStackMapsIterator it(maps);
+ CompressedStackMaps global_table;
+ global_table =
+ this->isolate()->object_store()->canonicalized_stack_map_entries();
+ CompressedStackMapsIterator it(maps, global_table);
const uword start = Instructions::PayloadStart(code.instructions());
const uint32_t pc_offset = pc() - start;
if (it.Find(pc_offset)) {
@@ -299,7 +302,7 @@
// of outgoing arguments is not explicitly tracked.
// Spill slots are at the 'bottom' of the frame.
- intptr_t spill_slot_count = it.spill_slot_bit_count();
+ intptr_t spill_slot_count = it.SpillSlotBitCount();
for (intptr_t bit = 0; bit < spill_slot_count; ++bit) {
if (it.IsObject(bit)) {
visitor->VisitPointer(last);
@@ -309,7 +312,7 @@
// The live registers at the 'top' of the frame comprise the rest of the
// stack map.
- for (intptr_t bit = it.length() - 1; bit >= spill_slot_count; --bit) {
+ for (intptr_t bit = it.Length() - 1; bit >= spill_slot_count; --bit) {
if (it.IsObject(bit)) {
visitor->VisitPointer(first);
}
diff --git a/runtime/vm/stack_trace.cc b/runtime/vm/stack_trace.cc
index 17724a3..449c323 100644
--- a/runtime/vm/stack_trace.cc
+++ b/runtime/vm/stack_trace.cc
@@ -4,13 +4,15 @@
#include "vm/stack_trace.h"
#include "vm/stack_frame.h"
+#include "vm/symbols.h"
namespace dart {
// Count the number of frames that are on the stack.
intptr_t StackTraceUtils::CountFrames(Thread* thread,
int skip_frames,
- const Function& async_function) {
+ const Function& async_function,
+ bool* sync_async_end) {
Zone* zone = thread->zone();
intptr_t frame_count = 0;
StackFrameIterator frames(ValidationPolicy::kDontValidateFrames, thread,
@@ -20,8 +22,12 @@
Function& function = Function::Handle(zone);
Code& code = Code::Handle(zone);
Bytecode& bytecode = Bytecode::Handle(zone);
+ String& function_name = String::Handle(zone);
const bool async_function_is_null = async_function.IsNull();
- for (; frame != NULL; frame = frames.NextFrame()) {
+ int sync_async_gap_frames = -1;
+ ASSERT(async_function_is_null || sync_async_end != NULL);
+ for (; frame != NULL && sync_async_gap_frames != 0;
+ frame = frames.NextFrame()) {
if (!frame->IsDartFrame()) {
continue;
}
@@ -39,14 +45,23 @@
code = frame->LookupDartCode();
function = code.function();
}
- frame_count++;
+ if (sync_async_gap_frames > 0) {
+ function_name = function.QualifiedScrubbedName();
+ if (!CheckAndSkipAsync(&sync_async_gap_frames, function_name)) {
+ *sync_async_end = false;
+ return frame_count;
+ }
+ } else {
+ frame_count++;
+ }
if (!async_function_is_null &&
(async_function.raw() == function.parent_function())) {
- return frame_count;
+ sync_async_gap_frames = kSyncAsyncFrameGap;
}
}
- // We hit the sentinel.
- ASSERT(async_function_is_null);
+ if (!async_function_is_null) {
+ *sync_async_end = sync_async_gap_frames == 0;
+ }
return frame_count;
}
diff --git a/runtime/vm/stack_trace.h b/runtime/vm/stack_trace.h
index 394f45b..ea4ed29 100644
--- a/runtime/vm/stack_trace.h
+++ b/runtime/vm/stack_trace.h
@@ -8,6 +8,7 @@
#include "vm/allocation.h"
#include "vm/flag_list.h"
#include "vm/object.h"
+#include "vm/symbols.h"
namespace dart {
@@ -16,10 +17,12 @@
/// Counts the number of stack frames.
/// Skips over the first |skip_frames|.
/// If |async_function| is not null, stops at the function that has
- /// |async_function| as its parent.
+ /// |async_function| as its parent, and records in 'sync_async_end' whether
+ /// |async_function| was called synchronously.
static intptr_t CountFrames(Thread* thread,
int skip_frames,
- const Function& async_function);
+ const Function& async_function,
+ bool* sync_async_end);
/// Collects |count| frames into |code_array| and |pc_offset_array|.
/// Writing begins at |array_offset|.
@@ -42,6 +45,36 @@
StackTrace* async_stack_trace,
Array* async_code_array,
Array* async_pc_offset_array);
+
+ // The number of frames involved in a "sync-async" gap: a synchronous initial
+ // invocation of an asynchronous function. See CheckAndSkipAsync.
+ static constexpr intptr_t kSyncAsyncFrameGap = 2;
+
+ // A synchronous invocation of an async function involves the following
+ // frames:
+ // <async function>__<anonymous_closure> (0)
+ // _Closure.call (1)
+ // _AsyncAwaitCompleter.start (2)
+ // <async_function> (3)
+ //
+ // Alternatively, for bytecode or optimized frames, we may see:
+ // <async function>__<anonymous_closure> (0)
+ // _AsyncAwaitCompleter.start (1)
+ // <async_function> (2)
+ static bool CheckAndSkipAsync(int* skip_sync_async_frames_count,
+ const String& function_name) {
+ ASSERT(*skip_sync_async_frames_count > 0);
+ if (function_name.Equals(Symbols::_AsyncAwaitCompleterStart())) {
+ *skip_sync_async_frames_count = 0;
+ return true;
+ }
+ if (function_name.Equals(Symbols::_ClosureCall()) &&
+ *skip_sync_async_frames_count == 2) {
+ (*skip_sync_async_frames_count)--;
+ return true;
+ }
+ return false;
+ }
};
} // namespace dart
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 739e4fd..98f20cf 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -25,8 +25,13 @@
DECLARE_FLAG(bool, enable_interpreter);
-Code* StubCode::entries_[kNumStubEntries] = {
-#define STUB_CODE_DECLARE(name) nullptr,
+StubCode::StubCodeEntry StubCode::entries_[kNumStubEntries] = {
+#if defined(DART_PRECOMPILED_RUNTIME)
+#define STUB_CODE_DECLARE(name) {nullptr, #name},
+#else
+#define STUB_CODE_DECLARE(name) \
+ {nullptr, #name, compiler::StubCodeCompiler::Generate##name##Stub},
+#endif
VM_STUB_CODE_LIST(STUB_CODE_DECLARE)
#undef STUB_CODE_DECLARE
};
@@ -39,25 +44,22 @@
#else
-#define STUB_CODE_GENERATE(name) \
- entries_[k##name##Index] = Code::ReadOnlyHandle(); \
- *entries_[k##name##Index] = \
- Generate("_stub_" #name, &object_pool_builder, \
- compiler::StubCodeCompiler::Generate##name##Stub);
-
-#define STUB_CODE_SET_OBJECT_POOL(name) \
- entries_[k##name##Index]->set_object_pool(object_pool.raw());
-
void StubCode::Init() {
compiler::ObjectPoolBuilder object_pool_builder;
// Generate all the stubs.
- VM_STUB_CODE_LIST(STUB_CODE_GENERATE);
+ for (size_t i = 0; i < ARRAY_SIZE(entries_); i++) {
+ entries_[i].code = Code::ReadOnlyHandle();
+ *(entries_[i].code) =
+ Generate(entries_[i].name, &object_pool_builder, entries_[i].generator);
+ }
const ObjectPool& object_pool =
ObjectPool::Handle(ObjectPool::NewFromBuilder(object_pool_builder));
- VM_STUB_CODE_LIST(STUB_CODE_SET_OBJECT_POOL)
+ for (size_t i = 0; i < ARRAY_SIZE(entries_); i++) {
+ entries_[i].code->set_object_pool(object_pool.raw());
+ }
}
#undef STUB_CODE_GENERATE
@@ -74,32 +76,22 @@
/*optimized=*/false));
#ifndef PRODUCT
if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
- LogBlock lb;
- THR_Print("Code for stub '%s': {\n", name);
- DisassembleToStdout formatter;
- code.Disassemble(&formatter);
- THR_Print("}\n");
- const ObjectPool& object_pool = ObjectPool::Handle(code.object_pool());
- if (!object_pool.IsNull()) {
- object_pool.DebugPrint();
- }
+ Disassembler::DisassembleStub(name, code);
}
#endif // !PRODUCT
return code.raw();
}
#endif // defined(DART_PRECOMPILED_RUNTIME)
-#define STUB_CODE_CLEANUP(name) entries_[k##name##Index] = nullptr;
-
void StubCode::Cleanup() {
- VM_STUB_CODE_LIST(STUB_CODE_CLEANUP);
+ for (size_t i = 0; i < ARRAY_SIZE(entries_); i++) {
+ entries_[i].code = nullptr;
+ }
}
-#undef STUB_CODE_CLEANUP
-
bool StubCode::HasBeenInitialized() {
// Use AsynchronousGapMarker as canary.
- return entries_[kAsynchronousGapMarkerIndex] != nullptr;
+ return entries_[kAsynchronousGapMarkerIndex].code != nullptr;
}
bool StubCode::InInvocationStub(uword pc, bool is_interpreted_frame) {
@@ -199,15 +191,7 @@
Code::NotifyCodeObservers(name, stub, /*optimized=*/false);
#ifndef PRODUCT
if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
- LogBlock lb;
- THR_Print("Code for allocation stub '%s': {\n", name);
- DisassembleToStdout formatter;
- stub.Disassemble(&formatter);
- THR_Print("}\n");
- const ObjectPool& object_pool = ObjectPool::Handle(stub.object_pool());
- if (!object_pool.IsNull()) {
- object_pool.DebugPrint();
- }
+ Disassembler::DisassembleStub(name, stub);
}
#endif // !PRODUCT
}
@@ -245,15 +229,7 @@
#ifndef PRODUCT
if (FLAG_support_disassembler && FLAG_disassemble_stubs) {
- LogBlock lb;
- THR_Print("Code for isolate stub '%s': {\n", name);
- DisassembleToStdout formatter;
- stub.Disassemble(&formatter);
- THR_Print("}\n");
- const ObjectPool& object_pool = ObjectPool::Handle(stub.object_pool());
- if (!object_pool.IsNull()) {
- object_pool.DebugPrint();
- }
+ Disassembler::DisassembleStub(name, stub);
}
#endif // !PRODUCT
return stub.raw();
@@ -279,14 +255,12 @@
}
const char* StubCode::NameOfStub(uword entry_point) {
-#define VM_STUB_CODE_TESTER(name) \
- if (entries_[k##name##Index] != nullptr && \
- !entries_[k##name##Index]->IsNull() && \
- entries_[k##name##Index]->EntryPoint() == entry_point) { \
- return "" #name; \
+ for (size_t i = 0; i < ARRAY_SIZE(entries_); i++) {
+ if ((entries_[i].code != nullptr) && !entries_[i].code->IsNull() &&
+ (entries_[i].code->EntryPoint() == entry_point)) {
+ return entries_[i].name;
+ }
}
- VM_STUB_CODE_LIST(VM_STUB_CODE_TESTER);
-#undef VM_STUB_CODE_TESTER
return nullptr;
}
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index cf832cb..db86482 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -22,6 +22,8 @@
class SnapshotReader;
class SnapshotWriter;
+DECLARE_FLAG(bool, disassemble_stubs);
+
// Is it permitted for the stubs above to refer to Object::null(), which is
// allocated in the VM isolate and shared across all isolates.
// However, in cases where a simple GC-safe placeholder is needed on the stack,
@@ -52,7 +54,7 @@
// Define the shared stub code accessors.
#define STUB_CODE_ACCESSOR(name) \
- static const Code& name() { return *entries_[k##name##Index]; } \
+ static const Code& name() { return *entries_[k##name##Index].code; } \
static intptr_t name##Size() { return name().Size(); }
VM_STUB_CODE_LIST(STUB_CODE_ACCESSOR);
#undef STUB_CODE_ACCESSOR
@@ -76,11 +78,11 @@
static const intptr_t kNoInstantiator = 0;
static const intptr_t kInstantiationSizeInWords = 3;
- static const Code& EntryAt(intptr_t index) { return *entries_[index]; }
+ static const Code& EntryAt(intptr_t index) { return *(entries_[index].code); }
static void EntryAtPut(intptr_t index, Code* entry) {
ASSERT(entry->IsReadOnlyHandle());
- ASSERT(entries_[index] == nullptr);
- entries_[index] = entry;
+ ASSERT(entries_[index].code == nullptr);
+ entries_[index].code = entry;
}
static intptr_t NumEntries() { return kNumStubEntries; }
@@ -106,7 +108,14 @@
kNumStubEntries
};
- static Code* entries_[kNumStubEntries];
+ struct StubCodeEntry {
+ Code* code;
+ const char* name;
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ void (*generator)(compiler::Assembler* assembler);
+#endif
+ };
+ static StubCodeEntry entries_[kNumStubEntries];
};
} // namespace dart
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 3333c03..312e23b 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -382,7 +382,8 @@
ASSERT(type.IsType());
ASSERT(type.IsCanonical());
bool present = table.Insert(type);
- ASSERT(!present);
+ // Two recursive types with different topology (and hashes) may be equal.
+ ASSERT(!present || type.IsRecursive());
}
object_store->set_canonical_types(table.Release());
}
@@ -397,7 +398,8 @@
ASSERT(type_arg.IsTypeArguments());
ASSERT(type_arg.IsCanonical());
bool present = table.Insert(type_arg);
- ASSERT(!present);
+ // Two recursive types with different topology (and hashes) may be equal.
+ ASSERT(!present || type_arg.IsRecursive());
}
object_store->set_canonical_type_arguments(table.Release());
}
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index e9aa508..cb64951 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -580,6 +580,9 @@
static const String& Percent() {
return *(symbol_handles_[kNullCharId + '%']);
}
+ static const String& QuestionMark() {
+ return *(symbol_handles_[kNullCharId + '?']);
+ }
static const String& Caret() { return *(symbol_handles_[kNullCharId + '^']); }
static const String& Tilde() { return *(symbol_handles_[kNullCharId + '~']); }
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 2afc376..cd0dee8 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -514,7 +514,6 @@
}
heap()->CollectGarbage(Heap::kNew);
}
- heap()->CheckFinishConcurrentMarking(this);
}
if ((interrupt_bits & kMessageInterrupt) != 0) {
MessageHandler::MessageStatus status =
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 2469d30..3353213 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -173,6 +173,8 @@
#define CACHED_ADDRESSES_LIST(V) \
CACHED_VM_STUBS_ADDRESSES_LIST(V) \
+ V(uword, bootstrap_native_wrapper_entry_point_, \
+ NativeEntry::BootstrapNativeCallWrapperEntry(), 0) \
V(uword, no_scope_native_wrapper_entry_point_, \
NativeEntry::NoScopeNativeCallWrapperEntry(), 0) \
V(uword, auto_scope_native_wrapper_entry_point_, \
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index eff9fd1..244974e 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -104,7 +104,7 @@
return Code::null();
}
- // TODO(regis): Revisit when type checking mode is not kUnaware anymore.
+ // TODO(regis): Revisit when type checking mode is not kLegacy anymore.
if (type.raw() == Type::ObjectType() || type.raw() == Type::DynamicType() ||
type.raw() == Type::VoidType()) {
return StubCode::TopTypeTypeTest().raw();
@@ -274,7 +274,8 @@
/*exclude_null=*/false);
const Type& int_type = Type::Handle(Type::IntType());
- const bool smi_is_ok = int_type.IsSubtypeOf(type, Heap::kNew);
+ const bool smi_is_ok =
+ int_type.IsSubtypeOf(NNBDMode::kLegacy, type, Heap::kNew);
BuildOptimizedSubtypeRangeCheck(assembler, ranges, class_id_reg,
instance_reg, smi_is_ok);
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 66addfe..e6b60bb 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -33,6 +33,9 @@
namespace dart {
+DECLARE_FLAG(bool, gc_during_reload);
+DECLARE_FLAG(bool, force_evacuation);
+
const uint8_t* platform_strong_dill = kPlatformStrongDill;
const intptr_t platform_strong_dill_size = kPlatformStrongDillSize;
@@ -126,6 +129,7 @@
OS::PrintErr("Creation of isolate failed '%s'\n", err);
free(err);
}
+
EXPECT(isolate != NULL);
return isolate;
}
@@ -139,6 +143,20 @@
group_data, isolate_data);
}
+void SetupCoreLibrariesForUnitTest() {
+ TransitionVMToNative transition(Thread::Current());
+
+ Dart_EnterScope();
+ bool ok = bin::DartUtils::SetOriginalWorkingDirectory();
+ RELEASE_ASSERT(ok);
+ Dart_Handle result = bin::DartUtils::PrepareForScriptLoading(
+ /*is_service_isolate=*/false,
+ /*trace_loading=*/false);
+ Dart_ExitScope();
+
+ RELEASE_ASSERT(!Dart_IsError(result));
+}
+
static const char* kPackageScheme = "package:";
static bool IsPackageSchemeURL(const char* url_name) {
@@ -558,17 +576,22 @@
#ifndef PRODUCT
Dart_Handle TestCase::SetReloadTestScript(const char* script) {
- Dart_SourceFile* sourcefiles = NULL;
- intptr_t num_files = BuildSourceFilesArray(&sourcefiles, script);
- Dart_KernelCompilationResult compilation_result =
- KernelIsolate::UpdateInMemorySources(num_files, sourcefiles);
- delete[] sourcefiles;
- if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
- Dart_Handle result = Dart_NewApiError(compilation_result.error);
- free(compilation_result.error);
- return result;
- }
- return Api::Success();
+ // For our vm/cc/IsolateReload_* tests we flip the GC flag on, which will
+ // cause the isolate reload to do GCs before/after morphing, etc.
+ FLAG_gc_during_reload = true;
+ FLAG_force_evacuation = true;
+
+ Dart_SourceFile* sourcefiles = NULL;
+ intptr_t num_files = BuildSourceFilesArray(&sourcefiles, script);
+ Dart_KernelCompilationResult compilation_result =
+ KernelIsolate::UpdateInMemorySources(num_files, sourcefiles);
+ delete[] sourcefiles;
+ if (compilation_result.status != Dart_KernelCompilationStatus_Ok) {
+ Dart_Handle result = Dart_NewApiError(compilation_result.error);
+ free(compilation_result.error);
+ return result;
+ }
+ return Api::Success();
}
Dart_Handle TestCase::TriggerReload(const uint8_t* kernel_buffer,
@@ -579,10 +602,11 @@
bool success = false;
{
TransitionNativeToVM transition(thread);
- success = isolate->ReloadKernel(&js,
- false, // force_reload
- kernel_buffer, kernel_buffer_size,
- true); // dont_delete_reload_context
+ success =
+ isolate->group()->ReloadKernel(&js,
+ false, // force_reload
+ kernel_buffer, kernel_buffer_size,
+ true); // dont_delete_reload_context
OS::PrintErr("RELOAD REPORT:\n%s\n", js.ToCString());
}
@@ -593,9 +617,10 @@
if (Dart_IsError(result)) {
// Keep load error.
- } else if (isolate->reload_context()->reload_aborted()) {
+ } else if (isolate->group()->reload_context()->reload_aborted()) {
TransitionNativeToVM transition(thread);
- result = Api::NewHandle(thread, isolate->reload_context()->error());
+ result = Api::NewHandle(
+ thread, isolate->reload_context()->group_reload_context()->error());
} else {
result = Dart_RootLibrary();
}
@@ -603,6 +628,7 @@
TransitionNativeToVM transition(thread);
if (isolate->reload_context() != NULL) {
isolate->DeleteReloadContext();
+ isolate->group()->DeleteReloadContext();
}
return result;
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 947cd15..0d134cd 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -440,6 +440,10 @@
DISALLOW_COPY_AND_ASSIGN(TestIsolateScope);
};
+// Ensures core libraries are initialized, thereby allowing vm/cc tests to
+// e.g. run functions using microtasks.
+void SetupCoreLibrariesForUnitTest();
+
template <typename T>
struct is_void {
static const bool value = false;
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index e637088..33fa0b4 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -690,14 +690,14 @@
visibility = [ ":copy_dev_compiler_sdk" ]
deps = [
":copy_libraries",
- "../utils/dartdevc:dartdevc_kernel_sdk_outline",
+ "../utils/dartdevc:dartdevc_platform",
"../utils/dartdevc:dartdevc_sdk",
]
gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk", "target_gen_dir")
sources = [
# TODO(vsm): Remove post CFE.
"$gen_dir/ddc_sdk.sum",
- "$gen_dir/kernel/ddc_sdk.dill",
+ "$root_out_dir/ddc_sdk.dill",
]
outputs = [
"$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}",
diff --git a/sdk/lib/_http/crypto.dart b/sdk/lib/_http/crypto.dart
index 28b65ee..73f3745 100644
--- a/sdk/lib/_http/crypto.dart
+++ b/sdk/lib/_http/crypto.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.6
+
part of dart._http;
class _CryptoUtils {
diff --git a/sdk/lib/_http/http.dart b/sdk/lib/_http/http.dart
index 2fc751f..855234b 100644
--- a/sdk/lib/_http/http.dart
+++ b/sdk/lib/_http/http.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.6
+
library dart._http;
import 'dart:async';
@@ -126,8 +128,8 @@
* about the streaming qualities of an HttpServer.
* Pausing the subscription of the stream, pauses at the OS level.
*
- * * The [shelf](https://pub.dartlang.org/packages/shelf)
- * package on pub.dartlang.org contains a set of high-level classes that,
+ * * The [shelf](https://pub.dev/packages/shelf)
+ * package on pub.dev contains a set of high-level classes that,
* together with this class, makes it easy to provide content through HTTP
* servers.
*/
@@ -1006,7 +1008,7 @@
* that contains the content of and information about an HTTP request.
*
* __Note__: Check out the
- * [http_server](https://pub.dartlang.org/packages/http_server)
+ * [http_server](https://pub.dev/packages/http_server)
* package, which makes working with the low-level
* dart:io HTTP server subsystem easier.
*
@@ -1402,6 +1404,22 @@
@Deprecated("Use defaultHttpsPort instead")
static const int DEFAULT_HTTPS_PORT = defaultHttpsPort;
+ /// Enable logging of HTTP requests from all [HttpClient]s to the developer
+ /// timeline.
+ ///
+ /// Default is `false`.
+ static set enableTimelineLogging(bool value) {
+ _enableTimelineLogging = value ?? false;
+ }
+
+ /// Current state of HTTP request logging from all [HttpClient]s to the
+ /// developer timeline.
+ ///
+ /// Default is `false`.
+ static bool get enableTimelineLogging => _enableTimelineLogging;
+
+ static bool _enableTimelineLogging = false;
+
/// Gets and sets the idle timeout of non-active persistent (keep-alive)
/// connections.
///
diff --git a/sdk/lib/_http/http_date.dart b/sdk/lib/_http/http_date.dart
index d9301b4..edeb98f 100644
--- a/sdk/lib/_http/http_date.dart
+++ b/sdk/lib/_http/http_date.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.6
+
part of dart._http;
/**
diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart
index d452315..028fd2d 100644
--- a/sdk/lib/_http/http_headers.dart
+++ b/sdk/lib/_http/http_headers.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.6
+
part of dart._http;
class _HttpHeaders implements HttpHeaders {
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index 46611c0..323ea9b 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.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.6
+
part of dart._http;
int _nextServiceId = 1;
@@ -443,7 +445,9 @@
}
Future<HttpClientResponse> _authenticate(bool proxyAuth) {
+ _httpRequest._timeline?.instant('Authentication');
Future<HttpClientResponse> retry() {
+ _httpRequest._timeline?.instant('Retrying');
// Drain body and retry.
return drain().then((_) {
return _httpClient
@@ -1062,6 +1066,7 @@
// The HttpClient this request belongs to.
final _HttpClient _httpClient;
final _HttpClientConnection _httpClientConnection;
+ final TimelineTask _timeline;
final Completer<HttpClientResponse> _responseCompleter =
new Completer<HttpClientResponse>();
@@ -1078,15 +1083,61 @@
List<RedirectInfo> _responseRedirects = [];
_HttpClientRequest(_HttpOutgoing outgoing, Uri uri, this.method, this._proxy,
- this._httpClient, this._httpClientConnection)
+ this._httpClient, this._httpClientConnection, this._timeline)
: uri = uri,
super(uri, "1.1", outgoing) {
+ _timeline?.instant('Request initiated');
// GET and HEAD have 'content-length: 0' by default.
if (method == "GET" || method == "HEAD") {
contentLength = 0;
} else {
headers.chunkedTransferEncoding = true;
}
+
+ _responseCompleter.future.then((response) {
+ _timeline?.instant('Response receieved');
+ Map formatConnectionInfo() => {
+ 'localPort': response.connectionInfo?.localPort,
+ 'remoteAddress': response.connectionInfo?.remoteAddress?.address,
+ 'remotePort': response.connectionInfo?.remotePort,
+ };
+
+ Map formatHeaders() {
+ final headers = <String, List<String>>{};
+ response.headers.forEach((name, values) {
+ headers[name] = values;
+ });
+ return headers;
+ }
+
+ List<Map<String, dynamic>> formatRedirectInfo() {
+ final redirects = <Map<String, dynamic>>[];
+ for (final redirect in response.redirects) {
+ redirects.add({
+ 'location': redirect.location.toString(),
+ 'method': redirect.method,
+ 'statusCode': redirect.statusCode,
+ });
+ }
+ return redirects;
+ }
+
+ _timeline?.finish(arguments: {
+ // TODO(bkonyi): consider exposing certificate information?
+ // 'certificate': response.certificate,
+ 'requestHeaders': outgoing.outbound.headers._headers,
+ 'compressionState': response.compressionState.toString(),
+ 'connectionInfo': formatConnectionInfo(),
+ 'contentLength': response.contentLength,
+ 'cookies': [for (final cookie in response.cookies) cookie.toString()],
+ 'responseHeaders': formatHeaders(),
+ 'isRedirect': response.isRedirect,
+ 'persistentConnection': response.persistentConnection,
+ 'reasonPhrase': response.reasonPhrase,
+ 'redirects': formatRedirectInfo(),
+ 'statusCode': response.statusCode,
+ });
+ }, onError: (e) {});
}
Future<HttpClientResponse> get done {
@@ -1684,7 +1735,8 @@
});
}
- _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) {
+ _HttpClientRequest send(
+ Uri uri, int port, String method, _Proxy proxy, TimelineTask timeline) {
if (closed) {
throw new HttpException("Socket closed before request was sent",
uri: uri);
@@ -1696,8 +1748,8 @@
_SiteCredentials creds; // Credentials used to authorize this request.
var outgoing = new _HttpOutgoing(_socket);
// Create new request object, wrapping the outgoing connection.
- var request =
- new _HttpClientRequest(outgoing, uri, method, proxy, _httpClient, this);
+ var request = new _HttpClientRequest(
+ outgoing, uri, method, proxy, _httpClient, this, timeline);
// For the Host header an IPv6 address must be enclosed in []'s.
var host = uri.host;
if (host.contains(':')) host = "[$host]";
@@ -1732,6 +1784,7 @@
creds.authorize(request);
}
}
+
// Start sending the request (lazy, delayed until the user provides
// data).
_httpParser.isHead = method == "HEAD";
@@ -1825,10 +1878,31 @@
.then((_) => _socket.destroy());
}
- Future<_HttpClientConnection> createProxyTunnel(String host, int port,
- _Proxy proxy, bool callback(X509Certificate certificate)) {
+ Future<_HttpClientConnection> createProxyTunnel(
+ String host,
+ int port,
+ _Proxy proxy,
+ bool callback(X509Certificate certificate),
+ TimelineTask timeline) {
+ timeline?.instant('Establishing proxy tunnel', arguments: {
+ 'proxyInfo': {
+ if (proxy.host != null) 'host': proxy.host,
+ if (proxy.port != null)
+ 'port': proxy.port,
+ if (proxy.username != null)
+ 'username': proxy.username,
+ // TODO(bkonyi): is this something we would want to surface? Initial
+ // thought is no.
+ // if (proxy.password != null)
+ // 'password': proxy.password,
+ 'isDirect': proxy.isDirect,
+ }
+ });
+ final method = "CONNECT";
+ final uri = Uri(host: host, port: port);
+ _HttpClient._startRequestTimelineEvent(timeline, method, uri);
_HttpClientRequest request =
- send(new Uri(host: host, port: port), port, "CONNECT", proxy);
+ send(Uri(host: host, port: port), port, method, proxy, timeline);
if (proxy.isAuthenticated) {
// If the proxy configuration contains user information use that
// for proxy basic authorization.
@@ -1838,10 +1912,10 @@
}
return request.close().then((response) {
if (response.statusCode != HttpStatus.ok) {
- throw new HttpException(
- "Proxy failed to establish tunnel "
- "(${response.statusCode} ${response.reasonPhrase})",
- uri: request.uri);
+ final error = "Proxy failed to establish tunnel "
+ "(${response.statusCode} ${response.reasonPhrase})";
+ timeline?.instant(error);
+ throw new HttpException(error, uri: request.uri);
}
var socket = (response as _HttpClientResponse)
._httpRequest
@@ -1851,6 +1925,7 @@
host: host, context: _context, onBadCertificate: callback);
}).then((secureSocket) {
String key = _HttpClientConnection.makeKey(true, host, port);
+ timeline?.instant('Proxy tunnel established');
return new _HttpClientConnection(
key, secureSocket, request._httpClient, true);
});
@@ -1964,8 +2039,8 @@
}
}
- Future<_ConnectionInfo> connect(
- String uriHost, int uriPort, _Proxy proxy, _HttpClient client) {
+ Future<_ConnectionInfo> connect(String uriHost, int uriPort, _Proxy proxy,
+ _HttpClient client, TimelineTask timeline) {
if (hasIdle) {
var connection = takeIdle();
client._connectionsChanged();
@@ -1975,7 +2050,7 @@
_active.length + _connecting >= client.maxConnectionsPerHost) {
var completer = new Completer<_ConnectionInfo>();
_pending.add(() {
- completer.complete(connect(uriHost, uriPort, proxy, client));
+ completer.complete(connect(uriHost, uriPort, proxy, client, timeline));
});
return completer.future;
}
@@ -2021,7 +2096,7 @@
if (isSecure && !proxy.isDirect) {
connection._dispose = true;
return connection
- .createProxyTunnel(uriHost, uriPort, proxy, callback)
+ .createProxyTunnel(uriHost, uriPort, proxy, callback, timeline)
.then((tunnel) {
client
._getConnectionTarget(uriHost, uriPort, true)
@@ -2175,6 +2250,16 @@
set findProxy(String f(Uri uri)) => _findProxy = f;
+ static void _startRequestTimelineEvent(
+ TimelineTask timeline, String method, Uri uri) {
+ timeline?.start('HTTP CLIENT ${method.toUpperCase()}', arguments: {
+ 'filterKey':
+ 'HTTP/client', // key used to filter network requests from timeline
+ 'method': method.toUpperCase(),
+ 'uri': uri.toString(),
+ });
+ }
+
Future<_HttpClientRequest> _openUrl(String method, Uri uri) {
if (_closing) {
throw new StateError("Client is closed");
@@ -2212,19 +2297,32 @@
return new Future.error(error, stackTrace);
}
}
- return _getConnection(uri.host, port, proxyConf, isSecure)
- .then((_ConnectionInfo info) {
+ TimelineTask timeline;
+ // TODO(bkonyi): do we want this to be opt-in?
+ if (HttpClient.enableTimelineLogging) {
+ timeline = TimelineTask();
+ _startRequestTimelineEvent(timeline, method, uri);
+ }
+ return _getConnection(uri.host, port, proxyConf, isSecure, timeline).then(
+ (_ConnectionInfo info) {
_HttpClientRequest send(_ConnectionInfo info) {
+ timeline?.instant('Connection established');
return info.connection
- .send(uri, port, method.toUpperCase(), info.proxy);
+ .send(uri, port, method.toUpperCase(), info.proxy, timeline);
}
// If the connection was closed before the request was sent, create
// and use another connection.
if (info.connection.closed) {
- return _getConnection(uri.host, port, proxyConf, isSecure).then(send);
+ return _getConnection(uri.host, port, proxyConf, isSecure, timeline)
+ .then(send);
}
return send(info);
+ }, onError: (error) {
+ timeline?.finish(arguments: {
+ 'error': error.toString(),
+ });
+ throw error;
});
}
@@ -2291,7 +2389,7 @@
// Get a new _HttpClientConnection, from the matching _ConnectionTarget.
Future<_ConnectionInfo> _getConnection(String uriHost, int uriPort,
- _ProxyConfiguration proxyConf, bool isSecure) {
+ _ProxyConfiguration proxyConf, bool isSecure, TimelineTask timeline) {
Iterator<_Proxy> proxies = proxyConf.proxies.iterator;
Future<_ConnectionInfo> connect(error) {
@@ -2300,7 +2398,7 @@
String host = proxy.isDirect ? uriHost : proxy.host;
int port = proxy.isDirect ? uriPort : proxy.port;
return _getConnectionTarget(host, port, isSecure)
- .connect(uriHost, uriPort, proxy, this)
+ .connect(uriHost, uriPort, proxy, this, timeline)
// On error, continue with next proxy.
.catchError(connect);
}
diff --git a/sdk/lib/_http/http_parser.dart b/sdk/lib/_http/http_parser.dart
index f0444c2..8ef7ab0 100644
--- a/sdk/lib/_http/http_parser.dart
+++ b/sdk/lib/_http/http_parser.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.6
+
part of dart._http;
// Global constants.
diff --git a/sdk/lib/_http/http_session.dart b/sdk/lib/_http/http_session.dart
index 3907609..30b65af 100644
--- a/sdk/lib/_http/http_session.dart
+++ b/sdk/lib/_http/http_session.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.6
+
part of dart._http;
const String _DART_SESSION_ID = "DARTSESSID";
diff --git a/sdk/lib/_http/overrides.dart b/sdk/lib/_http/overrides.dart
index 7f9e689..4112c3c 100644
--- a/sdk/lib/_http/overrides.dart
+++ b/sdk/lib/_http/overrides.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.6
+
part of dart._http;
final _httpOverridesToken = new Object();
diff --git a/sdk/lib/_http/websocket.dart b/sdk/lib/_http/websocket.dart
index 5a949af..1d27852 100644
--- a/sdk/lib/_http/websocket.dart
+++ b/sdk/lib/_http/websocket.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.6
+
part of dart._http;
/**
diff --git a/sdk/lib/_http/websocket_impl.dart b/sdk/lib/_http/websocket_impl.dart
index ebbce45..c3d08ab 100644
--- a/sdk/lib/_http/websocket_impl.dart
+++ b/sdk/lib/_http/websocket_impl.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.6
+
part of dart._http;
const String _webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
diff --git a/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart b/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart
index 49c7df3..1be2417 100644
--- a/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.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.6
+
// DDC version of sdk/lib/js/dart2js/js_dart2js.dart
/// Low-level support for interoperating with JavaScript.
diff --git a/sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart b/sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
index d0377bb..feda1c1 100644
--- a/sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.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.6
+
/// Utility methods to efficiently manipulate typed JSInterop objects in cases
/// where the name to call is not known at runtime. You should only use these
/// methods when the same effect cannot be achieved with @JS annotations.
diff --git a/sdk/lib/_internal/js_dev_runtime/libraries.dart b/sdk/lib/_internal/js_dev_runtime/libraries.dart
index d5cffa2..b844996 100644
--- a/sdk/lib/_internal/js_dev_runtime/libraries.dart
+++ b/sdk/lib/_internal/js_dev_runtime/libraries.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.6
+
library libraries;
/**
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
index 894aef4..ef0a652 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/async_patch.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.6
+
// Patch file for the dart:async library.
import 'dart:_js_helper' show notNull, patch, ReifyFunctionTypes;
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/cli_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/cli_patch.dart
index b1c3841..b3ba63c 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/cli_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/cli_patch.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.6
+
import 'dart:_js_helper' show patch;
@patch
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart
index daa3bf8..f0f7c9b 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.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.6
+
// Patch file for dart:collection classes.
import 'dart:_foreign_helper' show JS, JSExportName;
import 'dart:_runtime' as dart;
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/convert_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/convert_patch.dart
index 486473b..6b85e67 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/convert_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/convert_patch.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.6
+
// Patch file for dart:convert library.
import 'dart:_js_helper' show argumentErrorValue, patch;
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
index a52e489..af9ae7d 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.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.6
+
// Patch file for dart:core classes.
import "dart:_internal" as _symbol_dev;
import 'dart:_interceptors';
@@ -949,6 +951,9 @@
int _max(int a, int b) => a > b ? a : b;
int _min(int a, int b) => a < b ? a : b;
+/// Empty list used as an initializer for local variables in the `_BigIntImpl`.
+final _dummyList = new Uint16List(0);
+
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -1194,9 +1199,6 @@
return null;
}
- if (radix is! int) {
- throw ArgumentError.value(radix, 'radix', 'is not an integer');
- }
if (radix < 2 || radix > 36) {
throw RangeError.range(radix, 2, 36, 'radix');
}
@@ -1558,8 +1560,7 @@
///
/// Returns 0 if abs(this) == abs(other); a positive number if
/// abs(this) > abs(other); and a negative number if abs(this) < abs(other).
- int _absCompare(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ int _absCompare(_BigIntImpl other) {
return _compareDigits(_digits, _used, other._digits, other._used);
}
@@ -1569,8 +1570,7 @@
* Returns a negative number if `this` is less than `other`, zero if they are
* equal, and a positive number if `this` is greater than `other`.
*/
- int compareTo(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ int compareTo(covariant _BigIntImpl other) {
if (_isNegative == other._isNegative) {
var result = _absCompare(other);
// Use 0 - result to avoid negative zero in JavaScript.
@@ -1712,7 +1712,8 @@
var digits = _digits;
var otherDigits = other._digits;
var resultDigits = Uint16List(resultUsed);
- var l, m;
+ _BigIntImpl l;
+ int m;
if (used < otherUsed) {
l = other;
m = used;
@@ -1738,7 +1739,8 @@
var digits = _digits;
var otherDigits = other._digits;
var resultDigits = Uint16List(resultUsed);
- var l, m;
+ _BigIntImpl l;
+ int m;
if (used < otherUsed) {
l = other;
m = used;
@@ -1766,8 +1768,7 @@
* Of both operands are negative, the result is negative, otherwise
* the result is non-negative.
*/
- _BigIntImpl operator &(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator &(covariant _BigIntImpl other) {
if (_isZero || other._isZero) return zero;
if (_isNegative == other._isNegative) {
if (_isNegative) {
@@ -1782,7 +1783,7 @@
return _absAndSetSign(other, false);
}
// _isNegative != other._isNegative
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1806,8 +1807,7 @@
* If both operands are non-negative, the result is non-negative,
* otherwise the result us negative.
*/
- _BigIntImpl operator |(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator |(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
if (_isNegative == other._isNegative) {
@@ -1823,7 +1823,7 @@
return _absOrSetSign(other, false);
}
// _neg != a._neg
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1848,8 +1848,7 @@
* If the operands have the same sign, the result is non-negative,
* otherwise the result is negative.
*/
- _BigIntImpl operator ^(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator ^(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
if (_isNegative == other._isNegative) {
@@ -1862,7 +1861,7 @@
return _absXorSetSign(other, false);
}
// _isNegative != a._isNegative
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1897,8 +1896,7 @@
}
/// Addition operator.
- _BigIntImpl operator +(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator +(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
var isNegative = _isNegative;
@@ -1916,8 +1914,7 @@
}
/// Subtraction operator.
- _BigIntImpl operator -(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator -(covariant _BigIntImpl other) {
if (_isZero) return -other;
if (other._isZero) return this;
var isNegative = _isNegative;
@@ -1969,8 +1966,7 @@
}
/// Multiplication operator.
- _BigIntImpl operator *(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator *(covariant _BigIntImpl other) {
var used = _used;
var otherUsed = other._used;
if (used == 0 || otherUsed == 0) {
@@ -2018,8 +2014,7 @@
}
/// Returns `trunc(this / other)`, with `other != 0`.
- _BigIntImpl _div(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl _div(_BigIntImpl other) {
assert(other._used > 0);
if (_used < other._used) {
return zero;
@@ -2038,8 +2033,7 @@
}
/// Returns `this - other * trunc(this / other)`, with `other != 0`.
- _BigIntImpl _rem(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl _rem(_BigIntImpl other) {
assert(other._used > 0);
if (_used < other._used) {
return this;
@@ -2239,8 +2233,7 @@
* seven.remainder(-three); // => 1
* ```
*/
- _BigIntImpl operator ~/(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator ~/(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2254,8 +2247,7 @@
* `this == (this ~/ other) * other + r`.
* As a consequence the remainder `r` has the same sign as the divider `this`.
*/
- _BigIntImpl remainder(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl remainder(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2266,16 +2258,16 @@
double operator /(BigInt other) => this.toDouble() / other.toDouble();
/** Relational less than operator. */
- bool operator <(BigInt other) => compareTo(other) < 0;
+ bool operator <(covariant _BigIntImpl other) => compareTo(other) < 0;
/** Relational less than or equal operator. */
- bool operator <=(BigInt other) => compareTo(other) <= 0;
+ bool operator <=(covariant _BigIntImpl other) => compareTo(other) <= 0;
/** Relational greater than operator. */
- bool operator >(BigInt other) => compareTo(other) > 0;
+ bool operator >(covariant _BigIntImpl other) => compareTo(other) > 0;
/** Relational greater than or equal operator. */
- bool operator >=(BigInt other) => compareTo(other) >= 0;
+ bool operator >=(covariant _BigIntImpl other) => compareTo(other) >= 0;
/**
* Euclidean modulo operator.
@@ -2288,8 +2280,7 @@
*
* See [remainder] for the remainder of the truncating division.
*/
- _BigIntImpl operator %(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator %(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2352,9 +2343,8 @@
* The [exponent] must be non-negative and [modulus] must be
* positive.
*/
- _BigIntImpl modPow(BigInt bigExponent, BigInt bigModulus) {
- _BigIntImpl exponent = bigExponent;
- _BigIntImpl modulus = bigModulus;
+ _BigIntImpl modPow(
+ covariant _BigIntImpl exponent, covariant _BigIntImpl modulus) {
if (exponent._isNegative) {
throw ArgumentError("exponent must be positive: $exponent");
}
@@ -2378,7 +2368,7 @@
resultDigits[j] = gDigits[j];
}
var resultUsed = gUsed;
- var result2Used;
+ int result2Used;
for (int i = exponentBitlen - 2; i >= 0; i--) {
result2Used = z.sqr(resultDigits, resultUsed, result2Digits);
if (!(exponent & (one << i))._isZero) {
@@ -2453,19 +2443,19 @@
// Variables a, b, c, and d require one more digit.
final abcdUsed = maxUsed + 1;
final abcdLen = abcdUsed + 2; // +2 to satisfy _absAdd.
- var aDigits, bDigits, cDigits, dDigits;
- bool aIsNegative, bIsNegative, cIsNegative, dIsNegative;
+ var aDigits = _dummyList;
+ var aIsNegative = false;
+ var cDigits = _dummyList;
+ var cIsNegative = false;
if (ac) {
aDigits = Uint16List(abcdLen);
- aIsNegative = false;
aDigits[0] = 1;
cDigits = Uint16List(abcdLen);
- cIsNegative = false;
}
- bDigits = Uint16List(abcdLen);
- bIsNegative = false;
- dDigits = Uint16List(abcdLen);
- dIsNegative = false;
+ var bDigits = Uint16List(abcdLen);
+ var bIsNegative = false;
+ var dDigits = Uint16List(abcdLen);
+ var dIsNegative = false;
dDigits[0] = 1;
while (true) {
@@ -2658,8 +2648,7 @@
* It is an error if no modular inverse exists.
*/
// Returns 1/this % modulus, with modulus > 0.
- _BigIntImpl modInverse(BigInt bigInt) {
- _BigIntImpl modulus = bigInt;
+ _BigIntImpl modInverse(covariant _BigIntImpl modulus) {
if (modulus <= zero) {
throw ArgumentError("Modulus must be strictly positive: $modulus");
}
@@ -2684,8 +2673,7 @@
*
* If both `this` and `other` is zero, the result is also zero.
*/
- _BigIntImpl gcd(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl gcd(covariant _BigIntImpl other) {
if (_isZero) return other.abs();
if (other._isZero) return this.abs();
return _binaryGcd(this, other, false);
@@ -3004,8 +2992,8 @@
_modulus._digits[_modulus._used - 1].bitLength);
int convert(_BigIntImpl x, Uint16List resultDigits) {
- var digits;
- var used;
+ Uint16List digits;
+ int used;
if (x._isNegative || x._absCompare(_modulus) >= 0) {
var remainder = x._rem(_modulus);
if (x._isNegative && remainder._used > 0) {
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart
index 7f5e4fe..954f09e 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/developer_patch.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.6
+
// Patch file for dart:developer library.
import 'dart:_js_helper' show patch, ForceInline, ReifyFunctionTypes;
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
index 5e850bb..6ab2349 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.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.6
+
import 'dart:core' hide Symbol;
import 'dart:core' as core show Symbol;
import 'dart:_js_primitives' show printString;
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
index fcdaa65..514ffcb 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.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.6
+
import 'dart:_js_helper' show patch;
import 'dart:async';
import 'dart:convert';
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/isolate_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/isolate_patch.dart
index f6aa73bb..93e4165 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/isolate_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/isolate_patch.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.6
+
// Patch file for the dart:isolate library.
import 'dart:_js_helper' show patch, NoReifyGeneric;
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/math_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/math_patch.dart
index 2ba4220..c2363f7 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/math_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/math_patch.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.6
+
// Patch file for dart:math library.
import 'dart:_foreign_helper' show JS;
import 'dart:_js_helper' show patch, nullCheck, notNull;
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart
index e3b015b..7795c8f 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/mirrors_patch.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.6
+
// Patch library for dart:mirrors.
import 'dart:_js_helper' show patch;
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart
index f1e2dc1..ab74676 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.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.6
+
import 'dart:collection';
import 'dart:_js_helper' show patch;
import 'dart:_native_typed_data';
diff --git a/sdk/lib/_internal/js_dev_runtime/private/annotations.dart b/sdk/lib/_internal/js_dev_runtime/private/annotations.dart
index bc437da..feac26e 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/annotations.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/annotations.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.6
+
part of dart._js_helper;
/// Tells the optimizing compiler to always inline the annotated method.
diff --git a/sdk/lib/_internal/js_dev_runtime/private/custom_hash_map.dart b/sdk/lib/_internal/js_dev_runtime/private/custom_hash_map.dart
index c7c920d..c387062 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/custom_hash_map.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/custom_hash_map.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.6
+
part of dart._js_helper;
class CustomKeyHashMap<K, V> extends CustomHashMap<K, V> {
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
index 1fe79ab..ac6ad55 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.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.6
+
/// This library defines the operations that define and manipulate Dart
/// classes. Included in this are:
/// - Generics
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
index f875336..4a5813d 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.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.6
+
part of dart._runtime;
// We need to set these properties while the sdk is only partially initialized
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index e388cd6..eac2648 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.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.6
+
/// This library defines runtime operations on objects used by the code
/// generator.
part of dart._runtime;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
index 34c66e2..a869a3f 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/rtti.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.6
+
/// This library defines the association between runtime objects and
/// runtime types.
part of dart._runtime;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
index 1c6ce56..68eef6d 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.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.6
+
@ReifyFunctionTypes(false)
library dart._runtime;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 4456041..7931294 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.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.6
+
/// This library defines the representation of runtime types.
part of dart._runtime;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart
index 2c06179..c691cfd 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/utils.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.6
+
part of dart._runtime;
/// This library defines a set of general javascript utilities for us
diff --git a/sdk/lib/_internal/js_dev_runtime/private/debugger.dart b/sdk/lib/_internal/js_dev_runtime/private/debugger.dart
index 4618317..9bdca7a 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/debugger.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/debugger.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.6
+
library dart._debugger;
import 'dart:_foreign_helper' show JS;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart
index 588d789..b46e817 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/foreign_helper.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.6
+
library dart._foreign_helper;
/**
diff --git a/sdk/lib/_internal/js_dev_runtime/private/identity_hash_map.dart b/sdk/lib/_internal/js_dev_runtime/private/identity_hash_map.dart
index 04107cc..fa62a8f 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/identity_hash_map.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/identity_hash_map.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.6
+
part of dart._js_helper;
class IdentityMap<K, V> extends InternalMap<K, V> {
diff --git a/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart b/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
index 6ddd96b..db81230 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/interceptors.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/interceptors.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.6
+
library dart._interceptors;
import 'dart:collection';
diff --git a/sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart
index 9132848..78e8e19 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/isolate_helper.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.6
+
library dart._isolate_helper;
import 'dart:_runtime' as dart;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_array.dart b/sdk/lib/_internal/js_dev_runtime/private/js_array.dart
index f064b24..2d33e74 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_array.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_array.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.6
+
part of dart._interceptors;
/**
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
index 5d6b037..94ef1de 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_helper.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.6
+
library dart._js_helper;
import 'dart:collection';
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_mirrors.dart b/sdk/lib/_internal/js_dev_runtime/private/js_mirrors.dart
index a93f5fb..38402be 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_mirrors.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_mirrors.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.6
+
library dart._js_mirrors;
import 'dart:mirrors';
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_number.dart b/sdk/lib/_internal/js_dev_runtime/private/js_number.dart
index 5f8c7e0..3d974a7 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_number.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_number.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.6
+
part of dart._interceptors;
/**
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_primitives.dart b/sdk/lib/_internal/js_dev_runtime/private/js_primitives.dart
index 1347b62..f6c0c59 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_primitives.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_primitives.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.6
+
/// dart2js "primitives", that is, features that cannot be implemented without
/// access to JavaScript features.
library dart2js._js_primitives;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_rti.dart b/sdk/lib/_internal/js_dev_runtime/private/js_rti.dart
index 015c83e..e058820 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_rti.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_rti.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.6
+
part of dart._js_helper;
// TODO(leafp): Maybe get rid of this? Currently used by the interceptors
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_string.dart b/sdk/lib/_internal/js_dev_runtime/private/js_string.dart
index 4271d34..de63d0a 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_string.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_string.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.6
+
part of dart._interceptors;
/**
diff --git a/sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart b/sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart
index 1c03db8..d9051f4 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.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.6
+
// Efficient JavaScript based implementation of a linked hash map used as a
// backing map for constant maps and the [LinkedHashMap] patch
diff --git a/sdk/lib/_internal/js_dev_runtime/private/mirror_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/mirror_helper.dart
index f78926a..dc635a9 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/mirror_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/mirror_helper.dart
@@ -1,6 +1,8 @@
// Copyright (c) 2013, 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.
+// @dart = 2.6
+
/**
* Helps dealing with reflection in the case that the source code has been
* changed as a result of compiling with dart2dart.
diff --git a/sdk/lib/_internal/js_dev_runtime/private/native_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/native_helper.dart
index cc214e8..d7a312c1 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/native_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/native_helper.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.6
+
part of dart._js_helper;
// Obsolete in dart dev compiler. Added only so that the same version of
diff --git a/sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart b/sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart
index 2a7a621..a444d0c 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/native_typed_data.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.6
+
/**
* Specialized integers and floating point numbers,
* with SIMD support and efficient lists.
diff --git a/sdk/lib/_internal/js_dev_runtime/private/profile.dart b/sdk/lib/_internal/js_dev_runtime/private/profile.dart
index d46f7f7..0b30862 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/profile.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/profile.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.6
+
/// This file supports profiling dynamic calls.
part of dart._debugger;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
index 6eeee38..0a02d3f 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.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.6
+
part of dart._js_helper;
// Helper method used by internal libraries.
diff --git a/sdk/lib/_internal/js_dev_runtime/private/string_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/string_helper.dart
index c1b5c18..326af11 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/string_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/string_helper.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.6
+
part of dart._js_helper;
@notNull
diff --git a/sdk/lib/_internal/js_runtime/lib/annotations.dart b/sdk/lib/_internal/js_runtime/lib/annotations.dart
index f53c5f3..971d2bd 100644
--- a/sdk/lib/_internal/js_runtime/lib/annotations.dart
+++ b/sdk/lib/_internal/js_runtime/lib/annotations.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.6
+
part of _js_helper;
/// Marks a class as native and defines its JavaScript name(s).
diff --git a/sdk/lib/_internal/js_runtime/lib/async_patch.dart b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
index 68bcbeb..de08681 100644
--- a/sdk/lib/_internal/js_runtime/lib/async_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/async_patch.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.6
+
// Patch file for the dart:async library.
import 'dart:_js_helper'
diff --git a/sdk/lib/_internal/js_runtime/lib/cli_patch.dart b/sdk/lib/_internal/js_runtime/lib/cli_patch.dart
index 6921e60..7f02085 100644
--- a/sdk/lib/_internal/js_runtime/lib/cli_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/cli_patch.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.6
+
import 'dart:_js_helper' show patch;
@patch
diff --git a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
index 300d490..604097f 100644
--- a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/collection_patch.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.6
+
// Patch file for dart:collection classes.
import 'dart:_foreign_helper' show JS;
import 'dart:_js_helper'
diff --git a/sdk/lib/_internal/js_runtime/lib/constant_map.dart b/sdk/lib/_internal/js_runtime/lib/constant_map.dart
index f7c7936..fce8922 100644
--- a/sdk/lib/_internal/js_runtime/lib/constant_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/constant_map.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.6
+
part of _js_helper;
class ConstantMapView<K, V> extends UnmodifiableMapView<K, V>
diff --git a/sdk/lib/_internal/js_runtime/lib/convert_patch.dart b/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
index fa6a0b0..421fd51 100644
--- a/sdk/lib/_internal/js_runtime/lib/convert_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/convert_patch.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.6
+
// Patch file for dart:convert library.
import 'dart:_js_helper' show argumentErrorValue, patch;
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index ec8dbc4..2f9c880 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.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.6
+
// Patch file for dart:core classes.
import "dart:_internal" hide Symbol, LinkedList, LinkedListEntry;
import "dart:_internal" as _symbol_dev;
@@ -855,6 +857,9 @@
int _max(int a, int b) => a > b ? a : b;
int _min(int a, int b) => a < b ? a : b;
+/// Empty list used as an initializer for local variables in the `_BigIntImpl`.
+final _dummyList = new Uint16List(0);
+
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -1453,8 +1458,7 @@
///
/// Returns 0 if abs(this) == abs(other); a positive number if
/// abs(this) > abs(other); and a negative number if abs(this) < abs(other).
- int _absCompare(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ int _absCompare(_BigIntImpl other) {
return _compareDigits(_digits, _used, other._digits, other._used);
}
@@ -1462,8 +1466,7 @@
///
/// Returns a negative number if `this` is less than `other`, zero if they are
/// equal, and a positive number if `this` is greater than `other`.
- int compareTo(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ int compareTo(covariant _BigIntImpl other) {
if (_isNegative == other._isNegative) {
var result = _absCompare(other);
// Use 0 - result to avoid negative zero in JavaScript.
@@ -1605,7 +1608,8 @@
var digits = _digits;
var otherDigits = other._digits;
var resultDigits = new Uint16List(resultUsed);
- var l, m;
+ _BigIntImpl l;
+ int m;
if (used < otherUsed) {
l = other;
m = used;
@@ -1631,7 +1635,8 @@
var digits = _digits;
var otherDigits = other._digits;
var resultDigits = new Uint16List(resultUsed);
- var l, m;
+ _BigIntImpl l;
+ int m;
if (used < otherUsed) {
l = other;
m = used;
@@ -1657,8 +1662,7 @@
///
/// Of both operands are negative, the result is negative, otherwise
/// the result is non-negative.
- _BigIntImpl operator &(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator &(covariant _BigIntImpl other) {
if (_isZero || other._isZero) return zero;
if (_isNegative == other._isNegative) {
if (_isNegative) {
@@ -1673,7 +1677,7 @@
return _absAndSetSign(other, false);
}
// _isNegative != other._isNegative
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1695,8 +1699,7 @@
///
/// If both operands are non-negative, the result is non-negative,
/// otherwise the result us negative.
- _BigIntImpl operator |(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator |(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
if (_isNegative == other._isNegative) {
@@ -1712,7 +1715,7 @@
return _absOrSetSign(other, false);
}
// _neg != a._neg
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1735,8 +1738,7 @@
///
/// If the operands have the same sign, the result is non-negative,
/// otherwise the result is negative.
- _BigIntImpl operator ^(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator ^(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
if (_isNegative == other._isNegative) {
@@ -1749,7 +1751,7 @@
return _absXorSetSign(other, false);
}
// _isNegative != a._isNegative
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1782,8 +1784,7 @@
}
/// Addition operator.
- _BigIntImpl operator +(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator +(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
var isNegative = _isNegative;
@@ -1801,8 +1802,7 @@
}
/// Subtraction operator.
- _BigIntImpl operator -(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator -(covariant _BigIntImpl other) {
if (_isZero) return -other;
if (other._isZero) return this;
var isNegative = _isNegative;
@@ -1854,8 +1854,7 @@
}
/// Multiplication operator.
- _BigIntImpl operator *(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator *(covariant _BigIntImpl other) {
var used = _used;
var otherUsed = other._used;
if (used == 0 || otherUsed == 0) {
@@ -1903,8 +1902,7 @@
}
/// Returns `trunc(this / other)`, with `other != 0`.
- _BigIntImpl _div(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl _div(_BigIntImpl other) {
assert(other._used > 0);
if (_used < other._used) {
return zero;
@@ -1923,8 +1921,7 @@
}
/// Returns `this - other * trunc(this / other)`, with `other != 0`.
- _BigIntImpl _rem(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl _rem(_BigIntImpl other) {
assert(other._used > 0);
if (_used < other._used) {
return this;
@@ -2118,8 +2115,7 @@
/// (-seven).remainder(three); // => -1
/// seven.remainder(-three); // => 1
/// ```
- _BigIntImpl operator ~/(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator ~/(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2132,8 +2128,7 @@
/// `this == (this ~/ other) * other + r`.
/// As a consequence the remainder `r` has the same sign as the divider
/// `this`.
- _BigIntImpl remainder(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl remainder(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2144,16 +2139,16 @@
double operator /(BigInt other) => this.toDouble() / other.toDouble();
/// Relational less than operator.
- bool operator <(BigInt other) => compareTo(other) < 0;
+ bool operator <(covariant _BigIntImpl other) => compareTo(other) < 0;
/// Relational less than or equal operator.
- bool operator <=(BigInt other) => compareTo(other) <= 0;
+ bool operator <=(covariant _BigIntImpl other) => compareTo(other) <= 0;
/// Relational greater than operator.
- bool operator >(BigInt other) => compareTo(other) > 0;
+ bool operator >(covariant _BigIntImpl other) => compareTo(other) > 0;
/// Relational greater than or equal operator.
- bool operator >=(BigInt other) => compareTo(other) >= 0;
+ bool operator >=(covariant _BigIntImpl other) => compareTo(other) >= 0;
/// Euclidean modulo operator.
///
@@ -2164,8 +2159,7 @@
/// The sign of the returned value `r` is always positive.
///
/// See [remainder] for the remainder of the truncating division.
- _BigIntImpl operator %(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator %(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2224,9 +2218,8 @@
///
/// The [exponent] must be non-negative and [modulus] must be
/// positive.
- _BigIntImpl modPow(BigInt bigExponent, BigInt bigModulus) {
- _BigIntImpl exponent = bigExponent;
- _BigIntImpl modulus = bigModulus;
+ _BigIntImpl modPow(
+ covariant _BigIntImpl exponent, covariant _BigIntImpl modulus) {
if (exponent._isNegative) {
throw new ArgumentError("exponent must be positive: $exponent");
}
@@ -2250,7 +2243,7 @@
resultDigits[j] = gDigits[j];
}
var resultUsed = gUsed;
- var result2Used;
+ int result2Used;
for (int i = exponentBitlen - 2; i >= 0; i--) {
result2Used = z.sqr(resultDigits, resultUsed, result2Digits);
if (!(exponent & (one << i))._isZero) {
@@ -2325,19 +2318,19 @@
// Variables a, b, c, and d require one more digit.
final abcdUsed = maxUsed + 1;
final abcdLen = abcdUsed + 2; // +2 to satisfy _absAdd.
- var aDigits, bDigits, cDigits, dDigits;
- bool aIsNegative, bIsNegative, cIsNegative, dIsNegative;
+ var aDigits = _dummyList;
+ var aIsNegative = false;
+ var cDigits = _dummyList;
+ var cIsNegative = false;
if (ac) {
aDigits = new Uint16List(abcdLen);
- aIsNegative = false;
aDigits[0] = 1;
cDigits = new Uint16List(abcdLen);
- cIsNegative = false;
}
- bDigits = new Uint16List(abcdLen);
- bIsNegative = false;
- dDigits = new Uint16List(abcdLen);
- dIsNegative = false;
+ var bDigits = new Uint16List(abcdLen);
+ var bIsNegative = false;
+ var dDigits = new Uint16List(abcdLen);
+ var dIsNegative = false;
dDigits[0] = 1;
while (true) {
@@ -2528,8 +2521,7 @@
///
/// It is an error if no modular inverse exists.
// Returns 1/this % modulus, with modulus > 0.
- _BigIntImpl modInverse(BigInt bigInt) {
- _BigIntImpl modulus = bigInt;
+ _BigIntImpl modInverse(covariant _BigIntImpl modulus) {
if (modulus <= zero) {
throw new ArgumentError("Modulus must be strictly positive: $modulus");
}
@@ -2552,8 +2544,7 @@
/// For any integer `x`, `x.gcd(x)` is `x.abs()`.
///
/// If both `this` and `other` is zero, the result is also zero.
- _BigIntImpl gcd(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl gcd(covariant _BigIntImpl other) {
if (_isZero) return other.abs();
if (other._isZero) return this.abs();
return _binaryGcd(this, other, false);
@@ -2863,8 +2854,8 @@
_modulus._digits[_modulus._used - 1].bitLength);
int convert(_BigIntImpl x, Uint16List resultDigits) {
- var digits;
- var used;
+ Uint16List digits;
+ int used;
if (x._isNegative || x._absCompare(_modulus) >= 0) {
var remainder = x._rem(_modulus);
if (x._isNegative && remainder._used > 0) {
diff --git a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart b/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
index 0ff0f66..6156f5e 100644
--- a/sdk/lib/_internal/js_runtime/lib/developer_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/developer_patch.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.6
+
// Patch file for dart:developer library.
import 'dart:_js_helper' show patch, ForceInline;
diff --git a/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart b/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
index 0cecf96..f2a7c77 100644
--- a/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/foreign_helper.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.6
+
library _foreign_helper;
import 'dart:_js_embedded_names' show JsGetName, JsBuiltin;
diff --git a/sdk/lib/_internal/js_runtime/lib/instantiation.dart b/sdk/lib/_internal/js_runtime/lib/instantiation.dart
index bb003e6..666cd69 100644
--- a/sdk/lib/_internal/js_runtime/lib/instantiation.dart
+++ b/sdk/lib/_internal/js_runtime/lib/instantiation.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.6
+
part of _js_helper;
/// Support class for generic function type instantiation (binding of types).
diff --git a/sdk/lib/_internal/js_runtime/lib/interceptors.dart b/sdk/lib/_internal/js_runtime/lib/interceptors.dart
index b676c1b..e0aa397 100644
--- a/sdk/lib/_internal/js_runtime/lib/interceptors.dart
+++ b/sdk/lib/_internal/js_runtime/lib/interceptors.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.6
+
library _interceptors;
import 'dart:_js_embedded_names'
diff --git a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
index 77884e2..7e3b456 100644
--- a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/internal_patch.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.6
+
import 'dart:core' hide Symbol;
import 'dart:core' as core;
import 'dart:_js_primitives' show printString;
diff --git a/sdk/lib/_internal/js_runtime/lib/io_patch.dart b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
index ee1eb4d..37aa15c 100644
--- a/sdk/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/io_patch.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.6
+
import 'dart:_js_helper' show patch;
import 'dart:_internal' hide Symbol;
import 'dart:async';
diff --git a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
index d781e7a..bb6363f 100644
--- a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/isolate_patch.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.6
+
// Patch file for the dart:isolate library.
import "dart:async";
diff --git a/sdk/lib/_internal/js_runtime/lib/js_array.dart b/sdk/lib/_internal/js_runtime/lib/js_array.dart
index ff820d4..7b92c3d 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_array.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_array.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.6
+
part of _interceptors;
class _Growable {
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index a9fd83b..4f332f4 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.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.6
+
library _js_helper;
import 'dart:_js_embedded_names'
diff --git a/sdk/lib/_internal/js_runtime/lib/js_names.dart b/sdk/lib/_internal/js_runtime/lib/js_names.dart
index cb4aa0e..767eced 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_names.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_names.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.6
+
library dart._js_names;
import 'dart:_js_embedded_names'
diff --git a/sdk/lib/_internal/js_runtime/lib/js_number.dart b/sdk/lib/_internal/js_runtime/lib/js_number.dart
index 918c1ba..610312b 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_number.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_number.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.6
+
part of _interceptors;
/// The super interceptor class for [JSInt] and [JSDouble]. The compiler
diff --git a/sdk/lib/_internal/js_runtime/lib/js_primitives.dart b/sdk/lib/_internal/js_runtime/lib/js_primitives.dart
index 97577a0..5422333 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_primitives.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_primitives.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.6
+
/// dart2js "primitives", that is, features that cannot be implemented without
/// access to JavaScript features.
library dart2js._js_primitives;
diff --git a/sdk/lib/_internal/js_runtime/lib/js_rti.dart b/sdk/lib/_internal/js_runtime/lib/js_rti.dart
index 762cd88..056e267 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_rti.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.6
+
/// This part contains helpers for supporting runtime type information.
///
/// The helper use a mixture of Dart and JavaScript objects. To indicate which
diff --git a/sdk/lib/_internal/js_runtime/lib/js_string.dart b/sdk/lib/_internal/js_runtime/lib/js_string.dart
index 39370d7..d6af957 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_string.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_string.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.6
+
part of _interceptors;
/// The interceptor class for [String]. The compiler recognizes this
diff --git a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
index 42ad0c4..dab8542 100644
--- a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.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.6
+
// Efficient JavaScript based implementation of a linked hash map used as a
// backing map for constant maps and the [LinkedHashMap] patch
diff --git a/sdk/lib/_internal/js_runtime/lib/math_patch.dart b/sdk/lib/_internal/js_runtime/lib/math_patch.dart
index 677953e..fc33945 100644
--- a/sdk/lib/_internal/js_runtime/lib/math_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/math_patch.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.6
+
// Patch file for dart:math library.
import 'dart:_foreign_helper' show JS;
import 'dart:_js_helper' show patch, checkNum;
diff --git a/sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart b/sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
index 6f8018a..767de5f 100644
--- a/sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
+++ b/sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.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.6
+
// Patch library for dart:mirrors.
import 'dart:_js_helper' show patch;
diff --git a/sdk/lib/_internal/js_runtime/lib/native_helper.dart b/sdk/lib/_internal/js_runtime/lib/native_helper.dart
index ccfa26f..d8d4e1d 100644
--- a/sdk/lib/_internal/js_runtime/lib/native_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/native_helper.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.6
+
part of _js_helper;
// TODO(ngeoffray): stop using this method once our optimizers can
diff --git a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
index 0a91641..db57ca3 100644
--- a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
+++ b/sdk/lib/_internal/js_runtime/lib/native_typed_data.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.6
+
/// Specialized integers and floating point numbers,
/// with SIMD support and efficient lists.
library dart.typed_data.implementation;
diff --git a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
index 3dacc06..576caaa 100644
--- a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/regexp_helper.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.6
+
part of _js_helper;
// Helper method used by internal libraries.
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index 5a8d3b9..8174aea 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.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.6
+
/// This library contains support for runtime type information.
library rti;
diff --git a/sdk/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart b/sdk/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart
index f87406b..5bcc512 100644
--- a/sdk/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart
+++ b/sdk/lib/_internal/js_runtime/lib/shared/async_await_error_codes.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.6
+
/// Contains error codes that transformed async/async* functions use to
/// communicate with js_helper functions.
diff --git a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
index 8456b8b..0ac7488 100644
--- a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
+++ b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.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.6
+
/// Contains the names of globals that are embedded into the output by the
/// compiler.
///
diff --git a/sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart b/sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart
index ef7fbff..3b35902 100644
--- a/sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart
+++ b/sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.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.6
+
/// Constants and predicates used for encoding and decoding type recipes.
///
/// This library is shared between the compiler and the runtime system.
diff --git a/sdk/lib/_internal/js_runtime/lib/string_helper.dart b/sdk/lib/_internal/js_runtime/lib/string_helper.dart
index ea5374e..eff8783 100644
--- a/sdk/lib/_internal/js_runtime/lib/string_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/string_helper.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.6
+
part of _js_helper;
stringIndexOfStringUnchecked(receiver, other, startIndex) {
diff --git a/sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart b/sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart
index 615c9da..a4a93ab 100644
--- a/sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/typed_data_patch.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.6
+
import 'dart:_js_helper' show patch;
import 'dart:_native_typed_data';
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index ffb8ed3..14b5e23 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.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.6
+
library libraries;
/**
diff --git a/sdk/lib/_internal/vm/bin/builtin.dart b/sdk/lib/_internal/vm/bin/builtin.dart
index 23c5dc7..dde9727 100644
--- a/sdk/lib/_internal/vm/bin/builtin.dart
+++ b/sdk/lib/_internal/vm/bin/builtin.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.6
+
library builtin;
// NOTE: Do not import 'dart:io' in builtin.
diff --git a/sdk/lib/_internal/vm/bin/cli_patch.dart b/sdk/lib/_internal/vm/bin/cli_patch.dart
index 504a0db..0ccae81 100644
--- a/sdk/lib/_internal/vm/bin/cli_patch.dart
+++ b/sdk/lib/_internal/vm/bin/cli_patch.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.6
+
import "dart:_internal" show patch;
@patch
diff --git a/sdk/lib/_internal/vm/bin/common_patch.dart b/sdk/lib/_internal/vm/bin/common_patch.dart
index 1bcd089..1b69371 100644
--- a/sdk/lib/_internal/vm/bin/common_patch.dart
+++ b/sdk/lib/_internal/vm/bin/common_patch.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:io" which contains all the imports used by
/// patches of that library. We plan to change this when we have a shared front
diff --git a/sdk/lib/_internal/vm/bin/directory_patch.dart b/sdk/lib/_internal/vm/bin/directory_patch.dart
index 7549f72..c6b7806 100644
--- a/sdk/lib/_internal/vm/bin/directory_patch.dart
+++ b/sdk/lib/_internal/vm/bin/directory_patch.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.6
+
// part of "common_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/bin/eventhandler_patch.dart b/sdk/lib/_internal/vm/bin/eventhandler_patch.dart
index 11ada47..1b5c5c8 100644
--- a/sdk/lib/_internal/vm/bin/eventhandler_patch.dart
+++ b/sdk/lib/_internal/vm/bin/eventhandler_patch.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.6
+
// part of "common_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/bin/file_patch.dart b/sdk/lib/_internal/vm/bin/file_patch.dart
index a404aa0..01681f4 100644
--- a/sdk/lib/_internal/vm/bin/file_patch.dart
+++ b/sdk/lib/_internal/vm/bin/file_patch.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.6
+
// part of "common_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart b/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart
index 973e6b6..1f081c7 100644
--- a/sdk/lib/_internal/vm/bin/file_system_entity_patch.dart
+++ b/sdk/lib/_internal/vm/bin/file_system_entity_patch.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.6
+
// part of "common_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/bin/filter_patch.dart b/sdk/lib/_internal/vm/bin/filter_patch.dart
index 6f556b6..0594b6b 100644
--- a/sdk/lib/_internal/vm/bin/filter_patch.dart
+++ b/sdk/lib/_internal/vm/bin/filter_patch.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.6
+
// part of "common_patch.dart";
class _FilterImpl extends NativeFieldWrapperClass1 implements RawZLibFilter {
diff --git a/sdk/lib/_internal/vm/bin/io_service_patch.dart b/sdk/lib/_internal/vm/bin/io_service_patch.dart
index d763ebb..5159869 100644
--- a/sdk/lib/_internal/vm/bin/io_service_patch.dart
+++ b/sdk/lib/_internal/vm/bin/io_service_patch.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.6
+
// part of "common_patch.dart";
class _IOServicePorts {
diff --git a/sdk/lib/_internal/vm/bin/namespace_patch.dart b/sdk/lib/_internal/vm/bin/namespace_patch.dart
index d8b7295..60bbb5e 100644
--- a/sdk/lib/_internal/vm/bin/namespace_patch.dart
+++ b/sdk/lib/_internal/vm/bin/namespace_patch.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.6
+
@pragma("vm:entry-point")
class _NamespaceImpl extends NativeFieldWrapperClass1 implements _Namespace {
_NamespaceImpl._();
diff --git a/sdk/lib/_internal/vm/bin/platform_patch.dart b/sdk/lib/_internal/vm/bin/platform_patch.dart
index 99b4e7c..a9c1040 100644
--- a/sdk/lib/_internal/vm/bin/platform_patch.dart
+++ b/sdk/lib/_internal/vm/bin/platform_patch.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.6
+
// part of "common_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/bin/process_patch.dart b/sdk/lib/_internal/vm/bin/process_patch.dart
index 86b6de3..7fc67dc 100644
--- a/sdk/lib/_internal/vm/bin/process_patch.dart
+++ b/sdk/lib/_internal/vm/bin/process_patch.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.6
+
// part of "common_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/bin/secure_socket_patch.dart b/sdk/lib/_internal/vm/bin/secure_socket_patch.dart
index 80dfd54..117f90f 100644
--- a/sdk/lib/_internal/vm/bin/secure_socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/secure_socket_patch.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.6
+
// part of "common_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index b0ce8e6..5771c76 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.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.6
+
// part of "common_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/bin/stdio_patch.dart b/sdk/lib/_internal/vm/bin/stdio_patch.dart
index ca8f16e..1303573 100644
--- a/sdk/lib/_internal/vm/bin/stdio_patch.dart
+++ b/sdk/lib/_internal/vm/bin/stdio_patch.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.6
+
// part of "common_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/bin/sync_socket_patch.dart b/sdk/lib/_internal/vm/bin/sync_socket_patch.dart
index 332d772..d98649e 100644
--- a/sdk/lib/_internal/vm/bin/sync_socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/sync_socket_patch.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.6
+
// part of "common_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/array.dart b/sdk/lib/_internal/vm/lib/array.dart
index 57e1624..1b75894 100644
--- a/sdk/lib/_internal/vm/lib/array.dart
+++ b/sdk/lib/_internal/vm/lib/array.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.6
+
// part of "core_patch.dart";
@pragma("vm:entry-point")
diff --git a/sdk/lib/_internal/vm/lib/array_patch.dart b/sdk/lib/_internal/vm/lib/array_patch.dart
index 5c308a2..26e6865 100644
--- a/sdk/lib/_internal/vm/lib/array_patch.dart
+++ b/sdk/lib/_internal/vm/lib/array_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index c1143fb7..7e9aff7 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:async" which contains all the imports used
/// by patches of that library. We plan to change this when we have a shared
diff --git a/sdk/lib/_internal/vm/lib/bigint_patch.dart b/sdk/lib/_internal/vm/lib/bigint_patch.dart
index e49305d..61958dc 100644
--- a/sdk/lib/_internal/vm/lib/bigint_patch.dart
+++ b/sdk/lib/_internal/vm/lib/bigint_patch.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.6
+
// part of dart.core;
// Copyright 2009 The Go Authors. All rights reserved.
diff --git a/sdk/lib/_internal/vm/lib/bool_patch.dart b/sdk/lib/_internal/vm/lib/bool_patch.dart
index 8fffd63..a969c02 100644
--- a/sdk/lib/_internal/vm/lib/bool_patch.dart
+++ b/sdk/lib/_internal/vm/lib/bool_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/class_id.dart b/sdk/lib/_internal/vm/lib/class_id.dart
index ff9d0b6..c1e8621 100644
--- a/sdk/lib/_internal/vm/lib/class_id.dart
+++ b/sdk/lib/_internal/vm/lib/class_id.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.6
+
// part of "internal_patch.dart";
@pragma("vm:entry-point")
diff --git a/sdk/lib/_internal/vm/lib/class_id_fasta.dart b/sdk/lib/_internal/vm/lib/class_id_fasta.dart
index c95930f..8732d2e 100644
--- a/sdk/lib/_internal/vm/lib/class_id_fasta.dart
+++ b/sdk/lib/_internal/vm/lib/class_id_fasta.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.6
+
// part of "internal_patch.dart";
@pragma("vm:entry-point")
diff --git a/sdk/lib/_internal/vm/lib/collection_patch.dart b/sdk/lib/_internal/vm/lib/collection_patch.dart
index 83f12ca..5364eb5 100644
--- a/sdk/lib/_internal/vm/lib/collection_patch.dart
+++ b/sdk/lib/_internal/vm/lib/collection_patch.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:collection" which contains all the imports
/// used by patches of that library. We plan to change this when we have a
diff --git a/sdk/lib/_internal/vm/lib/compact_hash.dart b/sdk/lib/_internal/vm/lib/compact_hash.dart
index f9ccfc0..112b9ba 100644
--- a/sdk/lib/_internal/vm/lib/compact_hash.dart
+++ b/sdk/lib/_internal/vm/lib/compact_hash.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.6
+
// part of "collection_patch.dart";
// Hash table with open addressing that separates the index from keys/values.
diff --git a/sdk/lib/_internal/vm/lib/convert_patch.dart b/sdk/lib/_internal/vm/lib/convert_patch.dart
index 747e1e3..d2c5f45 100644
--- a/sdk/lib/_internal/vm/lib/convert_patch.dart
+++ b/sdk/lib/_internal/vm/lib/convert_patch.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:convert" which contains all the imports
/// used by patches of that library. We plan to change this when we have a
diff --git a/sdk/lib/_internal/vm/lib/core_patch.dart b/sdk/lib/_internal/vm/lib/core_patch.dart
index c095178..eaf9d93 100644
--- a/sdk/lib/_internal/vm/lib/core_patch.dart
+++ b/sdk/lib/_internal/vm/lib/core_patch.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:core" which contains all the imports
/// used by patches of that library. We plan to change this when we have a
diff --git a/sdk/lib/_internal/vm/lib/date_patch.dart b/sdk/lib/_internal/vm/lib/date_patch.dart
index 1899e0c..25d22df 100644
--- a/sdk/lib/_internal/vm/lib/date_patch.dart
+++ b/sdk/lib/_internal/vm/lib/date_patch.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.6
+
// part of "core_patch.dart";
// VM implementation of DateTime.
diff --git a/sdk/lib/_internal/vm/lib/deferred_load_patch.dart b/sdk/lib/_internal/vm/lib/deferred_load_patch.dart
index 554b44f..0ab5e98 100644
--- a/sdk/lib/_internal/vm/lib/deferred_load_patch.dart
+++ b/sdk/lib/_internal/vm/lib/deferred_load_patch.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.6
+
// part of "async_patch.dart";
final Set<String> _loadedLibraries = new Set<String>();
diff --git a/sdk/lib/_internal/vm/lib/developer.dart b/sdk/lib/_internal/vm/lib/developer.dart
index cb35073..d6ab6af 100644
--- a/sdk/lib/_internal/vm/lib/developer.dart
+++ b/sdk/lib/_internal/vm/lib/developer.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:developer" which contains all the imports
/// used by patches of that library. We plan to change this when we have a
diff --git a/sdk/lib/_internal/vm/lib/double.dart b/sdk/lib/_internal/vm/lib/double.dart
index 71adedd..321fc39 100644
--- a/sdk/lib/_internal/vm/lib/double.dart
+++ b/sdk/lib/_internal/vm/lib/double.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.6
+
// part of "core_patch.dart";
@pragma("vm:entry-point")
diff --git a/sdk/lib/_internal/vm/lib/double_patch.dart b/sdk/lib/_internal/vm/lib/double_patch.dart
index a621e66..c70ab77 100644
--- a/sdk/lib/_internal/vm/lib/double_patch.dart
+++ b/sdk/lib/_internal/vm/lib/double_patch.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.6
+
// part of "core_patch.dart";
// VM implementation of double.
diff --git a/sdk/lib/_internal/vm/lib/empty_source.dart b/sdk/lib/_internal/vm/lib/empty_source.dart
index 95e028f..e5dbe09 100644
--- a/sdk/lib/_internal/vm/lib/empty_source.dart
+++ b/sdk/lib/_internal/vm/lib/empty_source.dart
@@ -2,4 +2,6 @@
// 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.6
+
// THIS FILE INTENTIONALLY LEFT BLANK.
diff --git a/sdk/lib/_internal/vm/lib/errors_patch.dart b/sdk/lib/_internal/vm/lib/errors_patch.dart
index a8cb80c..9a1d4e3 100644
--- a/sdk/lib/_internal/vm/lib/errors_patch.dart
+++ b/sdk/lib/_internal/vm/lib/errors_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/expando_patch.dart b/sdk/lib/_internal/vm/lib/expando_patch.dart
index a1400b6..7653c26 100644
--- a/sdk/lib/_internal/vm/lib/expando_patch.dart
+++ b/sdk/lib/_internal/vm/lib/expando_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart b/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
index 81fac07..b616ffc 100644
--- a/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.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.6
+
// All imports must be in all FFI patch files to not depend on the order
// the patches are applied.
import "dart:_internal" show patch;
diff --git a/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
index 473ba7a..586e041 100644
--- a/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.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.6
+
// All imports must be in all FFI patch files to not depend on the order
// the patches are applied.
import "dart:_internal" show patch;
diff --git a/sdk/lib/_internal/vm/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart
index 71706ef..33baa8f 100644
--- a/sdk/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_patch.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.6
+
// All imports must be in all FFI patch files to not depend on the order
// the patches are applied.
import "dart:_internal" show patch;
diff --git a/sdk/lib/_internal/vm/lib/function.dart b/sdk/lib/_internal/vm/lib/function.dart
index 1c99ca2..128a7dd 100644
--- a/sdk/lib/_internal/vm/lib/function.dart
+++ b/sdk/lib/_internal/vm/lib/function.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.6
+
// part of "core_patch.dart";
@pragma("vm:entry-point")
diff --git a/sdk/lib/_internal/vm/lib/function_patch.dart b/sdk/lib/_internal/vm/lib/function_patch.dart
index 0c88b4e..9d33e30 100644
--- a/sdk/lib/_internal/vm/lib/function_patch.dart
+++ b/sdk/lib/_internal/vm/lib/function_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/growable_array.dart b/sdk/lib/_internal/vm/lib/growable_array.dart
index f69ed92..c2f54db 100644
--- a/sdk/lib/_internal/vm/lib/growable_array.dart
+++ b/sdk/lib/_internal/vm/lib/growable_array.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.6
+
// part of "core_patch.dart";
@pragma("vm:entry-point")
diff --git a/sdk/lib/_internal/vm/lib/identical_patch.dart b/sdk/lib/_internal/vm/lib/identical_patch.dart
index 7fa8959..3e4dc1e 100644
--- a/sdk/lib/_internal/vm/lib/identical_patch.dart
+++ b/sdk/lib/_internal/vm/lib/identical_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/immutable_map.dart b/sdk/lib/_internal/vm/lib/immutable_map.dart
index 8fbe3d9..86e5d8d 100644
--- a/sdk/lib/_internal/vm/lib/immutable_map.dart
+++ b/sdk/lib/_internal/vm/lib/immutable_map.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.6
+
// part of "core_patch.dart";
/// Immutable map class for compiler generated map literals.
diff --git a/sdk/lib/_internal/vm/lib/integers.dart b/sdk/lib/_internal/vm/lib/integers.dart
index 9b3bd8e..19495a8 100644
--- a/sdk/lib/_internal/vm/lib/integers.dart
+++ b/sdk/lib/_internal/vm/lib/integers.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.6
+
// part of "core_patch.dart";
abstract class _IntegerImplementation implements int {
diff --git a/sdk/lib/_internal/vm/lib/integers_patch.dart b/sdk/lib/_internal/vm/lib/integers_patch.dart
index dc0a20a..9a2fb54 100644
--- a/sdk/lib/_internal/vm/lib/integers_patch.dart
+++ b/sdk/lib/_internal/vm/lib/integers_patch.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.6
+
// part of "core_patch.dart";
/// VM implementation of int.
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index fe05552..9a6cdb4 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:_internal" which contains all the imports
/// used by patches of that library. We plan to change this when we have a
diff --git a/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart b/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart
index e7e2fe3..05d0d81 100644
--- a/sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart
+++ b/sdk/lib/_internal/vm/lib/invocation_mirror_patch.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.6
+
// part of "core_patch.dart";
// NOTE: When making changes to this class, please also update
diff --git a/sdk/lib/_internal/vm/lib/isolate_patch.dart b/sdk/lib/_internal/vm/lib/isolate_patch.dart
index f43d181..f5e75c9 100644
--- a/sdk/lib/_internal/vm/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/vm/lib/isolate_patch.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:isolate" which contains all the imports
/// used by patches of that library. We plan to change this when we have a
diff --git a/sdk/lib/_internal/vm/lib/lib_prefix.dart b/sdk/lib/_internal/vm/lib/lib_prefix.dart
index f588ee3..00b934c 100644
--- a/sdk/lib/_internal/vm/lib/lib_prefix.dart
+++ b/sdk/lib/_internal/vm/lib/lib_prefix.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.6
+
// part of "core_patch.dart";
// This type corresponds to the VM-internal class LibraryPrefix.
diff --git a/sdk/lib/_internal/vm/lib/map_patch.dart b/sdk/lib/_internal/vm/lib/map_patch.dart
index 07dbc69..cda2946 100644
--- a/sdk/lib/_internal/vm/lib/map_patch.dart
+++ b/sdk/lib/_internal/vm/lib/map_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/math_patch.dart b/sdk/lib/_internal/vm/lib/math_patch.dart
index 99c166e..574e3ed 100644
--- a/sdk/lib/_internal/vm/lib/math_patch.dart
+++ b/sdk/lib/_internal/vm/lib/math_patch.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:math" which contains all the imports used
/// by patches of that library. We plan to change this when we have a shared
diff --git a/sdk/lib/_internal/vm/lib/mirror_reference.dart b/sdk/lib/_internal/vm/lib/mirror_reference.dart
index d203953..4fe5ffe 100644
--- a/sdk/lib/_internal/vm/lib/mirror_reference.dart
+++ b/sdk/lib/_internal/vm/lib/mirror_reference.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.6
+
// part of "mirrors_patch.dart";
@pragma("vm:entry-point")
diff --git a/sdk/lib/_internal/vm/lib/mirrors_impl.dart b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
index b0231b2..8101907 100644
--- a/sdk/lib/_internal/vm/lib/mirrors_impl.dart
+++ b/sdk/lib/_internal/vm/lib/mirrors_impl.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.6
+
// part of "mirrors_patch.dart";
var _dirty = false; // Set to true by the VM when more libraries are loaded.
diff --git a/sdk/lib/_internal/vm/lib/mirrors_patch.dart b/sdk/lib/_internal/vm/lib/mirrors_patch.dart
index 9850e91..1adbcbb 100644
--- a/sdk/lib/_internal/vm/lib/mirrors_patch.dart
+++ b/sdk/lib/_internal/vm/lib/mirrors_patch.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:_internal" which contains all the imports
/// used by patches of that library. We plan to change this when we have a
diff --git a/sdk/lib/_internal/vm/lib/null_patch.dart b/sdk/lib/_internal/vm/lib/null_patch.dart
index 01bb5aa..3e724f7 100644
--- a/sdk/lib/_internal/vm/lib/null_patch.dart
+++ b/sdk/lib/_internal/vm/lib/null_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/object_patch.dart b/sdk/lib/_internal/vm/lib/object_patch.dart
index 7168118..fe75579 100644
--- a/sdk/lib/_internal/vm/lib/object_patch.dart
+++ b/sdk/lib/_internal/vm/lib/object_patch.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.6
+
// part of "core_patch.dart";
@pragma("vm:exact-result-type", "dart:core#_Smi")
diff --git a/sdk/lib/_internal/vm/lib/print_patch.dart b/sdk/lib/_internal/vm/lib/print_patch.dart
index f0e7d91..96ee6b4 100644
--- a/sdk/lib/_internal/vm/lib/print_patch.dart
+++ b/sdk/lib/_internal/vm/lib/print_patch.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.6
+
// part of "internal_patch.dart";
// A print-closure gets a String that should be printed. In general the
diff --git a/sdk/lib/_internal/vm/lib/profiler.dart b/sdk/lib/_internal/vm/lib/profiler.dart
index 745eaa5..4a7140f 100644
--- a/sdk/lib/_internal/vm/lib/profiler.dart
+++ b/sdk/lib/_internal/vm/lib/profiler.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.6
+
// part of "developer.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/regexp_patch.dart b/sdk/lib/_internal/vm/lib/regexp_patch.dart
index 7621bb0..d47099a 100644
--- a/sdk/lib/_internal/vm/lib/regexp_patch.dart
+++ b/sdk/lib/_internal/vm/lib/regexp_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart b/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart
index 0f90f1e..b1cfc52 100644
--- a/sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart
+++ b/sdk/lib/_internal/vm/lib/schedule_microtask_patch.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.6
+
// part of "async_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/stacktrace.dart b/sdk/lib/_internal/vm/lib/stacktrace.dart
index 719d55a..94464a5 100644
--- a/sdk/lib/_internal/vm/lib/stacktrace.dart
+++ b/sdk/lib/_internal/vm/lib/stacktrace.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.6
+
// part of "core_patch.dart";
/// VM internal StackTrace implementation.
diff --git a/sdk/lib/_internal/vm/lib/stopwatch_patch.dart b/sdk/lib/_internal/vm/lib/stopwatch_patch.dart
index 87bc584..baf57aa 100644
--- a/sdk/lib/_internal/vm/lib/stopwatch_patch.dart
+++ b/sdk/lib/_internal/vm/lib/stopwatch_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/string_buffer_patch.dart b/sdk/lib/_internal/vm/lib/string_buffer_patch.dart
index 42e9d0d..d2ecf80 100644
--- a/sdk/lib/_internal/vm/lib/string_buffer_patch.dart
+++ b/sdk/lib/_internal/vm/lib/string_buffer_patch.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.6
+
// part of "core_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/string_patch.dart b/sdk/lib/_internal/vm/lib/string_patch.dart
index 837599b..507d435 100644
--- a/sdk/lib/_internal/vm/lib/string_patch.dart
+++ b/sdk/lib/_internal/vm/lib/string_patch.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.6
+
// part of "core_patch.dart";
const int _maxAscii = 0x7f;
diff --git a/sdk/lib/_internal/vm/lib/symbol_patch.dart b/sdk/lib/_internal/vm/lib/symbol_patch.dart
index 8b78e85..3671bf7 100644
--- a/sdk/lib/_internal/vm/lib/symbol_patch.dart
+++ b/sdk/lib/_internal/vm/lib/symbol_patch.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.6
+
// part of "internal_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/timeline.dart b/sdk/lib/_internal/vm/lib/timeline.dart
index fc9e698..d2a709e 100644
--- a/sdk/lib/_internal/vm/lib/timeline.dart
+++ b/sdk/lib/_internal/vm/lib/timeline.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.6
+
// part of "developer.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/timer_impl.dart b/sdk/lib/_internal/vm/lib/timer_impl.dart
index d61c71d..2d4623e 100644
--- a/sdk/lib/_internal/vm/lib/timer_impl.dart
+++ b/sdk/lib/_internal/vm/lib/timer_impl.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.6
+
// part of "isolate_patch.dart";
// Timer heap implemented as a array-based binary heap[0].
diff --git a/sdk/lib/_internal/vm/lib/timer_patch.dart b/sdk/lib/_internal/vm/lib/timer_patch.dart
index c243a86..db181ab 100644
--- a/sdk/lib/_internal/vm/lib/timer_patch.dart
+++ b/sdk/lib/_internal/vm/lib/timer_patch.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.6
+
// part of "async_patch.dart";
@patch
diff --git a/sdk/lib/_internal/vm/lib/type_patch.dart b/sdk/lib/_internal/vm/lib/type_patch.dart
index 35ce89f..b704cb9 100644
--- a/sdk/lib/_internal/vm/lib/type_patch.dart
+++ b/sdk/lib/_internal/vm/lib/type_patch.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.6
+
// part of "core_patch.dart";
// These Dart classes correspond to the VM internal implementation classes.
diff --git a/sdk/lib/_internal/vm/lib/typed_data_patch.dart b/sdk/lib/_internal/vm/lib/typed_data_patch.dart
index ed8658d44..2fc0182 100644
--- a/sdk/lib/_internal/vm/lib/typed_data_patch.dart
+++ b/sdk/lib/_internal/vm/lib/typed_data_patch.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.6
+
/// Note: the VM concatenates all patch files into a single patch file. This
/// file is the first patch in "dart:typed_data" which contains all the imports
/// used by patches of that library. We plan to change this when we have a
diff --git a/sdk/lib/_internal/vm/lib/uri_patch.dart b/sdk/lib/_internal/vm/lib/uri_patch.dart
index de10c9e..741f2d0 100644
--- a/sdk/lib/_internal/vm/lib/uri_patch.dart
+++ b/sdk/lib/_internal/vm/lib/uri_patch.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.6
+
// part of "core_patch.dart";
typedef Uri _UriBaseClosure();
diff --git a/sdk/lib/_internal/vm/lib/wasm_patch.dart b/sdk/lib/_internal/vm/lib/wasm_patch.dart
index 1372932..c24a396 100644
--- a/sdk/lib/_internal/vm/lib/wasm_patch.dart
+++ b/sdk/lib/_internal/vm/lib/wasm_patch.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.6
+
import 'dart:_internal' show patch;
import "dart:nativewrappers" show NativeFieldWrapperClass1;
import 'dart:typed_data';
diff --git a/sdk/lib/_internal/vm/lib/weak_property.dart b/sdk/lib/_internal/vm/lib/weak_property.dart
index bc903e9..ed8e570 100644
--- a/sdk/lib/_internal/vm/lib/weak_property.dart
+++ b/sdk/lib/_internal/vm/lib/weak_property.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.6
+
// part of "core_patch.dart";
@pragma("vm:entry-point")
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index b3a5dbd..c58801f 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.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.6
+
/**
* Support for asynchronous programming,
* with classes such as Future and Stream.
@@ -87,7 +89,7 @@
* [asynchronous-programming]: https://www.dartlang.org/docs/dart-up-and-running/ch03.html#dartasync---asynchronous-programming
* [futures-tutorial]: https://www.dartlang.org/docs/tutorials/futures/
* [futures-error-handling]: https://www.dartlang.org/articles/futures-and-error-handling/
- * [test-readme]: https://pub.dartlang.org/packages/test
+ * [test-readme]: https://pub.dev/packages/test
*
* {@category Core}
*/
diff --git a/sdk/lib/async/async_error.dart b/sdk/lib/async/async_error.dart
index 1520c54..f0e8119 100644
--- a/sdk/lib/async/async_error.dart
+++ b/sdk/lib/async/async_error.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.6
+
part of dart.async;
_invokeErrorHandler(
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index 32e4582..c18a682 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.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.6
+
part of dart.async;
class _BroadcastStream<T> extends _ControllerStream<T> {
diff --git a/sdk/lib/async/deferred_load.dart b/sdk/lib/async/deferred_load.dart
index f83d4b8..0019f68 100644
--- a/sdk/lib/async/deferred_load.dart
+++ b/sdk/lib/async/deferred_load.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.6
+
part of dart.async;
/**
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 19c9dbe..7aeee47 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.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.6
+
part of dart.async;
/// A type representing values that are either `Future<T>` or `T`.
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 1ec0791..a915b96 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.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.6
+
part of dart.async;
/** The onValue and onError handlers return either a value or a future */
diff --git a/sdk/lib/async/schedule_microtask.dart b/sdk/lib/async/schedule_microtask.dart
index 801490a..40f6523 100644
--- a/sdk/lib/async/schedule_microtask.dart
+++ b/sdk/lib/async/schedule_microtask.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.6
+
part of dart.async;
typedef void _AsyncCallback();
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index bfa1741..51e9cd1 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.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.6
+
part of dart.async;
// -------------------------------------------------------------------
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index 34c6adf..f2854a9 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.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.6
+
part of dart.async;
// -------------------------------------------------------------------
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 14c84a5..b3969fc 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.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.6
+
part of dart.async;
/** Abstract and private interface for a place to put events. */
diff --git a/sdk/lib/async/stream_pipe.dart b/sdk/lib/async/stream_pipe.dart
index e526179..5771db4 100644
--- a/sdk/lib/async/stream_pipe.dart
+++ b/sdk/lib/async/stream_pipe.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.6
+
part of dart.async;
/** Runs user code and takes actions depending on success or failure. */
diff --git a/sdk/lib/async/stream_transformers.dart b/sdk/lib/async/stream_transformers.dart
index 9ec13bd..7cba3ba 100644
--- a/sdk/lib/async/stream_transformers.dart
+++ b/sdk/lib/async/stream_transformers.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.6
+
part of dart.async;
/**
diff --git a/sdk/lib/async/timer.dart b/sdk/lib/async/timer.dart
index 97560a9..6c42767 100644
--- a/sdk/lib/async/timer.dart
+++ b/sdk/lib/async/timer.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.6
+
part of dart.async;
/**
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 7c66de1..d8f8596 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.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.6
+
part of dart.async;
typedef R ZoneCallback<R>();
diff --git a/sdk/lib/cli/cli.dart b/sdk/lib/cli/cli.dart
index 9c19c3a..cabc17e 100644
--- a/sdk/lib/cli/cli.dart
+++ b/sdk/lib/cli/cli.dart
@@ -2,7 +2,10 @@
// 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.6
+
/// {@category VM}
+/// {@nodoc}
library dart.cli;
import 'dart:async';
diff --git a/sdk/lib/cli/wait_for.dart b/sdk/lib/cli/wait_for.dart
index 1886ff1..57202bc 100644
--- a/sdk/lib/cli/wait_for.dart
+++ b/sdk/lib/cli/wait_for.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.6
+
part of dart.cli;
/**
diff --git a/sdk/lib/collection/collection.dart b/sdk/lib/collection/collection.dart
index b050a48..80f6d93 100644
--- a/sdk/lib/collection/collection.dart
+++ b/sdk/lib/collection/collection.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.6
+
/// Classes and utilities that supplement the collection support in dart:core.
///
/// To use this library in your code:
diff --git a/sdk/lib/collection/collections.dart b/sdk/lib/collection/collections.dart
index 9b43996..600dead 100644
--- a/sdk/lib/collection/collections.dart
+++ b/sdk/lib/collection/collections.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.6
+
part of dart.collection;
/// An unmodifiable [List] view of another List.
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index 525f43a..e3da5a2 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.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.6
+
part of dart.collection;
/// Default function for equality comparison in customized HashMaps
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index 3fd00fe..97492e9 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.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.6
+
part of dart.collection;
/// An unordered hash-table based [Set] implementation.
diff --git a/sdk/lib/collection/iterable.dart b/sdk/lib/collection/iterable.dart
index 14e7226..944466d 100644
--- a/sdk/lib/collection/iterable.dart
+++ b/sdk/lib/collection/iterable.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.6
+
part of dart.collection;
/// This [Iterable] mixin implements all [Iterable] members except `iterator`.
diff --git a/sdk/lib/collection/iterator.dart b/sdk/lib/collection/iterator.dart
index 671f0ee..05bcfae 100644
--- a/sdk/lib/collection/iterator.dart
+++ b/sdk/lib/collection/iterator.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.6
+
part of dart.collection;
/// The [HasNextIterator] class wraps an [Iterator] and provides methods to
diff --git a/sdk/lib/collection/linked_hash_map.dart b/sdk/lib/collection/linked_hash_map.dart
index e3a650d..548bc49 100644
--- a/sdk/lib/collection/linked_hash_map.dart
+++ b/sdk/lib/collection/linked_hash_map.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.6
+
part of dart.collection;
/// A hash-table based implementation of [Map].
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index a058b5e..4fb199b 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.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.6
+
part of dart.collection;
/// A [LinkedHashSet] is a hash-table based [Set] implementation.
diff --git a/sdk/lib/collection/linked_list.dart b/sdk/lib/collection/linked_list.dart
index 91461cb..94f30cf 100644
--- a/sdk/lib/collection/linked_list.dart
+++ b/sdk/lib/collection/linked_list.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.6
+
part of dart.collection;
/// A specialized double-linked list of elements that extends [LinkedListEntry].
diff --git a/sdk/lib/collection/list.dart b/sdk/lib/collection/list.dart
index 56661e3..3009b37 100644
--- a/sdk/lib/collection/list.dart
+++ b/sdk/lib/collection/list.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.6
+
part of dart.collection;
/// Abstract implementation of a list.
diff --git a/sdk/lib/collection/maps.dart b/sdk/lib/collection/maps.dart
index 8159342..3204db0 100644
--- a/sdk/lib/collection/maps.dart
+++ b/sdk/lib/collection/maps.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.6
+
part of dart.collection;
/// Base class for implementing a [Map].
diff --git a/sdk/lib/collection/queue.dart b/sdk/lib/collection/queue.dart
index 8a95cf4..151edc4 100644
--- a/sdk/lib/collection/queue.dart
+++ b/sdk/lib/collection/queue.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.6
+
part of dart.collection;
/// A [Queue] is a collection that can be manipulated at both ends. One
diff --git a/sdk/lib/collection/set.dart b/sdk/lib/collection/set.dart
index c911faf..8efe4eb 100644
--- a/sdk/lib/collection/set.dart
+++ b/sdk/lib/collection/set.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.6
+
/// Base implementations of [Set].
part of dart.collection;
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart
index 5f71934..a877e18 100644
--- a/sdk/lib/collection/splay_tree.dart
+++ b/sdk/lib/collection/splay_tree.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.6
+
part of dart.collection;
typedef _Predicate<T> = bool Function(T value);
diff --git a/sdk/lib/convert/ascii.dart b/sdk/lib/convert/ascii.dart
index 35105ac..82f2276 100644
--- a/sdk/lib/convert/ascii.dart
+++ b/sdk/lib/convert/ascii.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.6
+
part of dart.convert;
/// An instance of the default implementation of the [AsciiCodec].
diff --git a/sdk/lib/convert/base64.dart b/sdk/lib/convert/base64.dart
index 7ebd1d5..871ebd8 100644
--- a/sdk/lib/convert/base64.dart
+++ b/sdk/lib/convert/base64.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.6
+
part of dart.convert;
/// A [base64](https://tools.ietf.org/html/rfc4648) encoder and decoder.
diff --git a/sdk/lib/convert/byte_conversion.dart b/sdk/lib/convert/byte_conversion.dart
index 3d52d78..ffde7d9 100644
--- a/sdk/lib/convert/byte_conversion.dart
+++ b/sdk/lib/convert/byte_conversion.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.6
+
part of dart.convert;
/// The [ByteConversionSink] provides an interface for converters to
diff --git a/sdk/lib/convert/chunked_conversion.dart b/sdk/lib/convert/chunked_conversion.dart
index e946f97..7253981 100644
--- a/sdk/lib/convert/chunked_conversion.dart
+++ b/sdk/lib/convert/chunked_conversion.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.6
+
part of dart.convert;
/// A [ChunkedConversionSink] is used to transmit data more efficiently between
diff --git a/sdk/lib/convert/codec.dart b/sdk/lib/convert/codec.dart
index 38e4a3c..1d8daf3 100644
--- a/sdk/lib/convert/codec.dart
+++ b/sdk/lib/convert/codec.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.6
+
part of dart.convert;
/// A [Codec] encodes and (if supported) decodes data.
diff --git a/sdk/lib/convert/convert.dart b/sdk/lib/convert/convert.dart
index 6173782..ec6ba50 100644
--- a/sdk/lib/convert/convert.dart
+++ b/sdk/lib/convert/convert.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.6
+
///
/// Encoders and decoders for converting between different data representations,
/// including JSON and UTF-8.
diff --git a/sdk/lib/convert/converter.dart b/sdk/lib/convert/converter.dart
index 2167933..047859f 100644
--- a/sdk/lib/convert/converter.dart
+++ b/sdk/lib/convert/converter.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.6
+
part of dart.convert;
/// A [Converter] converts data from one representation into another.
diff --git a/sdk/lib/convert/encoding.dart b/sdk/lib/convert/encoding.dart
index 7ce8ec3..663ae64 100644
--- a/sdk/lib/convert/encoding.dart
+++ b/sdk/lib/convert/encoding.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.6
+
part of dart.convert;
/// Open-ended Encoding enum.
diff --git a/sdk/lib/convert/html_escape.dart b/sdk/lib/convert/html_escape.dart
index a0a7119..5f10544 100644
--- a/sdk/lib/convert/html_escape.dart
+++ b/sdk/lib/convert/html_escape.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.6
+
part of dart.convert;
/// A `String` converter that converts characters to HTML entities.
diff --git a/sdk/lib/convert/json.dart b/sdk/lib/convert/json.dart
index 97216f7..a834a9e 100644
--- a/sdk/lib/convert/json.dart
+++ b/sdk/lib/convert/json.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.6
+
part of dart.convert;
/// Error thrown by JSON serialization if an object cannot be serialized.
@@ -279,7 +281,7 @@
Stream<String> bind(Stream<Object> stream) => super.bind(stream);
Converter<Object, T> fuse<T>(Converter<String, T> other) {
- if (other is Utf8Encoder && T is List<int>) {
+ if (other is Utf8Encoder) {
// The instance check guarantees that `T` is (a subtype of) List<int>,
// but the static type system doesn't know that, and so we cast.
// Cast through dynamic to keep the cast implicit for builds using
diff --git a/sdk/lib/convert/latin1.dart b/sdk/lib/convert/latin1.dart
index c22010c..06fa681 100644
--- a/sdk/lib/convert/latin1.dart
+++ b/sdk/lib/convert/latin1.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.6
+
part of dart.convert;
/// An instance of the default implementation of the [Latin1Codec].
diff --git a/sdk/lib/convert/line_splitter.dart b/sdk/lib/convert/line_splitter.dart
index 71be2c0..f51e53c 100644
--- a/sdk/lib/convert/line_splitter.dart
+++ b/sdk/lib/convert/line_splitter.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.6
+
part of dart.convert;
// Character constants.
diff --git a/sdk/lib/convert/string_conversion.dart b/sdk/lib/convert/string_conversion.dart
index 81e5621..086ed79 100644
--- a/sdk/lib/convert/string_conversion.dart
+++ b/sdk/lib/convert/string_conversion.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.6
+
part of dart.convert;
/// This class provides an interface for converters to
diff --git a/sdk/lib/convert/utf.dart b/sdk/lib/convert/utf.dart
index 39eb135..a614f39 100644
--- a/sdk/lib/convert/utf.dart
+++ b/sdk/lib/convert/utf.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.6
+
part of dart.convert;
/// The Unicode Replacement character `U+FFFD` (�).
diff --git a/sdk/lib/core/annotations.dart b/sdk/lib/core/annotations.dart
index 2d30f1c..6c39fcf 100644
--- a/sdk/lib/core/annotations.dart
+++ b/sdk/lib/core/annotations.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/bigint.dart b/sdk/lib/core/bigint.dart
index b495a9e..c3f261b 100644
--- a/sdk/lib/core/bigint.dart
+++ b/sdk/lib/core/bigint.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/bool.dart b/sdk/lib/core/bool.dart
index 5ed1065..f2ecf08 100644
--- a/sdk/lib/core/bool.dart
+++ b/sdk/lib/core/bool.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/comparable.dart b/sdk/lib/core/comparable.dart
index 835aa34..08bb965 100644
--- a/sdk/lib/core/comparable.dart
+++ b/sdk/lib/core/comparable.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/core.dart b/sdk/lib/core/core.dart
index 9ab8ed4..7d67132 100644
--- a/sdk/lib/core/core.dart
+++ b/sdk/lib/core/core.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.6
+
/**
*
* Built-in types, collections,
diff --git a/sdk/lib/core/date_time.dart b/sdk/lib/core/date_time.dart
index dd242de..f52e059 100644
--- a/sdk/lib/core/date_time.dart
+++ b/sdk/lib/core/date_time.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.6
+
part of dart.core;
/**
@@ -117,7 +119,7 @@
*
* The DateTime class does not provide internationalization.
* To internationalize your code, use
- * the [intl](https://pub.dartlang.org/packages/intl) package.
+ * the [intl](https://pub.dev/packages/intl) package.
*
*/
class DateTime implements Comparable<DateTime> {
@@ -238,7 +240,8 @@
* The time part is a two digit hour,
* then optionally a two digit minutes value,
* then optionally a two digit seconds value, and
- * then optionally a '.' or ',' followed by a one-to-six digit second fraction.
+ * then optionally a '.' or ',' followed by at least a one digit
+ * second fraction.
* The minutes and seconds may be separated from the previous parts by a
* ':'.
* Examples: "12", "12:30:24.124", "12:30:24,124", "123010.50".
@@ -261,8 +264,8 @@
* Examples of accepted strings:
*
* * `"2012-02-27 13:27:00"`
- * * `"2012-02-27 13:27:00.123456z"`
- * * `"2012-02-27 13:27:00,123456z"`
+ * * `"2012-02-27 13:27:00.123456789z"`
+ * * `"2012-02-27 13:27:00,123456789z"`
* * `"20120227 13:27:00"`
* * `"20120227T132700"`
* * `"20120227"`
@@ -283,14 +286,13 @@
return int.parse(matched);
}
- // Parses fractional second digits of '.(\d{1,6})' into the combined
- // microseconds.
+ // Parses fractional second digits of '.(\d+)' into the combined
+ // microseconds. We only use the first 6 digits because of DateTime
+ // precision of 999 milliseconds and 999 microseconds.
int parseMilliAndMicroseconds(String matched) {
if (matched == null) return 0;
int length = matched.length;
assert(length >= 1);
- assert(length <= 6);
-
int result = 0;
for (int i = 0; i < 6; i++) {
result *= 10;
@@ -307,7 +309,6 @@
int hour = parseIntOrZero(match[4]);
int minute = parseIntOrZero(match[5]);
int second = parseIntOrZero(match[6]);
- bool addOneMillisecond = false;
int milliAndMicroseconds = parseMilliAndMicroseconds(match[7]);
int millisecond =
milliAndMicroseconds ~/ Duration.microsecondsPerMillisecond;
@@ -560,7 +561,7 @@
* The returned string is constructed for the time zone of this instance.
* The `toString()` method provides a simply formatted string.
* It does not support internationalized strings.
- * Use the [intl](https://pub.dartlang.org/packages/intl) package
+ * Use the [intl](https://pub.dev/packages/intl) package
* at the pub shared packages repo.
*
* The resulting string can be parsed back using [parse].
@@ -860,7 +861,7 @@
* time_opt ::= <empty> | (' ' | 'T') hour minutes_opt
* minutes_opt ::= <empty> | colon_opt digit{2} seconds_opt
* seconds_opt ::= <empty> | colon_opt digit{2} millis_opt
- * micros_opt ::= <empty> | ('.' | ',') digit{1,6}
+ * micros_opt ::= <empty> | ('.' | ',') digit+
* timezone_opt ::= <empty> | space_opt timezone
* space_opt :: ' ' | <empty>
* timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt
@@ -868,6 +869,6 @@
*/
static final RegExp _parseFormat = RegExp(
r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // Day part.
- r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,6}))?)?)?' // Time part.
+ r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d+))?)?)?' // Time part.
r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // Timezone part.
}
diff --git a/sdk/lib/core/double.dart b/sdk/lib/core/double.dart
index 61191ec..18f782f 100644
--- a/sdk/lib/core/double.dart
+++ b/sdk/lib/core/double.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.6
+
part of dart.core;
// TODO: Convert this abstract class into a concrete class double
diff --git a/sdk/lib/core/duration.dart b/sdk/lib/core/duration.dart
index 914f05a..eeb0337 100644
--- a/sdk/lib/core/duration.dart
+++ b/sdk/lib/core/duration.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index 298083d..a1b410c 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/exceptions.dart b/sdk/lib/core/exceptions.dart
index 27c11fa..ef66d15 100644
--- a/sdk/lib/core/exceptions.dart
+++ b/sdk/lib/core/exceptions.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.6
+
part of dart.core;
// Exceptions are thrown either by the VM or from Dart code.
diff --git a/sdk/lib/core/expando.dart b/sdk/lib/core/expando.dart
index 92cf90c..2ccb07d 100644
--- a/sdk/lib/core/expando.dart
+++ b/sdk/lib/core/expando.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/function.dart b/sdk/lib/core/function.dart
index 7ff40e9..4e026f8 100644
--- a/sdk/lib/core/function.dart
+++ b/sdk/lib/core/function.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/identical.dart b/sdk/lib/core/identical.dart
index 68da9f3..ec24609 100644
--- a/sdk/lib/core/identical.dart
+++ b/sdk/lib/core/identical.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/int.dart b/sdk/lib/core/int.dart
index bc493fb..a6253c0 100644
--- a/sdk/lib/core/int.dart
+++ b/sdk/lib/core/int.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/invocation.dart b/sdk/lib/core/invocation.dart
index e9ea57e..8b7df36 100644
--- a/sdk/lib/core/invocation.dart
+++ b/sdk/lib/core/invocation.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 0744937..c6aba41 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/iterator.dart b/sdk/lib/core/iterator.dart
index cd0ad32..73a7d3f 100644
--- a/sdk/lib/core/iterator.dart
+++ b/sdk/lib/core/iterator.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart
index 27e1653..9500c56 100644
--- a/sdk/lib/core/list.dart
+++ b/sdk/lib/core/list.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index 21d3945..8f76dfd 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/null.dart b/sdk/lib/core/null.dart
index af7d86d..40140e8 100644
--- a/sdk/lib/core/null.dart
+++ b/sdk/lib/core/null.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/num.dart b/sdk/lib/core/num.dart
index e04112c..dedc8d4 100644
--- a/sdk/lib/core/num.dart
+++ b/sdk/lib/core/num.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/object.dart b/sdk/lib/core/object.dart
index 505efdf..08bf687 100644
--- a/sdk/lib/core/object.dart
+++ b/sdk/lib/core/object.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/pattern.dart b/sdk/lib/core/pattern.dart
index 6749340..8eb0371 100644
--- a/sdk/lib/core/pattern.dart
+++ b/sdk/lib/core/pattern.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/print.dart b/sdk/lib/core/print.dart
index 42c7d1c..cc2f0ac 100644
--- a/sdk/lib/core/print.dart
+++ b/sdk/lib/core/print.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.6
+
part of dart.core;
/// Prints a string representation of the object to the console.
diff --git a/sdk/lib/core/regexp.dart b/sdk/lib/core/regexp.dart
index 9bd68ba..095e733 100644
--- a/sdk/lib/core/regexp.dart
+++ b/sdk/lib/core/regexp.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/set.dart b/sdk/lib/core/set.dart
index e57d974..9e1a6de 100644
--- a/sdk/lib/core/set.dart
+++ b/sdk/lib/core/set.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/sink.dart b/sdk/lib/core/sink.dart
index c79214b..80f9468d 100644
--- a/sdk/lib/core/sink.dart
+++ b/sdk/lib/core/sink.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/stacktrace.dart b/sdk/lib/core/stacktrace.dart
index 2eb1493..ed5f85d 100644
--- a/sdk/lib/core/stacktrace.dart
+++ b/sdk/lib/core/stacktrace.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/stopwatch.dart b/sdk/lib/core/stopwatch.dart
index 45d71ca..20316eb 100644
--- a/sdk/lib/core/stopwatch.dart
+++ b/sdk/lib/core/stopwatch.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/string.dart b/sdk/lib/core/string.dart
index c611bd5..5a8deb8 100644
--- a/sdk/lib/core/string.dart
+++ b/sdk/lib/core/string.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/string_buffer.dart b/sdk/lib/core/string_buffer.dart
index 8fe17f5..d2a25ab 100644
--- a/sdk/lib/core/string_buffer.dart
+++ b/sdk/lib/core/string_buffer.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/string_sink.dart b/sdk/lib/core/string_sink.dart
index e7d950c..b0511ad 100644
--- a/sdk/lib/core/string_sink.dart
+++ b/sdk/lib/core/string_sink.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.6
+
part of dart.core;
abstract class StringSink {
diff --git a/sdk/lib/core/symbol.dart b/sdk/lib/core/symbol.dart
index a46ec97..748d465 100644
--- a/sdk/lib/core/symbol.dart
+++ b/sdk/lib/core/symbol.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.6
+
part of dart.core;
/// Opaque name used by mirrors, invocations and [Function.apply].
@@ -60,7 +62,7 @@
* assert(new Symbol("[]=") == #[]=]);
* assert(new Symbol("foo.bar") == #foo.bar);
* assert(identical(const Symbol("foo"), #foo));
- * assert(identical(const Symbol("[]="), #[]=]));
+ * assert(identical(const Symbol("[]="), #[]=));
* assert(identical(const Symbol("foo.bar"), #foo.bar));
* ```
*
diff --git a/sdk/lib/core/type.dart b/sdk/lib/core/type.dart
index d2e107b..48ac0e9 100644
--- a/sdk/lib/core/type.dart
+++ b/sdk/lib/core/type.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.6
+
part of dart.core;
/**
diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
index 2ca94a1..a85eb67 100644
--- a/sdk/lib/core/uri.dart
+++ b/sdk/lib/core/uri.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.6
+
part of dart.core;
// Frequently used character codes.
diff --git a/sdk/lib/developer/developer.dart b/sdk/lib/developer/developer.dart
index c446fdf..4490499 100644
--- a/sdk/lib/developer/developer.dart
+++ b/sdk/lib/developer/developer.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.6
+
/// Interact with developer tools such as the debugger and inspector.
///
/// This library is platform dependent and has separate implementations for
diff --git a/sdk/lib/developer/extension.dart b/sdk/lib/developer/extension.dart
index 3cc4ede..5d0da2a 100644
--- a/sdk/lib/developer/extension.dart
+++ b/sdk/lib/developer/extension.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.6
+
part of dart.developer;
/// A response to a service protocol extension RPC.
diff --git a/sdk/lib/developer/profiler.dart b/sdk/lib/developer/profiler.dart
index 05a9211..385d68a 100644
--- a/sdk/lib/developer/profiler.dart
+++ b/sdk/lib/developer/profiler.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.6
+
part of dart.developer;
/// A UserTag can be used to group samples in the Observatory profiler.
diff --git a/sdk/lib/developer/service.dart b/sdk/lib/developer/service.dart
index a4d92b9..81d0540 100644
--- a/sdk/lib/developer/service.dart
+++ b/sdk/lib/developer/service.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.6
+
part of dart.developer;
/// Service protocol is the protocol that a client like the Observatory
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart
index bfdb07b..14775b5 100644
--- a/sdk/lib/developer/timeline.dart
+++ b/sdk/lib/developer/timeline.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.6
+
part of dart.developer;
const bool _hasTimeline =
diff --git a/sdk/lib/ffi/annotations.dart b/sdk/lib/ffi/annotations.dart
index f68e525..1466c35 100644
--- a/sdk/lib/ffi/annotations.dart
+++ b/sdk/lib/ffi/annotations.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.6
+
part of dart.ffi;
class DartRepresentationOf {
diff --git a/sdk/lib/ffi/dynamic_library.dart b/sdk/lib/ffi/dynamic_library.dart
index ec68eeb..4640857 100644
--- a/sdk/lib/ffi/dynamic_library.dart
+++ b/sdk/lib/ffi/dynamic_library.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.6
+
part of dart.ffi;
/// Represents a dynamically loaded C library.
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index f072a7c..d00b4e7 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.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.6
+
/**
* Foreign Function Interface for interoperability with the C programming language.
*
diff --git a/sdk/lib/ffi/native_type.dart b/sdk/lib/ffi/native_type.dart
index aa30e63..c372b82 100644
--- a/sdk/lib/ffi/native_type.dart
+++ b/sdk/lib/ffi/native_type.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.6
+
part of dart.ffi;
/// [NativeType]'s subtypes represent a native type in C.
diff --git a/sdk/lib/ffi/struct.dart b/sdk/lib/ffi/struct.dart
index c6605d8..5d807b0 100644
--- a/sdk/lib/ffi/struct.dart
+++ b/sdk/lib/ffi/struct.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.6
+
part of dart.ffi;
/// This class is extended to define structs.
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 090115d..bdf8bac 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.6
+
/**
* HTML elements and other resources for web-based applications that need to
* interact with the browser and the DOM (Document Object Model).
diff --git a/sdk/lib/html/dartium/nativewrappers.dart b/sdk/lib/html/dartium/nativewrappers.dart
index b6d2dc4..db80798 100644
--- a/sdk/lib/html/dartium/nativewrappers.dart
+++ b/sdk/lib/html/dartium/nativewrappers.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.6
+
library nativewrappers;
class NativeFieldWrapperClass1 {}
diff --git a/sdk/lib/html/html_common/conversions.dart b/sdk/lib/html/html_common/conversions.dart
index a7775ed..cbe2cd6 100644
--- a/sdk/lib/html/html_common/conversions.dart
+++ b/sdk/lib/html/html_common/conversions.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.6
+
// Conversions for IDBKey.
//
// Per http://www.w3.org/TR/IndexedDB/#key-construct
diff --git a/sdk/lib/html/html_common/conversions_dart2js.dart b/sdk/lib/html/html_common/conversions_dart2js.dart
index 21ab9ae..028707f 100644
--- a/sdk/lib/html/html_common/conversions_dart2js.dart
+++ b/sdk/lib/html/html_common/conversions_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.6
+
part of html_common;
/// Converts a JavaScript object with properties into a Dart Map.
diff --git a/sdk/lib/html/html_common/css_class_set.dart b/sdk/lib/html/html_common/css_class_set.dart
index 2286057..486fa31 100644
--- a/sdk/lib/html/html_common/css_class_set.dart
+++ b/sdk/lib/html/html_common/css_class_set.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.6
+
part of html_common;
abstract class CssClassSetImpl extends SetBase<String> implements CssClassSet {
diff --git a/sdk/lib/html/html_common/device.dart b/sdk/lib/html/html_common/device.dart
index 123a5db..d4d9ed5 100644
--- a/sdk/lib/html/html_common/device.dart
+++ b/sdk/lib/html/html_common/device.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.6
+
part of html_common;
/**
diff --git a/sdk/lib/html/html_common/filtered_element_list.dart b/sdk/lib/html/html_common/filtered_element_list.dart
index fba6ad7..35e01cb 100644
--- a/sdk/lib/html/html_common/filtered_element_list.dart
+++ b/sdk/lib/html/html_common/filtered_element_list.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.6
+
part of html_common;
/**
diff --git a/sdk/lib/html/html_common/html_common.dart b/sdk/lib/html/html_common/html_common.dart
index e689c9a..6d6b08b 100644
--- a/sdk/lib/html/html_common/html_common.dart
+++ b/sdk/lib/html/html_common/html_common.dart
@@ -1,6 +1,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.6
+
library html_common;
import 'dart:async';
diff --git a/sdk/lib/html/html_common/html_common_dart2js.dart b/sdk/lib/html/html_common/html_common_dart2js.dart
index 3df2ccf..da4e210 100644
--- a/sdk/lib/html/html_common/html_common_dart2js.dart
+++ b/sdk/lib/html/html_common/html_common_dart2js.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.6
+
library html_common;
import 'dart:async';
diff --git a/sdk/lib/html/html_common/lists.dart b/sdk/lib/html/html_common/lists.dart
index c7abc41..83d65b7 100644
--- a/sdk/lib/html/html_common/lists.dart
+++ b/sdk/lib/html/html_common/lists.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.6
+
part of html_common;
class Lists {
diff --git a/sdk/lib/html/html_common/metadata.dart b/sdk/lib/html/html_common/metadata.dart
index b5542dc..991d99f 100644
--- a/sdk/lib/html/html_common/metadata.dart
+++ b/sdk/lib/html/html_common/metadata.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.6
+
library metadata;
/**
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index b664b7d..60bab46 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.6
+
/**
* A client-side key-value store with support for indexes.
*
diff --git a/sdk/lib/internal/async_cast.dart b/sdk/lib/internal/async_cast.dart
index e041ff3..aa3e375 100644
--- a/sdk/lib/internal/async_cast.dart
+++ b/sdk/lib/internal/async_cast.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.6
+
part of dart._internal;
// Casting wrappers for asynchronous classes.
diff --git a/sdk/lib/internal/cast.dart b/sdk/lib/internal/cast.dart
index b3620f5..f019c95 100644
--- a/sdk/lib/internal/cast.dart
+++ b/sdk/lib/internal/cast.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.6
+
part of dart._internal;
// Casting wrappers for collection classes.
diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
index 11ee996..bee60d6 100644
--- a/sdk/lib/internal/internal.dart
+++ b/sdk/lib/internal/internal.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.6
+
library dart._internal;
import 'dart:collection';
diff --git a/sdk/lib/internal/iterable.dart b/sdk/lib/internal/iterable.dart
index b3e8e4e..8f28b5f 100644
--- a/sdk/lib/internal/iterable.dart
+++ b/sdk/lib/internal/iterable.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.6
+
part of dart._internal;
/**
diff --git a/sdk/lib/internal/linked_list.dart b/sdk/lib/internal/linked_list.dart
index 31a6c01..1ad5889 100644
--- a/sdk/lib/internal/linked_list.dart
+++ b/sdk/lib/internal/linked_list.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.6
+
part of dart._internal;
/// A rudimentary linked list.
diff --git a/sdk/lib/internal/list.dart b/sdk/lib/internal/list.dart
index e0ddd70..3bf14a9 100644
--- a/sdk/lib/internal/list.dart
+++ b/sdk/lib/internal/list.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.6
+
part of dart._internal;
/**
diff --git a/sdk/lib/internal/patch.dart b/sdk/lib/internal/patch.dart
index 3fc9733..b6aeea8 100644
--- a/sdk/lib/internal/patch.dart
+++ b/sdk/lib/internal/patch.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.6
+
part of "dart:_internal";
class _Patch {
diff --git a/sdk/lib/internal/print.dart b/sdk/lib/internal/print.dart
index 417003b..466a414 100644
--- a/sdk/lib/internal/print.dart
+++ b/sdk/lib/internal/print.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.6
+
part of dart._internal;
/**
diff --git a/sdk/lib/internal/sort.dart b/sdk/lib/internal/sort.dart
index d6cca2e..a4489f3 100644
--- a/sdk/lib/internal/sort.dart
+++ b/sdk/lib/internal/sort.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.6
+
part of dart._internal;
/**
diff --git a/sdk/lib/internal/symbol.dart b/sdk/lib/internal/symbol.dart
index 54d235c..7fba4af 100644
--- a/sdk/lib/internal/symbol.dart
+++ b/sdk/lib/internal/symbol.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.6
+
part of dart._internal;
/**
diff --git a/sdk/lib/io/bytes_builder.dart b/sdk/lib/io/bytes_builder.dart
index 9113d44..6efe42c 100644
--- a/sdk/lib/io/bytes_builder.dart
+++ b/sdk/lib/io/bytes_builder.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/common.dart b/sdk/lib/io/common.dart
index 77b7587..d047752 100644
--- a/sdk/lib/io/common.dart
+++ b/sdk/lib/io/common.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.6
+
part of dart.io;
// Constants used when working with native ports.
diff --git a/sdk/lib/io/data_transformer.dart b/sdk/lib/io/data_transformer.dart
index 33c615d..0046416 100644
--- a/sdk/lib/io/data_transformer.dart
+++ b/sdk/lib/io/data_transformer.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index 2f141cb..44b8399 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index faed892..bcd63b2 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.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.6
+
part of dart.io;
class _Directory extends FileSystemEntity implements Directory {
diff --git a/sdk/lib/io/embedder_config.dart b/sdk/lib/io/embedder_config.dart
index cbc94f7..179c06a 100644
--- a/sdk/lib/io/embedder_config.dart
+++ b/sdk/lib/io/embedder_config.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.6
+
part of dart.io;
/// Embedder-specific, fine-grained dart:io configuration.
diff --git a/sdk/lib/io/eventhandler.dart b/sdk/lib/io/eventhandler.dart
index 36f54e6..6a3467f 100644
--- a/sdk/lib/io/eventhandler.dart
+++ b/sdk/lib/io/eventhandler.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.6
+
part of dart.io;
class _EventHandler {
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index cae672b..b04315f 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 410182c..f0a1275 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.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.6
+
part of dart.io;
// Read the file in blocks of size 64k.
diff --git a/sdk/lib/io/file_system_entity.dart b/sdk/lib/io/file_system_entity.dart
index dfff281..6427594 100644
--- a/sdk/lib/io/file_system_entity.dart
+++ b/sdk/lib/io/file_system_entity.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index d30e97e..7fc5bd3 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.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.6
+
/**
* File, socket, HTTP, and other I/O support for non-web applications.
*
@@ -65,7 +67,7 @@
* The [HttpServer] class provides the basic functionality for
* implementing an HTTP server.
* For some higher-level building-blocks, we recommend that you try
- * the [shelf](https://pub.dartlang.org/packages/shelf)
+ * the [shelf](https://pub.dev/packages/shelf)
* pub package, which contains
* a set of high-level classes that, together with the [HttpServer] class
* in this library, make it easier to implement HTTP servers.
diff --git a/sdk/lib/io/io_resource_info.dart b/sdk/lib/io/io_resource_info.dart
index 3e29221..a81da11 100644
--- a/sdk/lib/io/io_resource_info.dart
+++ b/sdk/lib/io/io_resource_info.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.6
+
part of dart.io;
abstract class _IOResourceInfo {
diff --git a/sdk/lib/io/io_service.dart b/sdk/lib/io/io_service.dart
index 7af382c..92d3e84 100644
--- a/sdk/lib/io/io_service.dart
+++ b/sdk/lib/io/io_service.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.6
+
part of dart.io;
class _IOService {
diff --git a/sdk/lib/io/io_sink.dart b/sdk/lib/io/io_sink.dart
index 5481265..96a68a9 100644
--- a/sdk/lib/io/io_sink.dart
+++ b/sdk/lib/io/io_sink.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 79f8656..b210507 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/namespace_impl.dart b/sdk/lib/io/namespace_impl.dart
index 88987b6..763f4aa 100644
--- a/sdk/lib/io/namespace_impl.dart
+++ b/sdk/lib/io/namespace_impl.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.6
+
part of dart.io;
// Each Isolate may run in a different "namespace", which provides the scope in
diff --git a/sdk/lib/io/network_profiling.dart b/sdk/lib/io/network_profiling.dart
index e562b0d..f303c9d 100644
--- a/sdk/lib/io/network_profiling.dart
+++ b/sdk/lib/io/network_profiling.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.6
+
part of dart.io;
@pragma('vm:entry-point')
diff --git a/sdk/lib/io/overrides.dart b/sdk/lib/io/overrides.dart
index aa1c8a4..0692f9d 100644
--- a/sdk/lib/io/overrides.dart
+++ b/sdk/lib/io/overrides.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.6
+
part of dart.io;
final _ioOverridesToken = new Object();
diff --git a/sdk/lib/io/platform.dart b/sdk/lib/io/platform.dart
index f7c9053..7fd53c8 100644
--- a/sdk/lib/io/platform.dart
+++ b/sdk/lib/io/platform.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/platform_impl.dart b/sdk/lib/io/platform_impl.dart
index a350119..8705697 100644
--- a/sdk/lib/io/platform_impl.dart
+++ b/sdk/lib/io/platform_impl.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.6
+
part of dart.io;
class _Platform {
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index 4cf78b9..93a6772 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.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.6
+
part of dart.io;
// TODO(ager): The only reason for this class is that we
diff --git a/sdk/lib/io/secure_server_socket.dart b/sdk/lib/io/secure_server_socket.dart
index b4ca32e..f21b4a27 100644
--- a/sdk/lib/io/secure_server_socket.dart
+++ b/sdk/lib/io/secure_server_socket.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index a4751ef..efec0b3 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/security_context.dart b/sdk/lib/io/security_context.dart
index 96da93b..e98fd78 100644
--- a/sdk/lib/io/security_context.dart
+++ b/sdk/lib/io/security_context.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/service_object.dart b/sdk/lib/io/service_object.dart
index e6b1851..6c0f882 100644
--- a/sdk/lib/io/service_object.dart
+++ b/sdk/lib/io/service_object.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.6
+
part of dart.io;
int _nextServiceId = 1;
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index 5d9c239..d03d5b2 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart
index cc8c7df..8faf791 100644
--- a/sdk/lib/io/stdio.dart
+++ b/sdk/lib/io/stdio.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.6
+
part of dart.io;
const int _stdioHandleTypeTerminal = 0;
diff --git a/sdk/lib/io/string_transformer.dart b/sdk/lib/io/string_transformer.dart
index f31c41e..c399932 100644
--- a/sdk/lib/io/string_transformer.dart
+++ b/sdk/lib/io/string_transformer.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.6
+
part of dart.io;
/// The current system encoding.
diff --git a/sdk/lib/io/sync_socket.dart b/sdk/lib/io/sync_socket.dart
index fee259d..386dc2e 100644
--- a/sdk/lib/io/sync_socket.dart
+++ b/sdk/lib/io/sync_socket.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.6
+
part of dart.io;
/**
diff --git a/sdk/lib/isolate/capability.dart b/sdk/lib/isolate/capability.dart
index a51eec2..4619192 100644
--- a/sdk/lib/isolate/capability.dart
+++ b/sdk/lib/isolate/capability.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.6
+
part of dart.isolate;
/**
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 8773cda..22c40b6 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.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.6
+
/**
* Concurrent programming using _isolates_:
* independent workers that are similar to threads
diff --git a/sdk/lib/js/_js.dart b/sdk/lib/js/_js.dart
index aef7ef9..cddb791 100644
--- a/sdk/lib/js/_js.dart
+++ b/sdk/lib/js/_js.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.6
+
/// Helper library used by `dart:js`.
///
/// This library hides any logic that is specific to the web, and allows us to
diff --git a/sdk/lib/js/_js_client.dart b/sdk/lib/js/_js_client.dart
index de25540..b3070d6 100644
--- a/sdk/lib/js/_js_client.dart
+++ b/sdk/lib/js/_js_client.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.6
+
import 'dart:html' show Blob, Event, ImageData, Node, Window, WorkerGlobalScope;
import 'dart:indexed_db' show KeyRange;
import 'dart:_js_helper' show patch;
diff --git a/sdk/lib/js/_js_server.dart b/sdk/lib/js/_js_server.dart
index b941d77..936c8bf 100644
--- a/sdk/lib/js/_js_server.dart
+++ b/sdk/lib/js/_js_server.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.6
+
import 'dart:_js_helper' show patch;
@patch
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 9c37ea8..317ee7f 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.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.6
+
/// Low-level support for interoperating with JavaScript.
///
/// You should usually use `package:js` instead of this library. For more
diff --git a/sdk/lib/js_util/dart2js/js_util_dart2js.dart b/sdk/lib/js_util/dart2js/js_util_dart2js.dart
index 2e731fb..3ed2098 100644
--- a/sdk/lib/js_util/dart2js/js_util_dart2js.dart
+++ b/sdk/lib/js_util/dart2js/js_util_dart2js.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.6
+
/// Utility methods to efficiently manipulate typed JSInterop objects in cases
/// where the name to call is not known at runtime. You should only use these
/// methods when the same effect cannot be achieved with @JS annotations.
diff --git a/sdk/lib/math/jenkins_smi_hash.dart b/sdk/lib/math/jenkins_smi_hash.dart
index d756b37..7bab10b 100644
--- a/sdk/lib/math/jenkins_smi_hash.dart
+++ b/sdk/lib/math/jenkins_smi_hash.dart
@@ -1,6 +1,8 @@
// Copyright (c) 2013, 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.
+// @dart = 2.6
+
part of dart.math;
/// This is the [Jenkins hash function][1] but using masking to keep
diff --git a/sdk/lib/math/math.dart b/sdk/lib/math/math.dart
index 548fb59..d73b21d 100644
--- a/sdk/lib/math/math.dart
+++ b/sdk/lib/math/math.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.6
+
/// Mathematical constants and functions, plus a random number generator.
///
/// To use this library in your code:
diff --git a/sdk/lib/math/point.dart b/sdk/lib/math/point.dart
index 1015e7b..4bebc0ff 100644
--- a/sdk/lib/math/point.dart
+++ b/sdk/lib/math/point.dart
@@ -1,6 +1,8 @@
// Copyright (c) 2013, 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.
+// @dart = 2.6
+
part of dart.math;
/// A utility class for representing two-dimensional positions.
diff --git a/sdk/lib/math/random.dart b/sdk/lib/math/random.dart
index e2e9d91..65c96be 100644
--- a/sdk/lib/math/random.dart
+++ b/sdk/lib/math/random.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.6
+
part of dart.math;
/// A generator of random bool, int, or double values.
diff --git a/sdk/lib/math/rectangle.dart b/sdk/lib/math/rectangle.dart
index 6e72036..51d90ef 100644
--- a/sdk/lib/math/rectangle.dart
+++ b/sdk/lib/math/rectangle.dart
@@ -1,6 +1,8 @@
// Copyright (c) 2013, 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.
+// @dart = 2.6
+
part of dart.math;
/// A base class for representing two-dimensional axis-aligned rectangles.
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 5e586a0..f15e3d3 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.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.6
+
// For the purposes of the mirrors library, we adopt a naming
// convention with respect to getters and setters. Specifically, for
// some variable or field...
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart
index 7966fd7..ca8fbb2 100644
--- a/sdk/lib/svg/dart2js/svg_dart2js.dart
+++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.6
+
/**
* Scalable Vector Graphics:
* Two-dimensional vector graphics with support for events and animation.
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index 89c9496..d5f091b 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.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.6
+
/// Lists that efficiently handle fixed sized data
/// (for example, unsigned 8 byte integers) and SIMD numeric types.
///
diff --git a/sdk/lib/typed_data/unmodifiable_typed_data.dart b/sdk/lib/typed_data/unmodifiable_typed_data.dart
index 3549041..2b0fe5e 100644
--- a/sdk/lib/typed_data/unmodifiable_typed_data.dart
+++ b/sdk/lib/typed_data/unmodifiable_typed_data.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.6
+
part of dart.typed_data;
/**
diff --git a/sdk/lib/vmservice/asset.dart b/sdk/lib/vmservice/asset.dart
index d5772e2..512a0c9 100644
--- a/sdk/lib/vmservice/asset.dart
+++ b/sdk/lib/vmservice/asset.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.6
+
part of dart._vmservice;
class Asset {
diff --git a/sdk/lib/vmservice/client.dart b/sdk/lib/vmservice/client.dart
index efe33c0..68cdaad 100644
--- a/sdk/lib/vmservice/client.dart
+++ b/sdk/lib/vmservice/client.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.6
+
part of dart._vmservice;
typedef void ClientServiceHandle(Message response);
diff --git a/sdk/lib/vmservice/constants.dart b/sdk/lib/vmservice/constants.dart
index 914576b..fa4b719 100644
--- a/sdk/lib/vmservice/constants.dart
+++ b/sdk/lib/vmservice/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.6
+
part of dart._vmservice;
// These must be kept in sync with runtime/vm/service.cc.
diff --git a/sdk/lib/vmservice/devfs.dart b/sdk/lib/vmservice/devfs.dart
index 20e0573..283006c 100644
--- a/sdk/lib/vmservice/devfs.dart
+++ b/sdk/lib/vmservice/devfs.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.6
+
part of dart._vmservice;
String _encodeDevFSDisabledError(Message message) {
diff --git a/sdk/lib/vmservice/message.dart b/sdk/lib/vmservice/message.dart
index 9e4375a..6f2abcb 100644
--- a/sdk/lib/vmservice/message.dart
+++ b/sdk/lib/vmservice/message.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.6
+
part of dart._vmservice;
enum MessageType { Request, Notification, Response }
diff --git a/sdk/lib/vmservice/message_router.dart b/sdk/lib/vmservice/message_router.dart
index 4c1b307..90ed184 100644
--- a/sdk/lib/vmservice/message_router.dart
+++ b/sdk/lib/vmservice/message_router.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.6
+
part of dart._vmservice;
abstract class MessageRouter {
diff --git a/sdk/lib/vmservice/named_lookup.dart b/sdk/lib/vmservice/named_lookup.dart
index 7087c94..0b5c044 100644
--- a/sdk/lib/vmservice/named_lookup.dart
+++ b/sdk/lib/vmservice/named_lookup.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.6
+
part of dart._vmservice;
/// Set like containes which automatically generated String ids for its items
diff --git a/sdk/lib/vmservice/running_isolate.dart b/sdk/lib/vmservice/running_isolate.dart
index 8a6dd36..f768dec 100644
--- a/sdk/lib/vmservice/running_isolate.dart
+++ b/sdk/lib/vmservice/running_isolate.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.6
+
part of dart._vmservice;
class RunningIsolate implements MessageRouter {
diff --git a/sdk/lib/vmservice/running_isolates.dart b/sdk/lib/vmservice/running_isolates.dart
index 24b155c..191a8d1 100644
--- a/sdk/lib/vmservice/running_isolates.dart
+++ b/sdk/lib/vmservice/running_isolates.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.6
+
part of dart._vmservice;
class RunningIsolates implements MessageRouter {
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index 0c340ee..3c5bcbe 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.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.6
+
library dart._vmservice;
import 'dart:async';
diff --git a/sdk/lib/wasm/wasm.dart b/sdk/lib/wasm/wasm.dart
index 0d123c2..3495b01 100644
--- a/sdk/lib/wasm/wasm.dart
+++ b/sdk/lib/wasm/wasm.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.6
+
/// {@category VM}
/// {@nodoc}
library dart.wasm;
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index ef2ee67..6a431aa 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.6
+
/**
* High-fidelity audio programming in the browser.
*
diff --git a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
index 80e36b1..8a6347f 100644
--- a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.6
+
/**
* 3D programming in the browser.
*
diff --git a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
index 0f703f9..6390fb4 100644
--- a/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
+++ b/sdk/lib/web_sql/dart2js/web_sql_dart2js.dart
@@ -1,3 +1,5 @@
+// @dart = 2.6
+
/**
* An API for storing data in the browser that can be queried with SQL.
*
diff --git a/sdk_nnbd/BUILD.gn b/sdk_nnbd/BUILD.gn
index e637088..33fa0b4 100644
--- a/sdk_nnbd/BUILD.gn
+++ b/sdk_nnbd/BUILD.gn
@@ -690,14 +690,14 @@
visibility = [ ":copy_dev_compiler_sdk" ]
deps = [
":copy_libraries",
- "../utils/dartdevc:dartdevc_kernel_sdk_outline",
+ "../utils/dartdevc:dartdevc_platform",
"../utils/dartdevc:dartdevc_sdk",
]
gen_dir = get_label_info("../utils/dartdevc:dartdevc_sdk", "target_gen_dir")
sources = [
# TODO(vsm): Remove post CFE.
"$gen_dir/ddc_sdk.sum",
- "$gen_dir/kernel/ddc_sdk.dill",
+ "$root_out_dir/ddc_sdk.dill",
]
outputs = [
"$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}",
diff --git a/sdk_nnbd/lib/_http/http.dart b/sdk_nnbd/lib/_http/http.dart
index 2689758..aa591f2 100644
--- a/sdk_nnbd/lib/_http/http.dart
+++ b/sdk_nnbd/lib/_http/http.dart
@@ -128,8 +128,8 @@
* about the streaming qualities of an HttpServer.
* Pausing the subscription of the stream, pauses at the OS level.
*
- * * The [shelf](https://pub.dartlang.org/packages/shelf)
- * package on pub.dartlang.org contains a set of high-level classes that,
+ * * The [shelf](https://pub.dev/packages/shelf)
+ * package on pub.dev contains a set of high-level classes that,
* together with this class, makes it easy to provide content through HTTP
* servers.
*/
@@ -1008,7 +1008,7 @@
* that contains the content of and information about an HTTP request.
*
* __Note__: Check out the
- * [http_server](https://pub.dartlang.org/packages/http_server)
+ * [http_server](https://pub.dev/packages/http_server)
* package, which makes working with the low-level
* dart:io HTTP server subsystem easier.
*
@@ -1404,6 +1404,22 @@
@Deprecated("Use defaultHttpsPort instead")
static const int DEFAULT_HTTPS_PORT = defaultHttpsPort;
+ /// Enable logging of HTTP requests from all [HttpClient]s to the developer
+ /// timeline.
+ ///
+ /// Default is `false`.
+ static set enableTimelineLogging(bool value) {
+ _enableTimelineLogging = value ?? false;
+ }
+
+ /// Current state of HTTP request logging from all [HttpClient]s to the
+ /// developer timeline.
+ ///
+ /// Default is `false`.
+ static bool get enableTimelineLogging => _enableTimelineLogging;
+
+ static bool _enableTimelineLogging = false;
+
/// Gets and sets the idle timeout of non-active persistent (keep-alive)
/// connections.
///
diff --git a/sdk_nnbd/lib/_http/http_impl.dart b/sdk_nnbd/lib/_http/http_impl.dart
index dbbddb6..116da12 100644
--- a/sdk_nnbd/lib/_http/http_impl.dart
+++ b/sdk_nnbd/lib/_http/http_impl.dart
@@ -445,7 +445,9 @@
}
Future<HttpClientResponse> _authenticate(bool proxyAuth) {
+ _httpRequest._timeline?.instant('Authentication');
Future<HttpClientResponse> retry() {
+ _httpRequest._timeline?.instant('Retrying');
// Drain body and retry.
return drain().then((_) {
return _httpClient
@@ -1064,6 +1066,7 @@
// The HttpClient this request belongs to.
final _HttpClient _httpClient;
final _HttpClientConnection _httpClientConnection;
+ final TimelineTask _timeline;
final Completer<HttpClientResponse> _responseCompleter =
new Completer<HttpClientResponse>();
@@ -1080,15 +1083,61 @@
List<RedirectInfo> _responseRedirects = [];
_HttpClientRequest(_HttpOutgoing outgoing, Uri uri, this.method, this._proxy,
- this._httpClient, this._httpClientConnection)
+ this._httpClient, this._httpClientConnection, this._timeline)
: uri = uri,
super(uri, "1.1", outgoing) {
+ _timeline?.instant('Request initiated');
// GET and HEAD have 'content-length: 0' by default.
if (method == "GET" || method == "HEAD") {
contentLength = 0;
} else {
headers.chunkedTransferEncoding = true;
}
+
+ _responseCompleter.future.then((response) {
+ _timeline?.instant('Response receieved');
+ Map formatConnectionInfo() => {
+ 'localPort': response.connectionInfo?.localPort,
+ 'remoteAddress': response.connectionInfo?.remoteAddress?.address,
+ 'remotePort': response.connectionInfo?.remotePort,
+ };
+
+ Map formatHeaders() {
+ final headers = <String, List<String>>{};
+ response.headers.forEach((name, values) {
+ headers[name] = values;
+ });
+ return headers;
+ }
+
+ List<Map<String, dynamic>> formatRedirectInfo() {
+ final redirects = <Map<String, dynamic>>[];
+ for (final redirect in response.redirects) {
+ redirects.add({
+ 'location': redirect.location.toString(),
+ 'method': redirect.method,
+ 'statusCode': redirect.statusCode,
+ });
+ }
+ return redirects;
+ }
+
+ _timeline?.finish(arguments: {
+ // TODO(bkonyi): consider exposing certificate information?
+ // 'certificate': response.certificate,
+ 'requestHeaders': outgoing.outbound.headers._headers,
+ 'compressionState': response.compressionState.toString(),
+ 'connectionInfo': formatConnectionInfo(),
+ 'contentLength': response.contentLength,
+ 'cookies': [for (final cookie in response.cookies) cookie.toString()],
+ 'responseHeaders': formatHeaders(),
+ 'isRedirect': response.isRedirect,
+ 'persistentConnection': response.persistentConnection,
+ 'reasonPhrase': response.reasonPhrase,
+ 'redirects': formatRedirectInfo(),
+ 'statusCode': response.statusCode,
+ });
+ }, onError: (e) {});
}
Future<HttpClientResponse> get done {
@@ -1686,7 +1735,8 @@
});
}
- _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy) {
+ _HttpClientRequest send(
+ Uri uri, int port, String method, _Proxy proxy, TimelineTask timeline) {
if (closed) {
throw new HttpException("Socket closed before request was sent",
uri: uri);
@@ -1698,8 +1748,8 @@
_SiteCredentials creds; // Credentials used to authorize this request.
var outgoing = new _HttpOutgoing(_socket);
// Create new request object, wrapping the outgoing connection.
- var request =
- new _HttpClientRequest(outgoing, uri, method, proxy, _httpClient, this);
+ var request = new _HttpClientRequest(
+ outgoing, uri, method, proxy, _httpClient, this, timeline);
// For the Host header an IPv6 address must be enclosed in []'s.
var host = uri.host;
if (host.contains(':')) host = "[$host]";
@@ -1734,6 +1784,7 @@
creds.authorize(request);
}
}
+
// Start sending the request (lazy, delayed until the user provides
// data).
_httpParser.isHead = method == "HEAD";
@@ -1827,10 +1878,31 @@
.then((_) => _socket.destroy());
}
- Future<_HttpClientConnection> createProxyTunnel(String host, int port,
- _Proxy proxy, bool callback(X509Certificate certificate)) {
+ Future<_HttpClientConnection> createProxyTunnel(
+ String host,
+ int port,
+ _Proxy proxy,
+ bool callback(X509Certificate certificate),
+ TimelineTask timeline) {
+ timeline?.instant('Establishing proxy tunnel', arguments: {
+ 'proxyInfo': {
+ if (proxy.host != null) 'host': proxy.host,
+ if (proxy.port != null)
+ 'port': proxy.port,
+ if (proxy.username != null)
+ 'username': proxy.username,
+ // TODO(bkonyi): is this something we would want to surface? Initial
+ // thought is no.
+ // if (proxy.password != null)
+ // 'password': proxy.password,
+ 'isDirect': proxy.isDirect,
+ }
+ });
+ final method = "CONNECT";
+ final uri = Uri(host: host, port: port);
+ _HttpClient._startRequestTimelineEvent(timeline, method, uri);
_HttpClientRequest request =
- send(new Uri(host: host, port: port), port, "CONNECT", proxy);
+ send(Uri(host: host, port: port), port, method, proxy, timeline);
if (proxy.isAuthenticated) {
// If the proxy configuration contains user information use that
// for proxy basic authorization.
@@ -1840,10 +1912,10 @@
}
return request.close().then((response) {
if (response.statusCode != HttpStatus.ok) {
- throw new HttpException(
- "Proxy failed to establish tunnel "
- "(${response.statusCode} ${response.reasonPhrase})",
- uri: request.uri);
+ final error = "Proxy failed to establish tunnel "
+ "(${response.statusCode} ${response.reasonPhrase})";
+ timeline?.instant(error);
+ throw new HttpException(error, uri: request.uri);
}
var socket = (response as _HttpClientResponse)
._httpRequest
@@ -1853,6 +1925,7 @@
host: host, context: _context, onBadCertificate: callback);
}).then((secureSocket) {
String key = _HttpClientConnection.makeKey(true, host, port);
+ timeline?.instant('Proxy tunnel established');
return new _HttpClientConnection(
key, secureSocket, request._httpClient, true);
});
@@ -1966,8 +2039,8 @@
}
}
- Future<_ConnectionInfo> connect(
- String uriHost, int uriPort, _Proxy proxy, _HttpClient client) {
+ Future<_ConnectionInfo> connect(String uriHost, int uriPort, _Proxy proxy,
+ _HttpClient client, TimelineTask timeline) {
if (hasIdle) {
var connection = takeIdle();
client._connectionsChanged();
@@ -1977,7 +2050,7 @@
_active.length + _connecting >= client.maxConnectionsPerHost) {
var completer = new Completer<_ConnectionInfo>();
_pending.add(() {
- completer.complete(connect(uriHost, uriPort, proxy, client));
+ completer.complete(connect(uriHost, uriPort, proxy, client, timeline));
});
return completer.future;
}
@@ -2023,7 +2096,7 @@
if (isSecure && !proxy.isDirect) {
connection._dispose = true;
return connection
- .createProxyTunnel(uriHost, uriPort, proxy, callback)
+ .createProxyTunnel(uriHost, uriPort, proxy, callback, timeline)
.then((tunnel) {
client
._getConnectionTarget(uriHost, uriPort, true)
@@ -2177,6 +2250,16 @@
set findProxy(String f(Uri uri)) => _findProxy = f;
+ static void _startRequestTimelineEvent(
+ TimelineTask timeline, String method, Uri uri) {
+ timeline?.start('HTTP CLIENT ${method.toUpperCase()}', arguments: {
+ 'filterKey':
+ 'HTTP/client', // key used to filter network requests from timeline
+ 'method': method.toUpperCase(),
+ 'uri': uri.toString(),
+ });
+ }
+
Future<_HttpClientRequest> _openUrl(String method, Uri uri) {
if (_closing) {
throw new StateError("Client is closed");
@@ -2214,19 +2297,32 @@
return new Future.error(error, stackTrace);
}
}
- return _getConnection(uri.host, port, proxyConf, isSecure)
- .then((_ConnectionInfo info) {
+ TimelineTask timeline;
+ // TODO(bkonyi): do we want this to be opt-in?
+ if (HttpClient.enableTimelineLogging) {
+ timeline = TimelineTask();
+ _startRequestTimelineEvent(timeline, method, uri);
+ }
+ return _getConnection(uri.host, port, proxyConf, isSecure, timeline).then(
+ (_ConnectionInfo info) {
_HttpClientRequest send(_ConnectionInfo info) {
+ timeline?.instant('Connection established');
return info.connection
- .send(uri, port, method.toUpperCase(), info.proxy);
+ .send(uri, port, method.toUpperCase(), info.proxy, timeline);
}
// If the connection was closed before the request was sent, create
// and use another connection.
if (info.connection.closed) {
- return _getConnection(uri.host, port, proxyConf, isSecure).then(send);
+ return _getConnection(uri.host, port, proxyConf, isSecure, timeline)
+ .then(send);
}
return send(info);
+ }, onError: (error) {
+ timeline?.finish(arguments: {
+ 'error': error.toString(),
+ });
+ throw error;
});
}
@@ -2293,7 +2389,7 @@
// Get a new _HttpClientConnection, from the matching _ConnectionTarget.
Future<_ConnectionInfo> _getConnection(String uriHost, int uriPort,
- _ProxyConfiguration proxyConf, bool isSecure) {
+ _ProxyConfiguration proxyConf, bool isSecure, TimelineTask timeline) {
Iterator<_Proxy> proxies = proxyConf.proxies.iterator;
Future<_ConnectionInfo> connect(error) {
@@ -2302,7 +2398,7 @@
String host = proxy.isDirect ? uriHost : proxy.host;
int port = proxy.isDirect ? uriPort : proxy.port;
return _getConnectionTarget(host, port, isSecure)
- .connect(uriHost, uriPort, proxy, this)
+ .connect(uriHost, uriPort, proxy, this, timeline)
// On error, continue with next proxy.
.catchError(connect);
}
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart
index 894aef4..089ed04 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/async_patch.dart
@@ -24,11 +24,11 @@
@ReifyFunctionTypes(false)
_async<T>(Function() initGenerator) {
var iter;
- Object Function(Object) onValue;
- Object Function(Object, StackTrace) onError;
+ late Object? Function(Object?) onValue;
+ late Object Function(Object, StackTrace) onError;
- onAwait(Object value) {
- _Future f;
+ onAwait(Object? value) {
+ _Future<Object?> f;
if (value is _Future) {
f = value;
} else if (value is Future) {
@@ -159,7 +159,7 @@
}
@ReifyFunctionTypes(false)
- static Object _scheduleImmediateWithPromise(void Function() callback) {
+ static void _scheduleImmediateWithPromise(void Function() callback) {
dart.addAsyncCallback();
JS('', '#.Promise.resolve(null).then(#)', dart.global_, () {
dart.removeAsyncCallback();
@@ -180,7 +180,7 @@
@patch
class Timer {
@patch
- static Timer _createTimer(Duration duration, void callback()) {
+ static Timer _createTimer(Duration duration, void Function() callback) {
int milliseconds = duration.inMilliseconds;
if (milliseconds < 0) milliseconds = 0;
return TimerImpl(milliseconds, callback);
@@ -196,7 +196,7 @@
}
@patch
-void _rethrow(Object error, StackTrace stackTrace) {
+void _rethrow(Object error, StackTrace? stackTrace) {
JS('', 'throw #', dart.createErrorWithStack(error, stackTrace));
}
@@ -226,7 +226,7 @@
/// }
///
class _AsyncStarImpl<T> {
- StreamController<T> controller;
+ late StreamController<T> controller;
Object Function(_AsyncStarImpl<T>) initGenerator;
@notNull
bool isSuspendedAtYieldStar = false;
@@ -241,11 +241,11 @@
@notNull
bool isSuspendedAtAwait = false;
- Completer cancellationCompleter;
- Object jsIterator;
+ Completer? cancellationCompleter;
+ late Object jsIterator;
- Null Function(Object, StackTrace) _handleErrorCallback;
- void Function([Object]) _runBodyCallback;
+ Null Function(Object, StackTrace)? _handleErrorCallback;
+ void Function([Object?])? _runBodyCallback;
_AsyncStarImpl(this.initGenerator) {
controller = StreamController(
@@ -291,10 +291,10 @@
};
var zone = Zone.current;
if (!identical(zone, Zone.root)) {
- _handleErrorCallback = zone.bindBinaryCallback(_handleErrorCallback);
+ _handleErrorCallback = zone.bindBinaryCallback(_handleErrorCallback!);
}
}
- return _handleErrorCallback;
+ return _handleErrorCallback!;
}
void scheduleGenerator() {
@@ -316,11 +316,11 @@
if (_runBodyCallback == null) {
_runBodyCallback = JS('!', '#.bind(this)', runBody);
if (!identical(zone, Zone.root)) {
- var registered = zone.registerUnaryCallback(_runBodyCallback);
+ var registered = zone.registerUnaryCallback(_runBodyCallback!);
_runBodyCallback = ([arg]) => zone.runUnaryGuarded(registered, arg);
}
}
- zone.scheduleMicrotask(_runBodyCallback);
+ zone.scheduleMicrotask(_runBodyCallback!);
}
void runBody(awaitValue) {
@@ -333,16 +333,16 @@
iterResult = JS('', '#.next(#)', jsIterator, awaitValue);
} catch (e, s) {
addError(e, s);
- return null;
+ return;
}
if (JS('!', '#.done', iterResult)) {
close();
- return null;
+ return;
}
// If we're suspended at a yield/yield*, we're done for now.
- if (isSuspendedAtYield || isSuspendedAtYieldStar) return null;
+ if (isSuspendedAtYield || isSuspendedAtYieldStar) return;
// Handle `await`: if we get a value passed to `yield` it means we are
// waiting on this Future. Make sure to prevent scheduling, and pass the
@@ -351,10 +351,10 @@
// TODO(jmesserly): is the timing here correct? The assumption here is
// that we should schedule `await` in `async*` the same as in `async`.
isSuspendedAtAwait = true;
- FutureOr<Object> value = JS('', '#.value', iterResult);
+ FutureOr<Object?> value = JS('', '#.value', iterResult);
// TODO(jmesserly): this logic was copied from `async` function impl.
- _Future f;
+ _Future<Object?> f;
if (value is _Future) {
f = value;
} else if (value is Future) {
@@ -363,7 +363,7 @@
} else {
f = _Future.value(value);
}
- f._thenAwait(_runBodyCallback, handleError);
+ f._thenAwait(_runBodyCallback!, handleError);
}
/// Adds element to [stream] and returns true if the caller should terminate
@@ -417,10 +417,11 @@
}
void addError(Object error, StackTrace stackTrace) {
- if (cancellationCompleter != null && !cancellationCompleter.isCompleted) {
+ var completer = cancellationCompleter;
+ if (completer != null && !completer.isCompleted) {
// If the stream has been cancelled, complete the cancellation future
// with the error.
- cancellationCompleter.completeError(error, stackTrace);
+ completer.completeError(error, stackTrace);
} else if (controller.hasListener) {
controller.addError(error, stackTrace);
}
@@ -432,10 +433,11 @@
}
void close() {
- if (cancellationCompleter != null && !cancellationCompleter.isCompleted) {
+ var completer = cancellationCompleter;
+ if (completer != null && !completer.isCompleted) {
// If the stream has been cancelled, complete the cancellation future
// with the error.
- cancellationCompleter.complete();
+ completer.complete();
}
controller.close();
}
@@ -465,7 +467,7 @@
scheduleGenerator();
}
}
- return cancellationCompleter.future;
+ return cancellationCompleter!.future;
}
_fatal(String message) => throw StateError(message);
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/convert_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/convert_patch.dart
index 486473b..c945df2 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/convert_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/convert_patch.dart
@@ -8,7 +8,7 @@
import 'dart:_foreign_helper' show JS;
import 'dart:_interceptors' show JSExtendableArray;
import 'dart:_internal' show MappedIterable, ListIterable;
-import 'dart:collection' show Maps, LinkedHashMap, MapBase;
+import 'dart:collection' show LinkedHashMap, MapBase;
import 'dart:_native_typed_data' show NativeUint8List;
/**
@@ -28,7 +28,7 @@
* Throws [FormatException] if the input is not valid JSON text.
*/
@patch
-_parseJson(String source, reviver(Object key, Object value)) {
+_parseJson(String source, reviver(key, value)?) {
if (source is! String) throw argumentErrorValue(source);
var parsed;
@@ -51,8 +51,7 @@
* Maps. [json] is expected to be freshly allocated so elements can be replaced
* in-place.
*/
-_convertJsonToDart(json, reviver(Object key, Object value)) {
- assert(reviver != null);
+_convertJsonToDart(json, reviver(Object? key, Object? value)) {
walk(e) {
// JavaScript null, string, number, bool are in the correct representation.
if (JS<bool>('!', '# == null', e) ||
@@ -212,7 +211,7 @@
return value;
}
- remove(Object key) {
+ remove(Object? key) {
if (!_isUpgraded && !containsKey(key)) return null;
return _upgrade().remove(key);
}
@@ -296,7 +295,7 @@
// safely force a concurrent modification error in case
// someone is iterating over the map here.
if (keys.isEmpty) {
- keys.add(null);
+ keys.add("");
} else {
keys.clear();
}
@@ -355,13 +354,13 @@
/// Delegate to [parent.containsKey] to ensure the performance expected
/// from [Map.keys.containsKey].
- bool contains(Object key) => _parent.containsKey(key);
+ bool contains(Object? key) => _parent.containsKey(key);
}
@patch
class JsonDecoder {
@patch
- StringConversionSink startChunkedConversion(Sink<Object> sink) {
+ StringConversionSink startChunkedConversion(Sink<Object?> sink) {
return _JsonDecoderSink(_reviver, sink);
}
}
@@ -373,17 +372,16 @@
* The sink only creates one object, but its input can be chunked.
*/
// TODO(floitsch): don't accumulate everything before starting to decode.
-class _JsonDecoderSink extends _StringSinkConversionSink {
- final Function(Object key, Object value) _reviver;
- final Sink<Object> _sink;
+class _JsonDecoderSink extends _StringSinkConversionSink<StringBuffer> {
+ final Object? Function(Object? key, Object? value)? _reviver;
+ final Sink<Object?> _sink;
_JsonDecoderSink(this._reviver, this._sink) : super(StringBuffer(''));
void close() {
super.close();
- StringBuffer buffer = _stringSink;
- String accumulated = buffer.toString();
- buffer.clear();
+ String accumulated = _stringSink.toString();
+ _stringSink.clear();
Object decoded = _parseJson(accumulated, _reviver);
_sink.add(decoded);
_sink.close();
@@ -399,8 +397,8 @@
// Currently not intercepting UTF8 decoding.
@patch
- static String _convertIntercepted(
- bool allowMalformed, List<int> codeUnits, int start, int end) {
+ static String? _convertIntercepted(
+ bool allowMalformed, List<int> codeUnits, int start, int? end) {
// Test `codeUnits is NativeUint8List`. Dart's NativeUint8List is
// implemented by JavaScript's Uint8Array.
if (JS<bool>('!', '# instanceof Uint8Array', codeUnits)) {
@@ -410,8 +408,8 @@
}
}
- static String _convertInterceptedUint8List(
- bool allowMalformed, NativeUint8List codeUnits, int start, int end) {
+ static String? _convertInterceptedUint8List(
+ bool allowMalformed, NativeUint8List codeUnits, int start, int? end) {
if (allowMalformed) {
// TextDecoder with option {fatal: false} does not produce the same result
// as [Utf8Decoder]. It disagrees on the number of `U+FFFD` (REPLACEMENT
@@ -442,12 +440,12 @@
JS<NativeUint8List>('!', '#.subarray(#, #)', codeUnits, start, end));
}
- static String _useTextDecoderChecked(decoder, NativeUint8List codeUnits) {
+ static String? _useTextDecoderChecked(decoder, NativeUint8List codeUnits) {
if (_unsafe(codeUnits)) return null;
return _useTextDecoderUnchecked(decoder, codeUnits);
}
- static String _useTextDecoderUnchecked(decoder, NativeUint8List codeUnits) {
+ static String? _useTextDecoderUnchecked(decoder, NativeUint8List codeUnits) {
// If the input is malformed, catch the exception and return `null` to fall
// back on unintercepted decoder. The fallback will either succeed in
// decoding, or report the problem better than TextDecoder.
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
index 48e9236..a8e6e12 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -28,7 +28,7 @@
String _symbolToString(Symbol symbol) => symbol is PrivateSymbol
? PrivateSymbol.getName(symbol)
- : _symbol_dev.Symbol.getName(symbol);
+ : _symbol_dev.Symbol.getName(symbol as _symbol_dev.Symbol);
@patch
int identityHashCode(Object? object) {
@@ -102,7 +102,7 @@
@patch
class Function {
@patch
- static apply(Function f, List<Object>? positionalArguments,
+ static apply(Function function, List<dynamic>? positionalArguments,
[Map<Symbol, dynamic>? namedArguments]) {
positionalArguments ??= [];
// dcall expects the namedArguments as a JS map in the last slot.
@@ -111,9 +111,9 @@
namedArguments.forEach((symbol, arg) {
JS('', '#[#] = #', map, _symbolToString(symbol), arg);
});
- return dart.dcall(f, positionalArguments, map);
+ return dart.dcall(function, positionalArguments, map);
}
- return dart.dcall(f, positionalArguments);
+ return dart.dcall(function, positionalArguments);
}
static Map<String, dynamic> _toMangledNames(
@@ -132,14 +132,14 @@
@JSExportName('as')
static Object _as_Function(Object o) {
// Avoid extra function call to core.Function.is() by manually inlining.
- if (JS<Object>('!', 'typeof $o == "function"') || o == null) return o;
+ if (JS<bool>('!', 'typeof $o == "function"') || o == null) return o;
return dart.cast(o, dart.unwrapType(Function), false);
}
@JSExportName('_check')
static Object _check_Function(Object o) {
// Avoid extra function call to core.Function.is() by manually inlining.
- if (JS<Object>('!', 'typeof $o == "function"') || o == null) return o;
+ if (JS<bool>('!', 'typeof $o == "function"') || o == null) return o;
return dart.cast(o, dart.unwrapType(Function), true);
}
}
@@ -188,7 +188,7 @@
@patch
static int parse(String source,
{int? radix, @deprecated int onError(String source)?}) {
- return Primitives.parseInt(source, radix, onError)!;
+ return Primitives.parseInt(source, radix, onError);
}
@patch
@@ -233,8 +233,8 @@
class double {
@patch
static double parse(String source,
- [@deprecated double onError(String source)]) {
- return Primitives.parseDouble(source, onError)!;
+ [@deprecated double onError(String source)?]) {
+ return Primitives.parseDouble(source, onError);
}
@patch
@@ -308,7 +308,7 @@
@patch
class Error {
@patch
- static String _objectToString(Object? object) {
+ static String _objectToString(Object object) {
return "Instance of '${dart.typeName(dart.getReifiedType(object))}'";
}
@@ -318,7 +318,7 @@
}
@patch
- StackTrace get stackTrace => dart.stackTraceForError(this);
+ StackTrace? get stackTrace => dart.stackTraceForError(this);
}
@patch
@@ -452,7 +452,7 @@
int get weekday => Primitives.getWeekday(this);
@patch
- bool operator ==(dynamic other) =>
+ bool operator ==(Object other) =>
other is DateTime &&
_value == other.millisecondsSinceEpoch &&
isUtc == other.isUtc;
@@ -505,16 +505,16 @@
@patch
class List<E> {
@patch
- factory List([@undefined int _length]) {
+ factory List([@undefined int? length]) {
dynamic list;
- if (JS<bool>('!', '# === void 0', _length)) {
+ if (JS<bool>('!', '# === void 0', length)) {
list = JS('', '[]');
} else {
- int length = JS('!', '#', _length);
- if (_length == null || length < 0) {
+ int _length = JS('!', '#', length);
+ if (length == null || _length < 0) {
throw ArgumentError("Length must be a non-negative integer: $_length");
}
- list = JS('', 'new Array(#)', length);
+ list = JS('', 'new Array(#)', _length);
JS('', '#.fill(null)', list);
JSArray.markFixedList(list);
}
@@ -522,7 +522,7 @@
}
@patch
- factory List.empty({bool growable = false}) {
+ factory List.empty({bool growable = true}) {
var list = JSArray<E>.of(JS('', 'new Array()'));
if (!growable) JSArray.markFixedList(list);
return list;
@@ -565,7 +565,7 @@
@patch
class Map<K, V> {
@patch
- factory Map.unmodifiable(Map other) {
+ factory Map.unmodifiable(Map<dynamic, dynamic> other) {
return UnmodifiableMapView<K, V>(Map<K, V>.from(other));
}
@@ -740,7 +740,7 @@
}
@patch
- void writeAll(Iterable objects, [String separator = ""]) {
+ void writeAll(Iterable<dynamic> objects, [String separator = ""]) {
_contents = _writeAll(_contents, objects, separator);
}
@@ -796,18 +796,15 @@
final Symbol _memberName;
final List? _arguments;
final Map<Symbol, dynamic>? _namedArguments;
- final List? _existingArgumentNames;
final Invocation? _invocation;
@patch
NoSuchMethodError(Object? receiver, Symbol memberName,
- List? positionalArguments, Map<Symbol, dynamic>? namedArguments,
- [List? existingArgumentNames = null])
+ List? positionalArguments, Map<Symbol, dynamic>? namedArguments)
: _receiver = receiver,
_memberName = memberName,
_arguments = positionalArguments,
_namedArguments = namedArguments,
- _existingArgumentNames = existingArgumentNames,
_invocation = null;
@patch
@@ -816,7 +813,6 @@
_memberName = invocation.memberName,
_arguments = invocation.positionalArguments,
_namedArguments = invocation.namedArguments,
- _existingArgumentNames = null,
_invocation = invocation;
@patch
@@ -848,20 +844,10 @@
var failureMessage = (invocation is dart.InvocationImpl)
? invocation.failureMessage
: 'method not found';
- List? existingArgumentNames = _existingArgumentNames;
- if (existingArgumentNames == null) {
- return "NoSuchMethodError: '$memberName'\n"
- "$failureMessage\n"
- "Receiver: ${receiverText}\n"
- "Arguments: [$actualParameters]";
- } else {
- String formalParameters = existingArgumentNames.join(', ');
- return "NoSuchMethodError: incorrect number of arguments passed to "
- "method named '$memberName'\n"
- "Receiver: ${receiverText}\n"
- "Tried calling: $memberName($actualParameters)\n"
- "Found: $memberName($formalParameters)";
- }
+ return "NoSuchMethodError: '$memberName'\n"
+ "$failureMessage\n"
+ "Receiver: ${receiverText}\n"
+ "Arguments: [$actualParameters]";
}
}
@@ -957,6 +943,9 @@
int _max(int a, int b) => a > b ? a : b;
int _min(int a, int b) => a < b ? a : b;
+/// Empty list used as an initializer for local variables in the `_BigIntImpl`.
+final _dummyList = new Uint16List(0);
+
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -1014,14 +1003,14 @@
// Result cache for last _divRem call.
// Result cache for last _divRem call.
- static Uint16List _lastDividendDigits;
- static int _lastDividendUsed;
- static Uint16List _lastDivisorDigits;
- static int _lastDivisorUsed;
- static Uint16List _lastQuoRemDigits;
- static int _lastQuoRemUsed;
- static int _lastRemUsed;
- static int _lastRem_nsh;
+ static Uint16List? _lastDividendDigits;
+ static int? _lastDividendUsed;
+ static Uint16List? _lastDivisorDigits;
+ static int? _lastDivisorUsed;
+ static Uint16List? _lastQuoRemDigits;
+ static int? _lastQuoRemUsed;
+ static int? _lastRemUsed;
+ static int? _lastRem_nsh;
/// Whether this bigint is negative.
final bool _isNegative;
@@ -1081,7 +1070,7 @@
// Read in the source 4 digits at a time.
// The first part may have a few leading virtual '0's to make the remaining
// parts all have exactly 4 digits.
- int digitInPartCount = 4 - source.length.remainder(4);
+ var digitInPartCount = 4 - source.length.remainder(4);
if (digitInPartCount == 4) digitInPartCount = 0;
for (int i = 0; i < source.length; i++) {
part = part * 10 + source.codeUnitAt(i) - _0;
@@ -1123,7 +1112,7 @@
/// If [isNegative] is true, negates the result before returning it.
///
/// The [source] (substring) must be a valid hex literal.
- static _BigIntImpl _parseHex(String source, int startPos, bool isNegative) {
+ static _BigIntImpl? _parseHex(String source, int startPos, bool isNegative) {
int hexDigitsPerChunk = _digitBits ~/ 4;
int sourceLength = source.length - startPos;
int chunkCount = (sourceLength / hexDigitsPerChunk).ceil();
@@ -1157,7 +1146,7 @@
///
/// The [source] will be checked for invalid characters. If it is invalid,
/// this function returns `null`.
- static _BigIntImpl _parseRadix(String source, int radix, bool isNegative) {
+ static _BigIntImpl? _parseRadix(String source, int radix, bool isNegative) {
var result = zero;
var base = _BigIntImpl._fromInt(radix);
for (int i = 0; i < source.length; i++) {
@@ -1209,11 +1198,11 @@
return _parseDecimal(decimalMatch, isNegative);
}
if (radix == 16 && (decimalMatch != null || nonDecimalMatch != null)) {
- return _parseHex(decimalMatch ?? nonDecimalMatch, 0, isNegative);
+ return _parseHex(decimalMatch ?? nonDecimalMatch!, 0, isNegative);
}
return _parseRadix(
- decimalMatch ?? nonDecimalMatch ?? hexMatch, radix, isNegative);
+ decimalMatch ?? nonDecimalMatch ?? hexMatch!, radix, isNegative);
}
static RegExp _parseRE = RegExp(
@@ -1261,7 +1250,7 @@
// then use the bit-manipulating `_fromDouble` for all other values.
if (value.abs() < 0x100000000) return _BigIntImpl._fromInt(value.toInt());
if (value is double) return _BigIntImpl._fromDouble(value);
- return _BigIntImpl._fromInt(value);
+ return _BigIntImpl._fromInt(value as int);
}
factory _BigIntImpl._fromInt(int value) {
@@ -1563,8 +1552,7 @@
///
/// Returns 0 if abs(this) == abs(other); a positive number if
/// abs(this) > abs(other); and a negative number if abs(this) < abs(other).
- int _absCompare(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ int _absCompare(_BigIntImpl other) {
return _compareDigits(_digits, _used, other._digits, other._used);
}
@@ -1574,8 +1562,7 @@
* Returns a negative number if `this` is less than `other`, zero if they are
* equal, and a positive number if `this` is greater than `other`.
*/
- int compareTo(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ int compareTo(covariant _BigIntImpl other) {
if (_isNegative == other._isNegative) {
var result = _absCompare(other);
// Use 0 - result to avoid negative zero in JavaScript.
@@ -1717,7 +1704,8 @@
var digits = _digits;
var otherDigits = other._digits;
var resultDigits = Uint16List(resultUsed);
- var l, m;
+ _BigIntImpl l;
+ int m;
if (used < otherUsed) {
l = other;
m = used;
@@ -1743,7 +1731,8 @@
var digits = _digits;
var otherDigits = other._digits;
var resultDigits = Uint16List(resultUsed);
- var l, m;
+ _BigIntImpl l;
+ int m;
if (used < otherUsed) {
l = other;
m = used;
@@ -1771,8 +1760,7 @@
* Of both operands are negative, the result is negative, otherwise
* the result is non-negative.
*/
- _BigIntImpl operator &(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator &(covariant _BigIntImpl other) {
if (_isZero || other._isZero) return zero;
if (_isNegative == other._isNegative) {
if (_isNegative) {
@@ -1787,7 +1775,7 @@
return _absAndSetSign(other, false);
}
// _isNegative != other._isNegative
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1811,8 +1799,7 @@
* If both operands are non-negative, the result is non-negative,
* otherwise the result us negative.
*/
- _BigIntImpl operator |(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator |(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
if (_isNegative == other._isNegative) {
@@ -1828,7 +1815,7 @@
return _absOrSetSign(other, false);
}
// _neg != a._neg
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1853,8 +1840,7 @@
* If the operands have the same sign, the result is non-negative,
* otherwise the result is negative.
*/
- _BigIntImpl operator ^(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator ^(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
if (_isNegative == other._isNegative) {
@@ -1867,7 +1853,7 @@
return _absXorSetSign(other, false);
}
// _isNegative != a._isNegative
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1902,8 +1888,7 @@
}
/// Addition operator.
- _BigIntImpl operator +(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator +(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
var isNegative = _isNegative;
@@ -1921,8 +1906,7 @@
}
/// Subtraction operator.
- _BigIntImpl operator -(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator -(covariant _BigIntImpl other) {
if (_isZero) return -other;
if (other._isZero) return this;
var isNegative = _isNegative;
@@ -1974,8 +1958,7 @@
}
/// Multiplication operator.
- _BigIntImpl operator *(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator *(covariant _BigIntImpl other) {
var used = _used;
var otherUsed = other._used;
if (used == 0 || otherUsed == 0) {
@@ -2023,8 +2006,7 @@
}
/// Returns `trunc(this / other)`, with `other != 0`.
- _BigIntImpl _div(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl _div(_BigIntImpl other) {
assert(other._used > 0);
if (_used < other._used) {
return zero;
@@ -2032,9 +2014,9 @@
_divRem(other);
// Return quotient, i.e.
// _lastQuoRem_digits[_lastRem_used.._lastQuoRem_used-1] with proper sign.
- var lastQuo_used = _lastQuoRemUsed - _lastRemUsed;
+ var lastQuo_used = _lastQuoRemUsed! - _lastRemUsed!;
var quo_digits = _cloneDigits(
- _lastQuoRemDigits, _lastRemUsed, _lastQuoRemUsed, lastQuo_used);
+ _lastQuoRemDigits!, _lastRemUsed!, _lastQuoRemUsed!, lastQuo_used);
var quo = _BigIntImpl._(false, lastQuo_used, quo_digits);
if ((_isNegative != other._isNegative) && (quo._used > 0)) {
quo = -quo;
@@ -2043,8 +2025,7 @@
}
/// Returns `this - other * trunc(this / other)`, with `other != 0`.
- _BigIntImpl _rem(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl _rem(_BigIntImpl other) {
assert(other._used > 0);
if (_used < other._used) {
return this;
@@ -2053,10 +2034,10 @@
// Return remainder, i.e.
// denormalized _lastQuoRem_digits[0.._lastRem_used-1] with proper sign.
var remDigits =
- _cloneDigits(_lastQuoRemDigits, 0, _lastRemUsed, _lastRemUsed);
- var rem = _BigIntImpl._(false, _lastRemUsed, remDigits);
- if (_lastRem_nsh > 0) {
- rem = rem >> _lastRem_nsh; // Denormalize remainder.
+ _cloneDigits(_lastQuoRemDigits!, 0, _lastRemUsed!, _lastRemUsed!);
+ var rem = _BigIntImpl._(false, _lastRemUsed!, remDigits);
+ if (_lastRem_nsh! > 0) {
+ rem = rem >> _lastRem_nsh!; // Denormalize remainder.
}
if (_isNegative && (rem._used > 0)) {
rem = -rem;
@@ -2244,8 +2225,7 @@
* seven.remainder(-three); // => 1
* ```
*/
- _BigIntImpl operator ~/(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator ~/(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2259,8 +2239,7 @@
* `this == (this ~/ other) * other + r`.
* As a consequence the remainder `r` has the same sign as the divider `this`.
*/
- _BigIntImpl remainder(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl remainder(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2271,16 +2250,16 @@
double operator /(BigInt other) => this.toDouble() / other.toDouble();
/** Relational less than operator. */
- bool operator <(BigInt other) => compareTo(other) < 0;
+ bool operator <(covariant _BigIntImpl other) => compareTo(other) < 0;
/** Relational less than or equal operator. */
- bool operator <=(BigInt other) => compareTo(other) <= 0;
+ bool operator <=(covariant _BigIntImpl other) => compareTo(other) <= 0;
/** Relational greater than operator. */
- bool operator >(BigInt other) => compareTo(other) > 0;
+ bool operator >(covariant _BigIntImpl other) => compareTo(other) > 0;
/** Relational greater than or equal operator. */
- bool operator >=(BigInt other) => compareTo(other) >= 0;
+ bool operator >=(covariant _BigIntImpl other) => compareTo(other) >= 0;
/**
* Euclidean modulo operator.
@@ -2293,8 +2272,7 @@
*
* See [remainder] for the remainder of the truncating division.
*/
- _BigIntImpl operator %(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator %(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2357,9 +2335,8 @@
* The [exponent] must be non-negative and [modulus] must be
* positive.
*/
- _BigIntImpl modPow(BigInt bigExponent, BigInt bigModulus) {
- _BigIntImpl exponent = bigExponent;
- _BigIntImpl modulus = bigModulus;
+ _BigIntImpl modPow(
+ covariant _BigIntImpl exponent, covariant _BigIntImpl modulus) {
if (exponent._isNegative) {
throw ArgumentError("exponent must be positive: $exponent");
}
@@ -2383,7 +2360,7 @@
resultDigits[j] = gDigits[j];
}
var resultUsed = gUsed;
- var result2Used;
+ int result2Used;
for (int i = exponentBitlen - 2; i >= 0; i--) {
result2Used = z.sqr(resultDigits, resultUsed, result2Digits);
if (!(exponent & (one << i))._isZero) {
@@ -2458,19 +2435,19 @@
// Variables a, b, c, and d require one more digit.
final abcdUsed = maxUsed + 1;
final abcdLen = abcdUsed + 2; // +2 to satisfy _absAdd.
- var aDigits, bDigits, cDigits, dDigits;
- bool aIsNegative, bIsNegative, cIsNegative, dIsNegative;
+ var aDigits = _dummyList;
+ var aIsNegative = false;
+ var cDigits = _dummyList;
+ var cIsNegative = false;
if (ac) {
aDigits = Uint16List(abcdLen);
- aIsNegative = false;
aDigits[0] = 1;
cDigits = Uint16List(abcdLen);
- cIsNegative = false;
}
- bDigits = Uint16List(abcdLen);
- bIsNegative = false;
- dDigits = Uint16List(abcdLen);
- dIsNegative = false;
+ var bDigits = Uint16List(abcdLen);
+ var bIsNegative = false;
+ var dDigits = Uint16List(abcdLen);
+ var dIsNegative = false;
dDigits[0] = 1;
while (true) {
@@ -2663,8 +2640,7 @@
* It is an error if no modular inverse exists.
*/
// Returns 1/this % modulus, with modulus > 0.
- _BigIntImpl modInverse(BigInt bigInt) {
- _BigIntImpl modulus = bigInt;
+ _BigIntImpl modInverse(covariant _BigIntImpl modulus) {
if (modulus <= zero) {
throw ArgumentError("Modulus must be strictly positive: $modulus");
}
@@ -2689,8 +2665,7 @@
*
* If both `this` and `other` is zero, the result is also zero.
*/
- _BigIntImpl gcd(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl gcd(covariant _BigIntImpl other) {
if (_isZero) return other.abs();
if (other._isZero) return this.abs();
return _binaryGcd(this, other, false);
@@ -3009,8 +2984,8 @@
_modulus._digits[_modulus._used - 1].bitLength);
int convert(_BigIntImpl x, Uint16List resultDigits) {
- var digits;
- var used;
+ Uint16List digits;
+ int used;
if (x._isNegative || x._absCompare(_modulus) >= 0) {
var remainder = x._rem(_modulus);
if (x._isNegative && remainder._used > 0) {
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart
index 5e850bb..6ab95c4 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/patch/internal_patch.dart
@@ -2,8 +2,6 @@
// 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:core' hide Symbol;
-import 'dart:core' as core show Symbol;
import 'dart:_js_primitives' show printString;
import 'dart:_js_helper' show patch;
import 'dart:_interceptors' show JSArray;
@@ -17,7 +15,7 @@
@patch
int get hashCode {
- int hash = JS('int|Null', '#._hashCode', this);
+ int? hash = JS('int|Null', '#._hashCode', this);
if (hash != null) return hash;
const arbitraryPrime = 664597;
hash = 0x1fffffff & (arbitraryPrime * _name.hashCode);
@@ -38,13 +36,13 @@
}
@patch
-List<E> makeListFixedLength<E>(List<E> growableList) {
+List<T> makeListFixedLength<T>(List<T> growableList) {
JSArray.markFixedList(growableList);
return growableList;
}
@patch
-List<E> makeFixedListUnmodifiable<E>(List<E> fixedLengthList) {
+List<T> makeFixedListUnmodifiable<T>(List<T> fixedLengthList) {
JSArray.markUnmodifiableList(fixedLengthList);
return fixedLengthList;
}
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
index b4ee6a6..c9263ba 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
@@ -34,8 +34,7 @@
// TODO(vsm): Per spec, we should throw an NSM here. Technically, we ought
// to thread through method info, but that uglifies the code and can't
// actually be queried ... it only affects how the error is printed.
- throw NoSuchMethodError(
- null, Symbol('<Unexpected Null Value>'), null, null, null);
+ throw NoSuchMethodError(null, Symbol('<Unexpected Null Value>'), null, null);
}
castError(obj, expectedType, [@notNull bool isImplicit = false]) {
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/debugger.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/debugger.dart
index 8715cbd..f6ec3b3 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/debugger.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/debugger.dart
@@ -2,8 +2,6 @@
// 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.5
-
library dart._debugger;
import 'dart:_foreign_helper' show JS;
@@ -172,7 +170,7 @@
/// [JsonMLFormatter] consumes [NameValuePair] objects and
class NameValuePair {
NameValuePair(
- {this.name,
+ {this.name = '',
this.value,
this.config = JsonMLConfig.none,
this.hideName = false});
@@ -188,7 +186,7 @@
int get hashCode => name.hashCode;
final String name;
- final Object value;
+ final Object? value;
final JsonMLConfig config;
final bool hideName;
@@ -198,8 +196,8 @@
class MapEntry {
MapEntry({this.key, this.value});
- final Object key;
- final Object value;
+ final Object? key;
+ final Object? value;
}
class IterableSpan {
@@ -217,7 +215,7 @@
/// 10000-length subset and 1 1-length subset.
int get maxPowerOfSubsetSize =>
(log(length - .5) / log(_maxSpanLength)).truncate();
- int get subsetSize => pow(_maxSpanLength, maxPowerOfSubsetSize);
+ int get subsetSize => pow(_maxSpanLength, maxPowerOfSubsetSize).toInt();
Map<int, dynamic> asMap() =>
iterable.skip(start).take(length).toList().asMap();
@@ -285,7 +283,7 @@
/// Devtools Formatter API.
class JsonMLElement {
dynamic _attributes;
- List _jsonML;
+ late List _jsonML;
JsonMLElement(tagName) {
_attributes = JS('', '{}');
@@ -409,7 +407,7 @@
// The value is indented when it is on a different line from the name
// by setting right padding of the name to -13px and the padding of the
// value to 13px.
- JsonMLElement nameSpan;
+ JsonMLElement? nameSpan;
var valueStyle = '';
if (!child.hideName) {
nameSpan = JsonMLElement('span')
@@ -445,38 +443,36 @@
abstract class Formatter {
bool accept(object, config);
- String preview(object);
+ String? preview(object);
bool hasChildren(object);
- List<NameValuePair> children(object);
+ List<NameValuePair>? children(object);
}
class DartFormatter {
- List<Formatter> _formatters;
+ final List<Formatter> _formatters;
- DartFormatter() {
- // The order of formatters matters as formatters earlier in the list take
- // precedence.
- _formatters = [
- ObjectInternalsFormatter(),
- ClassFormatter(),
- TypeFormatter(),
- NamedConstructorFormatter(),
- MapFormatter(),
- MapOverviewFormatter(),
- IterableFormatter(),
- IterableSpanFormatter(),
- MapEntryFormatter(),
- StackTraceFormatter(),
- ErrorAndExceptionFormatter(),
- FunctionFormatter(),
- HeritageClauseFormatter(),
- LibraryModuleFormatter(),
- LibraryFormatter(),
- ObjectFormatter(),
- ];
- }
+ DartFormatter()
+ : _formatters = [
+ // Formatters earlier in the list take precedence.
+ ObjectInternalsFormatter(),
+ ClassFormatter(),
+ TypeFormatter(),
+ NamedConstructorFormatter(),
+ MapFormatter(),
+ MapOverviewFormatter(),
+ IterableFormatter(),
+ IterableSpanFormatter(),
+ MapEntryFormatter(),
+ StackTraceFormatter(),
+ ErrorAndExceptionFormatter(),
+ FunctionFormatter(),
+ HeritageClauseFormatter(),
+ LibraryModuleFormatter(),
+ LibraryFormatter(),
+ ObjectFormatter(),
+ ];
- String preview(object, config) {
+ String? preview(object, config) {
try {
if (object == null ||
object is num ||
@@ -511,7 +507,7 @@
return false;
}
- List<NameValuePair> children(object, config) {
+ List<NameValuePair>? children(object, config) {
try {
if (object != null) {
for (var formatter in _formatters) {
@@ -557,7 +553,7 @@
bool hasChildren(object) => true;
- List<NameValuePair> children(object) {
+ children(object) {
var type = dart.getType(object);
var ret = LinkedHashSet<NameValuePair>();
// We use a Set rather than a List to avoid duplicates.
@@ -590,7 +586,7 @@
/// Formatter for module Dart Library objects.
class LibraryModuleFormatter implements Formatter {
- accept(object, config) => dart.getModuleName(object) != null;
+ bool accept(object, config) => dart.getModuleName(object) != null;
bool hasChildren(object) => true;
@@ -621,7 +617,7 @@
class LibraryFormatter implements Formatter {
var genericParameters = HashMap<String, String>();
- accept(object, config) => object is Library;
+ bool accept(object, config) => object is Library;
bool hasChildren(object) => true;
@@ -656,7 +652,7 @@
/// we can distinguish them based on whether they have been tagged with
/// runtime type information.
class FunctionFormatter implements Formatter {
- accept(object, config) {
+ bool accept(object, config) {
if (_typeof(object) != 'function') return false;
return dart.getReifiedType(object) != null;
}
@@ -689,7 +685,7 @@
class MapOverviewFormatter implements Formatter {
// Because this comes after MapFormatter in the list, internal
// maps will be picked up by that formatter.
- accept(object, config) => object is Map;
+ bool accept(object, config) => object is Map;
bool hasChildren(object) => true;
@@ -717,7 +713,7 @@
/// This is only used for internal maps, or when shown as [[entries]]
/// from MapOverViewFormatter.
class MapFormatter implements Formatter {
- accept(object, config) =>
+ bool accept(object, config) =>
object is InternalMap || config == JsonMLConfig.asMap;
bool hasChildren(object) => true;
@@ -778,7 +774,7 @@
}
class NamedConstructorFormatter implements Formatter {
- accept(object, config) => object is NamedConstructor;
+ bool accept(object, config) => object is NamedConstructor;
// TODO(bmilligan): Display the signature of the named constructor as the
// preview.
@@ -797,7 +793,7 @@
/// Formatter for synthetic MapEntry objects used to display contents of a Map
/// cleanly.
class MapEntryFormatter implements Formatter {
- accept(object, config) => object is MapEntry;
+ bool accept(object, config) => object is MapEntry;
String preview(object) {
MapEntry entry = object;
@@ -838,7 +834,7 @@
/// Formatter for synthetic IterableSpan objects used to display contents of
/// an Iterable cleanly.
class IterableSpanFormatter implements Formatter {
- accept(object, config) => object is IterableSpan;
+ bool accept(object, config) => object is IterableSpan;
String preview(object) {
return '[${object.start}...${object.end - 1}]';
@@ -853,7 +849,7 @@
class ErrorAndExceptionFormatter extends ObjectFormatter {
static final RegExp _pattern = RegExp(r'\d+\:\d+');
- accept(object, config) => object is Error || object is Exception;
+ bool accept(object, config) => object is Error || object is Exception;
bool hasChildren(object) => true;
@@ -866,8 +862,8 @@
l.contains(_pattern) &&
!l.contains('dart:sdk') &&
!l.contains('dart_sdk'),
- orElse: () => null);
- return line != null ? '${object} at ${line}' : '${object}';
+ orElse: () => '');
+ return line != '' ? '${object} at ${line}' : '${object}';
}
List<NameValuePair> children(object) {
@@ -889,7 +885,7 @@
}
class StackTraceFormatter implements Formatter {
- accept(object, config) => object is StackTrace;
+ bool accept(object, config) => object is StackTrace;
String preview(object) => 'StackTrace';
@@ -907,7 +903,7 @@
}
class ClassFormatter implements Formatter {
- accept(object, config) => config == JsonMLConfig.asClass;
+ bool accept(object, config) => config == JsonMLConfig.asClass;
String preview(type) {
var implements = dart.getImplements(type);
@@ -978,7 +974,7 @@
}
class TypeFormatter implements Formatter {
- accept(object, config) => object is Type;
+ bool accept(object, config) => object is Type;
String preview(object) => object.toString();
@@ -994,7 +990,7 @@
///
/// Raw JS stack traces are used if $dartStackTraceUtility has not been
/// specified.
-StackTraceMapper get stackTraceMapper {
+StackTraceMapper? get stackTraceMapper {
var _util = JS('', r'#.$dartStackTraceUtility', dart.global_);
return _util != null ? JS('!', '#.mapper', _util) : null;
}
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/foreign_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/foreign_helper.dart
index c9296cc..357047e 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/foreign_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/foreign_helper.dart
@@ -2,8 +2,6 @@
// 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.5
-
library dart._foreign_helper;
/**
@@ -108,7 +106,7 @@
*/
// Add additional optional arguments if needed. The method is treated internally
// as a variable argument method.
-T JS<T extends Object>(String typeDescription, String codeTemplate,
+T JS<T extends Object?>(String typeDescription, String codeTemplate,
[arg0,
arg1,
arg2,
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/isolate_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/isolate_helper.dart
index 44824c7..6576653 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/isolate_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/isolate_helper.dart
@@ -2,8 +2,6 @@
// 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.5
-
library dart._isolate_helper;
import 'dart:_runtime' as dart;
@@ -36,7 +34,7 @@
class TimerImpl implements Timer {
final bool _once;
- int _handle;
+ int? _handle;
int _tick = 0;
TimerImpl(int milliseconds, void callback()) : _once = true {
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
index e86378d..dcf1866 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -203,7 +203,7 @@
}
static int timerFrequency;
- static num Function() timerTicks;
+ static int Function() timerTicks;
static bool get isD8 {
return JS(
@@ -268,7 +268,7 @@
}
@notNull
- static String stringFromCharCodes(JSArray<int> charCodes) {
+ static String stringFromCharCodes(List<int> charCodes) {
for (@nullCheck var i in charCodes) {
if (i < 0) throw argumentErrorValue(i);
if (i > 0xffff) return stringFromCodePoints(charCodes);
@@ -362,7 +362,7 @@
return -JS<int>('!', r'#.getTimezoneOffset()', lazyAsJsDate(receiver));
}
- static num valueFromDecomposedDate(
+ static int valueFromDecomposedDate(
@nullCheck int years,
@nullCheck int month,
@nullCheck int day,
@@ -375,10 +375,10 @@
var jsMonth = month - 1;
num value;
if (isUtc) {
- value = JS('!', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth, day,
- hours, minutes, seconds, milliseconds);
+ value = JS<int>('!', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth,
+ day, hours, minutes, seconds, milliseconds);
} else {
- value = JS('!', r'new Date(#, #, #, #, #, #, #).valueOf()', years,
+ value = JS<int>('!', r'new Date(#, #, #, #, #, #, #).valueOf()', years,
jsMonth, day, hours, minutes, seconds, milliseconds);
}
if (value.isNaN ||
@@ -390,14 +390,14 @@
return value;
}
- static num patchUpY2K(value, years, isUtc) {
- var date = JS('', r'new Date(#)', value);
+ static int patchUpY2K(value, years, isUtc) {
+ var date = JS<int>('!', r'new Date(#)', value);
if (isUtc) {
- JS('', r'#.setUTCFullYear(#)', date, years);
+ JS<int>('!', r'#.setUTCFullYear(#)', date, years);
} else {
- JS('', r'#.setFullYear(#)', date, years);
+ JS<int>('!', r'#.setFullYear(#)', date, years);
}
- return JS('!', r'#.valueOf()', date);
+ return JS<int>('!', r'#.valueOf()', date);
}
// Lazily keep a JS Date stored in the JS object.
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_typed_data.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_typed_data.dart
index 2a7a621..e1ed809 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_typed_data.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/native_typed_data.dart
@@ -33,69 +33,69 @@
Type get runtimeType => ByteBuffer;
- Uint8List asUint8List([int offsetInBytes = 0, int length]) {
+ Uint8List asUint8List([int offsetInBytes = 0, int? length]) {
return NativeUint8List.view(this, offsetInBytes, length);
}
- Int8List asInt8List([int offsetInBytes = 0, int length]) {
+ Int8List asInt8List([int offsetInBytes = 0, int? length]) {
return NativeInt8List.view(this, offsetInBytes, length);
}
- Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int length]) {
+ Uint8ClampedList asUint8ClampedList([int offsetInBytes = 0, int? length]) {
return NativeUint8ClampedList.view(this, offsetInBytes, length);
}
- Uint16List asUint16List([int offsetInBytes = 0, int length]) {
+ Uint16List asUint16List([int offsetInBytes = 0, int? length]) {
return NativeUint16List.view(this, offsetInBytes, length);
}
- Int16List asInt16List([int offsetInBytes = 0, int length]) {
+ Int16List asInt16List([int offsetInBytes = 0, int? length]) {
return NativeInt16List.view(this, offsetInBytes, length);
}
- Uint32List asUint32List([int offsetInBytes = 0, int length]) {
+ Uint32List asUint32List([int offsetInBytes = 0, int? length]) {
return NativeUint32List.view(this, offsetInBytes, length);
}
- Int32List asInt32List([int offsetInBytes = 0, int length]) {
+ Int32List asInt32List([int offsetInBytes = 0, int? length]) {
return NativeInt32List.view(this, offsetInBytes, length);
}
- Uint64List asUint64List([int offsetInBytes = 0, int length]) {
+ Uint64List asUint64List([int offsetInBytes = 0, int? length]) {
throw UnsupportedError("Uint64List not supported by dart2js.");
}
- Int64List asInt64List([int offsetInBytes = 0, int length]) {
+ Int64List asInt64List([int offsetInBytes = 0, int? length]) {
throw UnsupportedError("Int64List not supported by dart2js.");
}
- Int32x4List asInt32x4List([int offsetInBytes = 0, int length]) {
- NativeInt32List storage =
+ Int32x4List asInt32x4List([int offsetInBytes = 0, int? length]) {
+ var storage =
this.asInt32List(offsetInBytes, length != null ? length * 4 : null);
return NativeInt32x4List._externalStorage(storage);
}
- Float32List asFloat32List([int offsetInBytes = 0, int length]) {
+ Float32List asFloat32List([int offsetInBytes = 0, int? length]) {
return NativeFloat32List.view(this, offsetInBytes, length);
}
- Float64List asFloat64List([int offsetInBytes = 0, int length]) {
+ Float64List asFloat64List([int offsetInBytes = 0, int? length]) {
return NativeFloat64List.view(this, offsetInBytes, length);
}
- Float32x4List asFloat32x4List([int offsetInBytes = 0, int length]) {
- NativeFloat32List storage =
+ Float32x4List asFloat32x4List([int offsetInBytes = 0, int? length]) {
+ var storage =
this.asFloat32List(offsetInBytes, length != null ? length * 4 : null);
return NativeFloat32x4List._externalStorage(storage);
}
- Float64x2List asFloat64x2List([int offsetInBytes = 0, int length]) {
- NativeFloat64List storage =
+ Float64x2List asFloat64x2List([int offsetInBytes = 0, int? length]) {
+ var storage =
this.asFloat64List(offsetInBytes, length != null ? length * 2 : null);
return NativeFloat64x2List._externalStorage(storage);
}
- ByteData asByteData([int offsetInBytes = 0, int length]) {
+ ByteData asByteData([int offsetInBytes = 0, int? length]) {
return NativeByteData.view(this, offsetInBytes, length);
}
}
@@ -108,7 +108,7 @@
class NativeFloat32x4List extends Object
with ListMixin<Float32x4>, FixedLengthListMixin<Float32x4>
implements Float32x4List {
- final NativeFloat32List _storage;
+ final Float32List _storage;
/**
* Creates a [Float32x4List] of the specified length (in elements),
@@ -171,10 +171,10 @@
_storage[(index * 4) + 3] = value.w;
}
- Float32x4List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
+ Float32x4List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
return NativeFloat32x4List._externalStorage(
- _storage.sublist(start * 4, end * 4));
+ _storage.sublist(start * 4, stop * 4));
}
}
@@ -249,10 +249,10 @@
_storage[(index * 4) + 3] = value.w;
}
- Int32x4List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
+ Int32x4List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
return NativeInt32x4List._externalStorage(
- _storage.sublist(start * 4, end * 4));
+ _storage.sublist(start * 4, stop * 4));
}
}
@@ -264,7 +264,7 @@
class NativeFloat64x2List extends Object
with ListMixin<Float64x2>, FixedLengthListMixin<Float64x2>
implements Float64x2List {
- final NativeFloat64List _storage;
+ final Float64List _storage;
/**
* Creates a [Float64x2List] of the specified length (in elements),
@@ -321,10 +321,10 @@
_storage[(index * 2) + 1] = value.y;
}
- Float64x2List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
+ Float64x2List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
return NativeFloat64x2List._externalStorage(
- _storage.sublist(start * 2, end * 2));
+ _storage.sublist(start * 2, stop * 2));
}
}
@@ -393,7 +393,7 @@
if (offsetInBytes is! int) {
throw ArgumentError('Invalid view offsetInBytes $offsetInBytes');
}
- if (length != null && length is! int) {
+ if (length is! int?) {
throw ArgumentError('Invalid view length $length');
}
}
@@ -430,7 +430,7 @@
* the length of [buffer].
*/
factory NativeByteData.view(
- ByteBuffer buffer, int offsetInBytes, int length) {
+ ByteBuffer buffer, int offsetInBytes, int? length) {
_checkViewArguments(buffer, offsetInBytes, length);
return length == null
? _create2(buffer, offsetInBytes)
@@ -454,7 +454,7 @@
@JSName('getFloat32')
@Returns('double')
- double _getFloat32(int byteOffset, [bool littleEndian]) native;
+ double _getFloat32(int byteOffset, [bool? littleEndian]) native;
/**
* Returns the floating point number represented by the eight bytes at
@@ -469,7 +469,7 @@
@JSName('getFloat64')
@Returns('double')
- double _getFloat64(int byteOffset, [bool littleEndian]) native;
+ double _getFloat64(int byteOffset, [bool? littleEndian]) native;
/**
* Returns the (possibly negative) integer represented by the two bytes at
@@ -486,7 +486,7 @@
@JSName('getInt16')
@Returns('int')
- int _getInt16(int byteOffset, [bool littleEndian]) native;
+ int _getInt16(int byteOffset, [bool? littleEndian]) native;
/**
* Returns the (possibly negative) integer represented by the four bytes at
@@ -503,7 +503,7 @@
@JSName('getInt32')
@Returns('int')
- int _getInt32(int byteOffset, [bool littleEndian]) native;
+ int _getInt32(int byteOffset, [bool? littleEndian]) native;
/**
* Returns the (possibly negative) integer represented by the eight bytes at
@@ -543,7 +543,7 @@
@JSName('getUint16')
@Returns('int')
- int _getUint16(int byteOffset, [bool littleEndian]) native;
+ int _getUint16(int byteOffset, [bool? littleEndian]) native;
/**
* Returns the positive integer represented by the four bytes starting
@@ -559,7 +559,7 @@
@JSName('getUint32')
@Returns('int')
- int _getUint32(int byteOffset, [bool littleEndian]) native;
+ int _getUint32(int byteOffset, [bool? littleEndian]) native;
/**
* Returns the positive integer represented by the eight bytes starting
@@ -605,7 +605,7 @@
_setFloat32(byteOffset, value, Endian.little == endian);
@JSName('setFloat32')
- void _setFloat32(int byteOffset, num value, [bool littleEndian]) native;
+ void _setFloat32(int byteOffset, num value, [bool? littleEndian]) native;
/**
* Sets the eight bytes starting at the specified [byteOffset] in this
@@ -619,7 +619,7 @@
_setFloat64(byteOffset, value, Endian.little == endian);
@JSName('setFloat64')
- void _setFloat64(int byteOffset, num value, [bool littleEndian]) native;
+ void _setFloat64(int byteOffset, num value, [bool? littleEndian]) native;
/**
* Sets the two bytes starting at the specified [byteOffset] in this
@@ -634,7 +634,7 @@
_setInt16(byteOffset, value, Endian.little == endian);
@JSName('setInt16')
- void _setInt16(int byteOffset, int value, [bool littleEndian]) native;
+ void _setInt16(int byteOffset, int value, [bool? littleEndian]) native;
/**
* Sets the four bytes starting at the specified [byteOffset] in this
@@ -649,7 +649,7 @@
_setInt32(byteOffset, value, Endian.little == endian);
@JSName('setInt32')
- void _setInt32(int byteOffset, int value, [bool littleEndian]) native;
+ void _setInt32(int byteOffset, int value, [bool? littleEndian]) native;
/**
* Sets the eight bytes starting at the specified [byteOffset] in this
@@ -688,7 +688,7 @@
_setUint16(byteOffset, value, Endian.little == endian);
@JSName('setUint16')
- void _setUint16(int byteOffset, int value, [bool littleEndian]) native;
+ void _setUint16(int byteOffset, int value, [bool? littleEndian]) native;
/**
* Sets the four bytes starting at the specified [byteOffset] in this object
@@ -703,7 +703,7 @@
_setUint32(byteOffset, value, Endian.little == endian);
@JSName('setUint32')
- void _setUint32(int byteOffset, int value, [bool littleEndian]) native;
+ void _setUint32(int byteOffset, int value, [bool? littleEndian]) native;
/**
* Sets the eight bytes starting at the specified [byteOffset] in this object
@@ -822,7 +822,7 @@
_create1(_ensureNativeList(elements));
factory NativeFloat32List.view(
- ByteBuffer buffer, int offsetInBytes, int length) {
+ ByteBuffer buffer, int offsetInBytes, int? length) {
_checkViewArguments(buffer, offsetInBytes, length);
return length == null
? _create2(buffer, offsetInBytes)
@@ -831,10 +831,10 @@
Type get runtimeType => Float32List;
- Float32List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
+ Float32List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
var source =
- JS<NativeFloat32List>('!', '#.subarray(#, #)', this, start, end);
+ JS<NativeFloat32List>('!', '#.subarray(#, #)', this, start, stop);
return _create1(source);
}
@@ -857,7 +857,7 @@
_create1(_ensureNativeList(elements));
factory NativeFloat64List.view(
- ByteBuffer buffer, int offsetInBytes, int length) {
+ ByteBuffer buffer, int offsetInBytes, int? length) {
_checkViewArguments(buffer, offsetInBytes, length);
return length == null
? _create2(buffer, offsetInBytes)
@@ -866,9 +866,9 @@
Type get runtimeType => Float64List;
- Float64List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
- var source = JS('NativeFloat64List', '#.subarray(#, #)', this, start, end);
+ Float64List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
+ var source = JS('NativeFloat64List', '#.subarray(#, #)', this, start, stop);
return _create1(source);
}
@@ -890,7 +890,7 @@
_create1(_ensureNativeList(elements));
factory NativeInt16List.view(
- NativeByteBuffer buffer, int offsetInBytes, int length) {
+ NativeByteBuffer buffer, int offsetInBytes, int? length) {
_checkViewArguments(buffer, offsetInBytes, length);
return length == null
? _create2(buffer, offsetInBytes)
@@ -904,9 +904,9 @@
return JS<int>('!', '#[#]', this, index);
}
- Int16List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
- var source = JS('NativeInt16List', '#.subarray(#, #)', this, start, end);
+ Int16List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
+ var source = JS('NativeInt16List', '#.subarray(#, #)', this, start, stop);
return _create1(source);
}
@@ -928,7 +928,7 @@
_create1(_ensureNativeList(elements));
factory NativeInt32List.view(
- ByteBuffer buffer, int offsetInBytes, int length) {
+ ByteBuffer buffer, int offsetInBytes, int? length) {
_checkViewArguments(buffer, offsetInBytes, length);
return length == null
? _create2(buffer, offsetInBytes)
@@ -942,9 +942,10 @@
return JS<int>('!', '#[#]', this, index);
}
- Int32List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
- var source = JS<NativeInt32List>('!', '#.subarray(#, #)', this, start, end);
+ Int32List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
+ var source =
+ JS<NativeInt32List>('!', '#.subarray(#, #)', this, start, stop);
return _create1(source);
}
@@ -966,7 +967,7 @@
_create1(_ensureNativeList(elements));
factory NativeInt8List.view(
- ByteBuffer buffer, int offsetInBytes, int length) {
+ ByteBuffer buffer, int offsetInBytes, int? length) {
_checkViewArguments(buffer, offsetInBytes, length);
return length == null
? _create2(buffer, offsetInBytes)
@@ -980,9 +981,9 @@
return JS<int>('!', '#[#]', this, index);
}
- Int8List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
- var source = JS<NativeInt8List>('!', '#.subarray(#, #)', this, start, end);
+ Int8List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
+ var source = JS<NativeInt8List>('!', '#.subarray(#, #)', this, start, stop);
return _create1(source);
}
@@ -992,7 +993,7 @@
static NativeInt8List _create2(arg1, arg2) =>
JS<NativeInt8List>('!', 'new Int8Array(#, #)', arg1, arg2);
- static Int8List _create3(arg1, arg2, arg3) =>
+ static NativeInt8List _create3(arg1, arg2, arg3) =>
JS<NativeInt8List>('!', 'new Int8Array(#, #, #)', arg1, arg2, arg3);
}
@@ -1004,7 +1005,7 @@
_create1(_ensureNativeList(list));
factory NativeUint16List.view(
- ByteBuffer buffer, int offsetInBytes, int length) {
+ ByteBuffer buffer, int offsetInBytes, int? length) {
_checkViewArguments(buffer, offsetInBytes, length);
return length == null
? _create2(buffer, offsetInBytes)
@@ -1018,10 +1019,10 @@
return JS<int>('!', '#[#]', this, index);
}
- Uint16List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
+ Uint16List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
var source =
- JS<NativeUint16List>('!', '#.subarray(#, #)', this, start, end);
+ JS<NativeUint16List>('!', '#.subarray(#, #)', this, start, stop);
return _create1(source);
}
@@ -1043,7 +1044,7 @@
_create1(_ensureNativeList(elements));
factory NativeUint32List.view(
- ByteBuffer buffer, int offsetInBytes, int length) {
+ ByteBuffer buffer, int offsetInBytes, int? length) {
_checkViewArguments(buffer, offsetInBytes, length);
return length == null
? _create2(buffer, offsetInBytes)
@@ -1057,10 +1058,10 @@
return JS<int>('!', '#[#]', this, index);
}
- Uint32List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
+ Uint32List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
var source =
- JS<NativeUint32List>('!', '#.subarray(#, #)', this, start, end);
+ JS<NativeUint32List>('!', '#.subarray(#, #)', this, start, stop);
return _create1(source);
}
@@ -1083,7 +1084,7 @@
_create1(_ensureNativeList(elements));
factory NativeUint8ClampedList.view(
- ByteBuffer buffer, int offsetInBytes, int length) {
+ ByteBuffer buffer, int offsetInBytes, int? length) {
_checkViewArguments(buffer, offsetInBytes, length);
return length == null
? _create2(buffer, offsetInBytes)
@@ -1099,10 +1100,10 @@
return JS<int>('!', '#[#]', this, index);
}
- Uint8ClampedList sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
+ Uint8ClampedList sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
var source =
- JS<NativeUint8ClampedList>('!', '#.subarray(#, #)', this, start, end);
+ JS<NativeUint8ClampedList>('!', '#.subarray(#, #)', this, start, stop);
return _create1(source);
}
@@ -1133,7 +1134,7 @@
_create1(_ensureNativeList(elements));
factory NativeUint8List.view(
- ByteBuffer buffer, int offsetInBytes, int length) {
+ ByteBuffer buffer, int offsetInBytes, int? length) {
_checkViewArguments(buffer, offsetInBytes, length);
return length == null
? _create2(buffer, offsetInBytes)
@@ -1149,9 +1150,10 @@
return JS<int>('!', '#[#]', this, index);
}
- Uint8List sublist(int start, [int end]) {
- end = _checkValidRange(start, end, this.length);
- var source = JS<NativeUint8List>('!', '#.subarray(#, #)', this, start, end);
+ Uint8List sublist(int start, [int? end]) {
+ var stop = _checkValidRange(start, end, this.length);
+ var source =
+ JS<NativeUint8List>('!', '#.subarray(#, #)', this, start, stop);
return _create1(source);
}
@@ -1541,7 +1543,7 @@
floatList[1] = f.y;
floatList[2] = f.z;
floatList[3] = f.w;
- NativeInt32List view = floatList.buffer.asInt32List();
+ Int32List view = floatList.buffer.asInt32List();
return NativeInt32x4._truncated(view[0], view[1], view[2], view[3]);
}
@@ -1759,7 +1761,7 @@
final double y;
static NativeFloat64List _list = NativeFloat64List(2);
- static NativeUint32List _uint32View = _list.buffer.asUint32List();
+ static Uint32List _uint32View = _list.buffer.asUint32List();
NativeFloat64x2(this.x, this.y) {
if (x is! num) throw ArgumentError(x);
@@ -1890,7 +1892,7 @@
///
/// Returns the actual value of `end`, which is `length` if `end` is `null`, and
/// the original value of `end` otherwise.
-int _checkValidRange(int start, int end, int length) {
+int _checkValidRange(int start, int? end, int length) {
if (_isInvalidArrayIndex(start) || // Ensures start is non-negative int.
((end == null)
? start > length
diff --git a/sdk_nnbd/lib/_internal/js_dev_runtime/private/profile.dart b/sdk_nnbd/lib/_internal/js_dev_runtime/private/profile.dart
index 8f3410b..d46f7f7 100644
--- a/sdk_nnbd/lib/_internal/js_dev_runtime/private/profile.dart
+++ b/sdk_nnbd/lib/_internal/js_dev_runtime/private/profile.dart
@@ -2,8 +2,6 @@
// 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.5
-
/// This file supports profiling dynamic calls.
part of dart._debugger;
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
index e31c549..ce924cd 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/core_patch.dart
@@ -857,6 +857,9 @@
int _max(int a, int b) => a > b ? a : b;
int _min(int a, int b) => a < b ? a : b;
+/// Empty list used as an initializer for local variables in the `_BigIntImpl`.
+final _dummyList = new Uint16List(0);
+
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
@@ -1455,8 +1458,7 @@
///
/// Returns 0 if abs(this) == abs(other); a positive number if
/// abs(this) > abs(other); and a negative number if abs(this) < abs(other).
- int _absCompare(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ int _absCompare(_BigIntImpl other) {
return _compareDigits(_digits, _used, other._digits, other._used);
}
@@ -1464,8 +1466,7 @@
///
/// Returns a negative number if `this` is less than `other`, zero if they are
/// equal, and a positive number if `this` is greater than `other`.
- int compareTo(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ int compareTo(covariant _BigIntImpl other) {
if (_isNegative == other._isNegative) {
var result = _absCompare(other);
// Use 0 - result to avoid negative zero in JavaScript.
@@ -1607,7 +1608,8 @@
var digits = _digits;
var otherDigits = other._digits;
var resultDigits = new Uint16List(resultUsed);
- var l, m;
+ _BigIntImpl l;
+ int m;
if (used < otherUsed) {
l = other;
m = used;
@@ -1633,7 +1635,8 @@
var digits = _digits;
var otherDigits = other._digits;
var resultDigits = new Uint16List(resultUsed);
- var l, m;
+ _BigIntImpl l;
+ int m;
if (used < otherUsed) {
l = other;
m = used;
@@ -1659,8 +1662,7 @@
///
/// Of both operands are negative, the result is negative, otherwise
/// the result is non-negative.
- _BigIntImpl operator &(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator &(covariant _BigIntImpl other) {
if (_isZero || other._isZero) return zero;
if (_isNegative == other._isNegative) {
if (_isNegative) {
@@ -1675,7 +1677,7 @@
return _absAndSetSign(other, false);
}
// _isNegative != other._isNegative
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1697,8 +1699,7 @@
///
/// If both operands are non-negative, the result is non-negative,
/// otherwise the result us negative.
- _BigIntImpl operator |(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator |(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
if (_isNegative == other._isNegative) {
@@ -1714,7 +1715,7 @@
return _absOrSetSign(other, false);
}
// _neg != a._neg
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1737,8 +1738,7 @@
///
/// If the operands have the same sign, the result is non-negative,
/// otherwise the result is negative.
- _BigIntImpl operator ^(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator ^(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
if (_isNegative == other._isNegative) {
@@ -1751,7 +1751,7 @@
return _absXorSetSign(other, false);
}
// _isNegative != a._isNegative
- var p, n;
+ _BigIntImpl p, n;
if (_isNegative) {
p = other;
n = this;
@@ -1784,8 +1784,7 @@
}
/// Addition operator.
- _BigIntImpl operator +(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator +(covariant _BigIntImpl other) {
if (_isZero) return other;
if (other._isZero) return this;
var isNegative = _isNegative;
@@ -1803,8 +1802,7 @@
}
/// Subtraction operator.
- _BigIntImpl operator -(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator -(covariant _BigIntImpl other) {
if (_isZero) return -other;
if (other._isZero) return this;
var isNegative = _isNegative;
@@ -1856,8 +1854,7 @@
}
/// Multiplication operator.
- _BigIntImpl operator *(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator *(covariant _BigIntImpl other) {
var used = _used;
var otherUsed = other._used;
if (used == 0 || otherUsed == 0) {
@@ -1905,8 +1902,7 @@
}
/// Returns `trunc(this / other)`, with `other != 0`.
- _BigIntImpl _div(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl _div(_BigIntImpl other) {
assert(other._used > 0);
if (_used < other._used) {
return zero;
@@ -1925,8 +1921,7 @@
}
/// Returns `this - other * trunc(this / other)`, with `other != 0`.
- _BigIntImpl _rem(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl _rem(_BigIntImpl other) {
assert(other._used > 0);
if (_used < other._used) {
return this;
@@ -2120,8 +2115,7 @@
/// (-seven).remainder(three); // => -1
/// seven.remainder(-three); // => 1
/// ```
- _BigIntImpl operator ~/(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator ~/(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2134,8 +2128,7 @@
/// `this == (this ~/ other) * other + r`.
/// As a consequence the remainder `r` has the same sign as the divider
/// `this`.
- _BigIntImpl remainder(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl remainder(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2146,16 +2139,16 @@
double operator /(BigInt other) => this.toDouble() / other.toDouble();
/// Relational less than operator.
- bool operator <(BigInt other) => compareTo(other) < 0;
+ bool operator <(covariant _BigIntImpl other) => compareTo(other) < 0;
/// Relational less than or equal operator.
- bool operator <=(BigInt other) => compareTo(other) <= 0;
+ bool operator <=(covariant _BigIntImpl other) => compareTo(other) <= 0;
/// Relational greater than operator.
- bool operator >(BigInt other) => compareTo(other) > 0;
+ bool operator >(covariant _BigIntImpl other) => compareTo(other) > 0;
/// Relational greater than or equal operator.
- bool operator >=(BigInt other) => compareTo(other) >= 0;
+ bool operator >=(covariant _BigIntImpl other) => compareTo(other) >= 0;
/// Euclidean modulo operator.
///
@@ -2166,8 +2159,7 @@
/// The sign of the returned value `r` is always positive.
///
/// See [remainder] for the remainder of the truncating division.
- _BigIntImpl operator %(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl operator %(covariant _BigIntImpl other) {
if (other._used == 0) {
throw const IntegerDivisionByZeroException();
}
@@ -2226,9 +2218,8 @@
///
/// The [exponent] must be non-negative and [modulus] must be
/// positive.
- _BigIntImpl modPow(BigInt bigExponent, BigInt bigModulus) {
- _BigIntImpl exponent = bigExponent;
- _BigIntImpl modulus = bigModulus;
+ _BigIntImpl modPow(
+ covariant _BigIntImpl exponent, covariant _BigIntImpl modulus) {
if (exponent._isNegative) {
throw new ArgumentError("exponent must be positive: $exponent");
}
@@ -2252,7 +2243,7 @@
resultDigits[j] = gDigits[j];
}
var resultUsed = gUsed;
- var result2Used;
+ int result2Used;
for (int i = exponentBitlen - 2; i >= 0; i--) {
result2Used = z.sqr(resultDigits, resultUsed, result2Digits);
if (!(exponent & (one << i))._isZero) {
@@ -2327,19 +2318,19 @@
// Variables a, b, c, and d require one more digit.
final abcdUsed = maxUsed + 1;
final abcdLen = abcdUsed + 2; // +2 to satisfy _absAdd.
- var aDigits, bDigits, cDigits, dDigits;
- bool aIsNegative, bIsNegative, cIsNegative, dIsNegative;
+ var aDigits = _dummyList;
+ var aIsNegative = false;
+ var cDigits = _dummyList;
+ var cIsNegative = false;
if (ac) {
aDigits = new Uint16List(abcdLen);
- aIsNegative = false;
aDigits[0] = 1;
cDigits = new Uint16List(abcdLen);
- cIsNegative = false;
}
- bDigits = new Uint16List(abcdLen);
- bIsNegative = false;
- dDigits = new Uint16List(abcdLen);
- dIsNegative = false;
+ var bDigits = new Uint16List(abcdLen);
+ var bIsNegative = false;
+ var dDigits = new Uint16List(abcdLen);
+ var dIsNegative = false;
dDigits[0] = 1;
while (true) {
@@ -2530,8 +2521,7 @@
///
/// It is an error if no modular inverse exists.
// Returns 1/this % modulus, with modulus > 0.
- _BigIntImpl modInverse(BigInt bigInt) {
- _BigIntImpl modulus = bigInt;
+ _BigIntImpl modInverse(covariant _BigIntImpl modulus) {
if (modulus <= zero) {
throw new ArgumentError("Modulus must be strictly positive: $modulus");
}
@@ -2554,8 +2544,7 @@
/// For any integer `x`, `x.gcd(x)` is `x.abs()`.
///
/// If both `this` and `other` is zero, the result is also zero.
- _BigIntImpl gcd(BigInt bigInt) {
- _BigIntImpl other = bigInt;
+ _BigIntImpl gcd(covariant _BigIntImpl other) {
if (_isZero) return other.abs();
if (other._isZero) return this.abs();
return _binaryGcd(this, other, false);
@@ -2865,8 +2854,8 @@
_modulus._digits[_modulus._used - 1].bitLength);
int convert(_BigIntImpl x, Uint16List resultDigits) {
- var digits;
- var used;
+ Uint16List digits;
+ int used;
if (x._isNegative || x._absCompare(_modulus) >= 0) {
var remainder = x._rem(_modulus);
if (x._isNegative && remainder._used > 0) {
diff --git a/sdk_nnbd/lib/async/async.dart b/sdk_nnbd/lib/async/async.dart
index 75d1c60..616375c 100644
--- a/sdk_nnbd/lib/async/async.dart
+++ b/sdk_nnbd/lib/async/async.dart
@@ -87,7 +87,7 @@
* [asynchronous-programming]: https://www.dartlang.org/docs/dart-up-and-running/ch03.html#dartasync---asynchronous-programming
* [futures-tutorial]: https://www.dartlang.org/docs/tutorials/futures/
* [futures-error-handling]: https://www.dartlang.org/articles/futures-and-error-handling/
- * [test-readme]: https://pub.dartlang.org/packages/test
+ * [test-readme]: https://pub.dev/packages/test
*
* {@category Core}
*/
diff --git a/sdk_nnbd/lib/async/schedule_microtask.dart b/sdk_nnbd/lib/async/schedule_microtask.dart
index 95fca9e..940989c 100644
--- a/sdk_nnbd/lib/async/schedule_microtask.dart
+++ b/sdk_nnbd/lib/async/schedule_microtask.dart
@@ -132,7 +132,7 @@
* Learn how Dart handles the event queue and microtask queue, so you can write
* better asynchronous code with fewer surprises.
*/
-void scheduleMicrotask(void callback()) {
+void scheduleMicrotask(void Function() callback) {
_Zone currentZone = Zone._current;
if (identical(_rootZone, currentZone)) {
// No need to bind the callback. We know that the root's scheduleMicrotask
@@ -152,5 +152,5 @@
class _AsyncRun {
/** Schedule the given callback before any other event in the event-loop. */
- external static void _scheduleImmediate(void callback());
+ external static void _scheduleImmediate(void Function() callback);
}
diff --git a/sdk_nnbd/lib/async/stream_impl.dart b/sdk_nnbd/lib/async/stream_impl.dart
index c5f331c..5011a82 100644
--- a/sdk_nnbd/lib/async/stream_impl.dart
+++ b/sdk_nnbd/lib/async/stream_impl.dart
@@ -426,7 +426,7 @@
* during the call, and it checks for state changes after the call
* that should cause further callbacks.
*/
- void _guardCallback(void callback()) {
+ void _guardCallback(void Function() callback) {
assert(!_inCallback);
bool wasInputPaused = _isInputPaused;
_state |= _STATE_IN_CALLBACK;
diff --git a/sdk_nnbd/lib/async/timer.dart b/sdk_nnbd/lib/async/timer.dart
index 97560a9..e0ef447 100644
--- a/sdk_nnbd/lib/async/timer.dart
+++ b/sdk_nnbd/lib/async/timer.dart
@@ -42,7 +42,7 @@
* The [callback] function is invoked after the given [duration].
*
*/
- factory Timer(Duration duration, void callback()) {
+ factory Timer(Duration duration, void Function() callback) {
if (Zone.current == Zone.root) {
// No need to bind the callback. We know that the root's timer will
// be invoked in the root zone.
@@ -85,7 +85,7 @@
*
* This function is equivalent to `new Timer(Duration.zero, callback)`.
*/
- static void run(void callback()) {
+ static void run(void Function() callback) {
new Timer(Duration.zero, callback);
}
@@ -123,7 +123,8 @@
*/
bool get isActive;
- external static Timer _createTimer(Duration duration, void callback());
+ external static Timer _createTimer(
+ Duration duration, void Function() callback);
external static Timer _createPeriodicTimer(
Duration duration, void callback(Timer timer));
}
diff --git a/sdk_nnbd/lib/async/zone.dart b/sdk_nnbd/lib/async/zone.dart
index 4e956a2..31644f2 100644
--- a/sdk_nnbd/lib/async/zone.dart
+++ b/sdk_nnbd/lib/async/zone.dart
@@ -546,7 +546,7 @@
* return () => this.runGuarded(registered);
*
*/
- void Function() bindCallbackGuarded(void callback());
+ void Function() bindCallbackGuarded(void Function() callback);
/**
* Registers the provided [callback] and returns a function that will
@@ -615,12 +615,12 @@
* Custom zones may intercept this operation (for example to wrap the given
* [callback]).
*/
- void scheduleMicrotask(void callback());
+ void scheduleMicrotask(void Function() callback);
/**
* Creates a Timer where the callback is executed in this zone.
*/
- Timer createTimer(Duration duration, void callback());
+ Timer createTimer(Duration duration, void Function() callback);
/**
* Creates a periodic Timer where the callback is executed in this zone.
@@ -1202,7 +1202,7 @@
}
Timer _rootCreateTimer(Zone self, ZoneDelegate parent, Zone zone,
- Duration duration, void callback()) {
+ Duration duration, void Function() callback) {
if (!identical(_rootZone, zone)) {
callback = zone.bindCallback(callback);
}
diff --git a/sdk_nnbd/lib/convert/json.dart b/sdk_nnbd/lib/convert/json.dart
index 1fafde7..7e08ccb 100644
--- a/sdk_nnbd/lib/convert/json.dart
+++ b/sdk_nnbd/lib/convert/json.dart
@@ -288,8 +288,6 @@
if (other is Utf8Encoder) {
// The instance check guarantees that `T` is (a subtype of) List<int>,
// but the static type system doesn't know that, and so we cast.
- // Cast through dynamic to keep the cast implicit for builds using
- // unchecked implicit casts.
return JsonUtf8Encoder(indent, _toEncodable) as Converter<Object?, T>;
}
return super.fuse<T>(other);
diff --git a/sdk_nnbd/lib/convert/string_conversion.dart b/sdk_nnbd/lib/convert/string_conversion.dart
index ea33dc5..1d5f038 100644
--- a/sdk_nnbd/lib/convert/string_conversion.dart
+++ b/sdk_nnbd/lib/convert/string_conversion.dart
@@ -79,11 +79,11 @@
_sink.writeCharCode(charCode);
}
- void write(Object o) {
+ void write(Object? o) {
_sink.write(o);
}
- void writeln([Object o = ""]) {
+ void writeln([Object? o = ""]) {
_sink.writeln(o);
}
diff --git a/sdk_nnbd/lib/core/date_time.dart b/sdk_nnbd/lib/core/date_time.dart
index 4f5f299..6788d1d 100644
--- a/sdk_nnbd/lib/core/date_time.dart
+++ b/sdk_nnbd/lib/core/date_time.dart
@@ -117,7 +117,7 @@
*
* The DateTime class does not provide internationalization.
* To internationalize your code, use
- * the [intl](https://pub.dartlang.org/packages/intl) package.
+ * the [intl](https://pub.dev/packages/intl) package.
*
*/
class DateTime implements Comparable<DateTime> {
@@ -238,7 +238,8 @@
* The time part is a two digit hour,
* then optionally a two digit minutes value,
* then optionally a two digit seconds value, and
- * then optionally a '.' or ',' followed by a one-to-six digit second fraction.
+ * then optionally a '.' or ',' followed by at least a one digit
+ * second fraction.
* The minutes and seconds may be separated from the previous parts by a
* ':'.
* Examples: "12", "12:30:24.124", "12:30:24,124", "123010.50".
@@ -261,8 +262,8 @@
* Examples of accepted strings:
*
* * `"2012-02-27 13:27:00"`
- * * `"2012-02-27 13:27:00.123456z"`
- * * `"2012-02-27 13:27:00,123456z"`
+ * * `"2012-02-27 13:27:00.123456789z"`
+ * * `"2012-02-27 13:27:00,123456789z"`
* * `"20120227 13:27:00"`
* * `"20120227T132700"`
* * `"20120227"`
@@ -283,14 +284,13 @@
return int.parse(matched);
}
- // Parses fractional second digits of '.(\d{1,6})' into the combined
- // microseconds.
+ // Parses fractional second digits of '.(\d+)' into the combined
+ // microseconds. We only use the first 6 digits because of DateTime
+ // precision of 999 milliseconds and 999 microseconds.
int parseMilliAndMicroseconds(String? matched) {
if (matched == null) return 0;
int length = matched.length;
assert(length >= 1);
- assert(length <= 6);
-
int result = 0;
for (int i = 0; i < 6; i++) {
result *= 10;
@@ -557,7 +557,7 @@
* The returned string is constructed for the time zone of this instance.
* The `toString()` method provides a simply formatted string.
* It does not support internationalized strings.
- * Use the [intl](https://pub.dartlang.org/packages/intl) package
+ * Use the [intl](https://pub.dev/packages/intl) package
* at the pub shared packages repo.
*
* The resulting string can be parsed back using [parse].
@@ -857,7 +857,7 @@
* time_opt ::= <empty> | (' ' | 'T') hour minutes_opt
* minutes_opt ::= <empty> | colon_opt digit{2} seconds_opt
* seconds_opt ::= <empty> | colon_opt digit{2} millis_opt
- * micros_opt ::= <empty> | ('.' | ',') digit{1,6}
+ * micros_opt ::= <empty> | ('.' | ',') digit+
* timezone_opt ::= <empty> | space_opt timezone
* space_opt :: ' ' | <empty>
* timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt
@@ -865,6 +865,6 @@
*/
static final RegExp _parseFormat = RegExp(
r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // Day part.
- r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,6}))?)?)?' // Time part.
+ r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d+))?)?)?' // Time part.
r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // Timezone part.
}
diff --git a/sdk_nnbd/lib/core/num.dart b/sdk_nnbd/lib/core/num.dart
index 7b45da6..f63dc68 100644
--- a/sdk_nnbd/lib/core/num.dart
+++ b/sdk_nnbd/lib/core/num.dart
@@ -42,7 +42,7 @@
* Use [compareTo] for a comparison that distinguishes zero and minus zero,
* and that considers NaN values as equal.
*/
- bool operator ==(Object? other);
+ bool operator ==(Object other);
/**
* Returns a hash code for a numerical value.
diff --git a/sdk_nnbd/lib/core/print.dart b/sdk_nnbd/lib/core/print.dart
index c45336c..d88ea7f 100644
--- a/sdk_nnbd/lib/core/print.dart
+++ b/sdk_nnbd/lib/core/print.dart
@@ -7,9 +7,10 @@
/// Prints a string representation of the object to the console.
void print(Object? object) {
String line = object.toString();
- if (printToZone == null) {
+ var toZone = printToZone;
+ if (toZone == null) {
printToConsole(line);
} else {
- printToZone(line);
+ toZone(line);
}
}
diff --git a/sdk_nnbd/lib/internal/internal.dart b/sdk_nnbd/lib/internal/internal.dart
index 11ee996..1a92f98 100644
--- a/sdk_nnbd/lib/internal/internal.dart
+++ b/sdk_nnbd/lib/internal/internal.dart
@@ -16,7 +16,7 @@
Zone;
import 'dart:convert' show Converter;
import 'dart:core' hide Symbol;
-import 'dart:core' as core;
+import 'dart:core' as core show Symbol;
import 'dart:math' show Random;
part 'async_cast.dart';
diff --git a/sdk_nnbd/lib/internal/iterable.dart b/sdk_nnbd/lib/internal/iterable.dart
index 3865626..394dcaa 100644
--- a/sdk_nnbd/lib/internal/iterable.dart
+++ b/sdk_nnbd/lib/internal/iterable.dart
@@ -768,7 +768,7 @@
}
class FollowedByIterable<E> extends Iterable<E> {
- final EfficientLengthIterable<E> _first;
+ final Iterable<E> _first;
final Iterable<E> _second;
FollowedByIterable(this._first, this._second);
@@ -854,13 +854,13 @@
}
class WhereTypeIterable<T> extends Iterable<T> {
- final Iterable<Object> _source;
+ final Iterable<Object?> _source;
WhereTypeIterable(this._source);
Iterator<T> get iterator => new WhereTypeIterator<T>(_source.iterator);
}
class WhereTypeIterator<T> implements Iterator<T> {
- final Iterator<Object> _source;
+ final Iterator<Object?> _source;
WhereTypeIterator(this._source);
bool moveNext() {
while (_source.moveNext()) {
diff --git a/sdk_nnbd/lib/io/io.dart b/sdk_nnbd/lib/io/io.dart
index 64a1f78..2207d9b 100644
--- a/sdk_nnbd/lib/io/io.dart
+++ b/sdk_nnbd/lib/io/io.dart
@@ -67,7 +67,7 @@
* The [HttpServer] class provides the basic functionality for
* implementing an HTTP server.
* For some higher-level building-blocks, we recommend that you try
- * the [shelf](https://pub.dartlang.org/packages/shelf)
+ * the [shelf](https://pub.dev/packages/shelf)
* pub package, which contains
* a set of high-level classes that, together with the [HttpServer] class
* in this library, make it easier to implement HTTP servers.
diff --git a/sdk_nnbd/lib/libraries.json b/sdk_nnbd/lib/libraries.json
index 95aa4205..49d5373 100644
--- a/sdk_nnbd/lib/libraries.json
+++ b/sdk_nnbd/lib/libraries.json
@@ -4,151 +4,151 @@
"vm": {
"libraries": {
"_builtin": {
- "uri": "_internal/vm/bin/builtin.dart"
+ "uri": "../../sdk/lib/_internal/vm/bin/builtin.dart"
},
"cli": {
"patches": [
- "_internal/vm/bin/cli_patch.dart"
+ "../../sdk/lib/_internal/vm/bin/cli_patch.dart"
],
- "uri": "cli/cli.dart"
+ "uri": "../../sdk/lib/cli/cli.dart"
},
"core": {
"patches": [
- "_internal/vm/lib/core_patch.dart",
- "_internal/vm/lib/array.dart",
- "_internal/vm/lib/array_patch.dart",
- "_internal/vm/lib/bigint_patch.dart",
- "_internal/vm/lib/bool_patch.dart",
- "_internal/vm/lib/date_patch.dart",
- "_internal/vm/lib/double.dart",
- "_internal/vm/lib/double_patch.dart",
- "_internal/vm/lib/errors_patch.dart",
- "_internal/vm/lib/expando_patch.dart",
- "_internal/vm/lib/function.dart",
- "_internal/vm/lib/function_patch.dart",
- "_internal/vm/lib/growable_array.dart",
- "_internal/vm/lib/identical_patch.dart",
- "_internal/vm/lib/immutable_map.dart",
- "_internal/vm/lib/integers.dart",
- "_internal/vm/lib/integers_patch.dart",
- "_internal/vm/lib/invocation_mirror_patch.dart",
- "_internal/vm/lib/lib_prefix.dart",
- "_internal/vm/lib/map_patch.dart",
- "_internal/vm/lib/null_patch.dart",
- "_internal/vm/lib/object_patch.dart",
- "_internal/vm/lib/regexp_patch.dart",
- "_internal/vm/lib/stacktrace.dart",
- "_internal/vm/lib/stopwatch_patch.dart",
- "_internal/vm/lib/string_buffer_patch.dart",
- "_internal/vm/lib/string_patch.dart",
- "_internal/vm/lib/type_patch.dart",
- "_internal/vm/lib/uri_patch.dart",
- "_internal/vm/lib/weak_property.dart"
+ "../../sdk/lib/_internal/vm/lib/core_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/array.dart",
+ "../../sdk/lib/_internal/vm/lib/array_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/bigint_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/bool_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/date_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/double.dart",
+ "../../sdk/lib/_internal/vm/lib/double_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/errors_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/expando_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/function.dart",
+ "../../sdk/lib/_internal/vm/lib/function_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/growable_array.dart",
+ "../../sdk/lib/_internal/vm/lib/identical_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/immutable_map.dart",
+ "../../sdk/lib/_internal/vm/lib/integers.dart",
+ "../../sdk/lib/_internal/vm/lib/integers_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/lib_prefix.dart",
+ "../../sdk/lib/_internal/vm/lib/map_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/null_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/object_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/regexp_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/stacktrace.dart",
+ "../../sdk/lib/_internal/vm/lib/stopwatch_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/string_buffer_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/string_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/type_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/uri_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/weak_property.dart"
],
- "uri": "core/core.dart"
+ "uri": "../../sdk/lib/core/core.dart"
},
"async": {
"patches": [
- "_internal/vm/lib/async_patch.dart",
- "_internal/vm/lib/deferred_load_patch.dart",
- "_internal/vm/lib/schedule_microtask_patch.dart",
- "_internal/vm/lib/timer_patch.dart"
+ "../../sdk/lib/_internal/vm/lib/async_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/deferred_load_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/timer_patch.dart"
],
- "uri": "async/async.dart"
+ "uri": "../../sdk/lib/async/async.dart"
},
"collection": {
"patches": [
- "_internal/vm/lib/collection_patch.dart",
- "_internal/vm/lib/compact_hash.dart"
+ "../../sdk/lib/_internal/vm/lib/collection_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/compact_hash.dart"
],
- "uri": "collection/collection.dart"
+ "uri": "../../sdk/lib/collection/collection.dart"
},
"ffi": {
"patches": [
- "_internal/vm/lib/ffi_patch.dart",
- "_internal/vm/lib/ffi_dynamic_library_patch.dart",
- "_internal/vm/lib/ffi_native_type_patch.dart"
+ "../../sdk/lib/_internal/vm/lib/ffi_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart"
],
- "uri": "ffi/ffi.dart"
+ "uri": "../../sdk/lib/ffi/ffi.dart"
},
"typed_data": {
- "patches": "_internal/vm/lib/typed_data_patch.dart",
- "uri": "typed_data/typed_data.dart"
+ "patches": "../../sdk/lib/_internal/vm/lib/typed_data_patch.dart",
+ "uri": "../../sdk/lib/typed_data/typed_data.dart"
},
"nativewrappers": {
- "uri": "html/dartium/nativewrappers.dart"
+ "uri": "../../sdk/lib/html/dartium/nativewrappers.dart"
},
"mirrors": {
"patches": [
- "_internal/vm/lib/mirrors_patch.dart",
- "_internal/vm/lib/mirrors_impl.dart",
- "_internal/vm/lib/mirror_reference.dart"
+ "../../sdk/lib/_internal/vm/lib/mirrors_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/mirrors_impl.dart",
+ "../../sdk/lib/_internal/vm/lib/mirror_reference.dart"
],
- "uri": "mirrors/mirrors.dart"
+ "uri": "../../sdk/lib/mirrors/mirrors.dart"
},
"developer": {
"patches": [
- "_internal/vm/lib/developer.dart",
- "_internal/vm/lib/profiler.dart",
- "_internal/vm/lib/timeline.dart"
+ "../../sdk/lib/_internal/vm/lib/developer.dart",
+ "../../sdk/lib/_internal/vm/lib/profiler.dart",
+ "../../sdk/lib/_internal/vm/lib/timeline.dart"
],
- "uri": "developer/developer.dart"
+ "uri": "../../sdk/lib/developer/developer.dart"
},
"isolate": {
"patches": [
- "_internal/vm/lib/isolate_patch.dart",
- "_internal/vm/lib/timer_impl.dart"
+ "../../sdk/lib/_internal/vm/lib/isolate_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/timer_impl.dart"
],
- "uri": "isolate/isolate.dart"
+ "uri": "../../sdk/lib/isolate/isolate.dart"
},
"_vmservice": {
- "uri": "vmservice/vmservice.dart"
+ "uri": "../../sdk/lib/vmservice/vmservice.dart"
},
"wasm": {
"patches": [
- "_internal/vm/lib/wasm_patch.dart"
+ "../../sdk/lib/_internal/vm/lib/wasm_patch.dart"
],
- "uri": "wasm/wasm.dart"
+ "uri": "../../sdk/lib/wasm/wasm.dart"
},
"io": {
"patches": [
- "_internal/vm/bin/common_patch.dart",
- "_internal/vm/bin/directory_patch.dart",
- "_internal/vm/bin/eventhandler_patch.dart",
- "_internal/vm/bin/file_patch.dart",
- "_internal/vm/bin/file_system_entity_patch.dart",
- "_internal/vm/bin/filter_patch.dart",
- "_internal/vm/bin/io_service_patch.dart",
- "_internal/vm/bin/namespace_patch.dart",
- "_internal/vm/bin/platform_patch.dart",
- "_internal/vm/bin/process_patch.dart",
- "_internal/vm/bin/socket_patch.dart",
- "_internal/vm/bin/stdio_patch.dart",
- "_internal/vm/bin/secure_socket_patch.dart",
- "_internal/vm/bin/sync_socket_patch.dart"
+ "../../sdk/lib/_internal/vm/bin/common_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/directory_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/eventhandler_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/file_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/file_system_entity_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/filter_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/io_service_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/namespace_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/platform_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/process_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/socket_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/stdio_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/secure_socket_patch.dart",
+ "../../sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
],
- "uri": "io/io.dart"
+ "uri": "../../sdk/lib/io/io.dart"
},
"_internal": {
"patches": [
- "_internal/vm/lib/internal_patch.dart",
- "_internal/vm/lib/class_id_fasta.dart",
- "_internal/vm/lib/print_patch.dart",
- "_internal/vm/lib/symbol_patch.dart",
- "internal/patch.dart"
+ "../../sdk/lib/_internal/vm/lib/internal_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/class_id_fasta.dart",
+ "../../sdk/lib/_internal/vm/lib/print_patch.dart",
+ "../../sdk/lib/_internal/vm/lib/symbol_patch.dart",
+ "../../sdk/lib/internal/patch.dart"
],
- "uri": "internal/internal.dart"
+ "uri": "../../sdk/lib/internal/internal.dart"
},
"convert": {
- "patches": "_internal/vm/lib/convert_patch.dart",
- "uri": "convert/convert.dart"
+ "patches": "../../sdk/lib/_internal/vm/lib/convert_patch.dart",
+ "uri": "../../sdk/lib/convert/convert.dart"
},
"math": {
- "patches": "_internal/vm/lib/math_patch.dart",
- "uri": "math/math.dart"
+ "patches": "../../sdk/lib/_internal/vm/lib/math_patch.dart",
+ "uri": "../../sdk/lib/math/math.dart"
},
"_http": {
- "uri": "_http/http.dart"
+ "uri": "../../sdk/lib/_http/http.dart"
},
"vmservice_io": {
"uri": "../../runtime/bin/vmservice/vmservice_io.dart"
@@ -161,323 +161,323 @@
"dart2js": {
"libraries": {
"async": {
- "patches": "_internal/js_runtime/lib/async_patch.dart",
- "uri": "async/async.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/async_patch.dart",
+ "uri": "../../sdk/lib/async/async.dart"
},
"_interceptors": {
- "uri": "_internal/js_runtime/lib/interceptors.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/interceptors.dart"
},
"mirrors": {
- "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart",
"supported": false,
- "uri": "mirrors/mirrors.dart"
+ "uri": "../../sdk/lib/mirrors/mirrors.dart"
},
"_js_embedded_names": {
- "uri": "_internal/js_runtime/lib/shared/embedded_names.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart"
},
"io": {
- "patches": "_internal/js_runtime/lib/io_patch.dart",
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/io_patch.dart",
"supported": false,
- "uri": "io/io.dart"
+ "uri": "../../sdk/lib/io/io.dart"
},
"_internal": {
- "patches": "_internal/js_runtime/lib/internal_patch.dart",
- "uri": "internal/internal.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/internal_patch.dart",
+ "uri": "../../sdk/lib/internal/internal.dart"
},
"_metadata": {
- "uri": "html/html_common/metadata.dart"
+ "uri": "../../sdk/lib/html/html_common/metadata.dart"
},
"_async_await_error_codes": {
- "uri": "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart"
},
"_http": {
- "uri": "_http/http.dart"
+ "uri": "../../sdk/lib/_http/http.dart"
},
"_js_primitives": {
- "uri": "_internal/js_runtime/lib/js_primitives.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/js_primitives.dart"
},
"_js_helper": {
- "uri": "_internal/js_runtime/lib/js_helper.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/js_helper.dart"
},
"js": {
- "uri": "js/dart2js/js_dart2js.dart"
+ "uri": "../../sdk/lib/js/dart2js/js_dart2js.dart"
},
"html_common": {
- "uri": "html/html_common/html_common_dart2js.dart"
+ "uri": "../../sdk/lib/html/html_common/html_common_dart2js.dart"
},
"_recipe_syntax": {
- "uri": "_internal/js_runtime/lib/shared/recipe_syntax.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart"
},
"_native_typed_data": {
- "uri": "_internal/js_runtime/lib/native_typed_data.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/native_typed_data.dart"
},
"_js_names": {
- "uri": "_internal/js_runtime/lib/js_names.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/js_names.dart"
},
"core": {
- "patches": "_internal/js_runtime/lib/core_patch.dart",
- "uri": "core/core.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/core_patch.dart",
+ "uri": "../../sdk/lib/core/core.dart"
},
"collection": {
- "patches": "_internal/js_runtime/lib/collection_patch.dart",
- "uri": "collection/collection.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/collection_patch.dart",
+ "uri": "../../sdk/lib/collection/collection.dart"
},
"js_util": {
- "uri": "js_util/dart2js/js_util_dart2js.dart"
+ "uri": "../../sdk/lib/js_util/dart2js/js_util_dart2js.dart"
},
"typed_data": {
- "patches": "_internal/js_runtime/lib/typed_data_patch.dart",
- "uri": "typed_data/typed_data.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart",
+ "uri": "../../sdk/lib/typed_data/typed_data.dart"
},
"web_audio": {
- "uri": "web_audio/dart2js/web_audio_dart2js.dart"
+ "uri": "../../sdk/lib/web_audio/dart2js/web_audio_dart2js.dart"
},
"html": {
- "uri": "html/dart2js/html_dart2js.dart"
+ "uri": "../../sdk/lib/html/dart2js/html_dart2js.dart"
},
"isolate": {
- "patches": "_internal/js_runtime/lib/isolate_patch.dart",
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/isolate_patch.dart",
"supported": false,
- "uri": "isolate/isolate.dart"
+ "uri": "../../sdk/lib/isolate/isolate.dart"
},
"developer": {
- "patches": "_internal/js_runtime/lib/developer_patch.dart",
- "uri": "developer/developer.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/developer_patch.dart",
+ "uri": "../../sdk/lib/developer/developer.dart"
},
"web_gl": {
- "uri": "web_gl/dart2js/web_gl_dart2js.dart"
+ "uri": "../../sdk/lib/web_gl/dart2js/web_gl_dart2js.dart"
},
"indexed_db": {
- "uri": "indexed_db/dart2js/indexed_db_dart2js.dart"
+ "uri": "../../sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart"
},
"_js": {
- "patches": "js/_js_client.dart",
- "uri": "js/_js.dart"
+ "patches": "../../sdk/lib/js/_js_client.dart",
+ "uri": "../../sdk/lib/js/_js.dart"
},
"convert": {
- "patches": "_internal/js_runtime/lib/convert_patch.dart",
- "uri": "convert/convert.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/convert_patch.dart",
+ "uri": "../../sdk/lib/convert/convert.dart"
},
"math": {
- "patches": "_internal/js_runtime/lib/math_patch.dart",
- "uri": "math/math.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/math_patch.dart",
+ "uri": "../../sdk/lib/math/math.dart"
},
"_foreign_helper": {
- "uri": "_internal/js_runtime/lib/foreign_helper.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/foreign_helper.dart"
},
"web_sql": {
- "uri": "web_sql/dart2js/web_sql_dart2js.dart"
+ "uri": "../../sdk/lib/web_sql/dart2js/web_sql_dart2js.dart"
},
"_rti": {
- "uri": "_internal/js_runtime/lib/rti.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/rti.dart"
},
"svg": {
- "uri": "svg/dart2js/svg_dart2js.dart"
+ "uri": "../../sdk/lib/svg/dart2js/svg_dart2js.dart"
}
}
},
"dartdevc": {
"libraries": {
"async": {
- "patches": "_internal/js_dev_runtime/patch/async_patch.dart",
- "uri": "async/async.dart"
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart",
+ "uri": "../../sdk/lib/async/async.dart"
},
"_runtime": {
"uri": "_internal/js_dev_runtime/private/ddc_runtime/runtime.dart"
},
"_interceptors": {
- "uri": "_internal/js_dev_runtime/private/interceptors.dart"
+ "uri": "../../sdk/lib/_internal/js_dev_runtime/private/interceptors.dart"
},
"mirrors": {
- "patches": "_internal/js_dev_runtime/patch/mirrors_patch.dart",
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart",
"supported": false,
- "uri": "mirrors/mirrors.dart"
+ "uri": "../../sdk/lib/mirrors/mirrors.dart"
},
"_debugger": {
- "uri": "_internal/js_dev_runtime/private/debugger.dart"
+ "uri": "../../sdk/lib/_internal/js_dev_runtime/private/debugger.dart"
},
"io": {
- "patches": "_internal/js_dev_runtime/patch/io_patch.dart",
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart",
"supported": false,
- "uri": "io/io.dart"
+ "uri": "../../sdk/lib/io/io.dart"
},
"_internal": {
- "patches": "_internal/js_dev_runtime/patch/internal_patch.dart",
- "uri": "internal/internal.dart"
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart",
+ "uri": "../../sdk/lib/internal/internal.dart"
},
"_metadata": {
- "uri": "html/html_common/metadata.dart"
+ "uri": "../../sdk/lib/html/html_common/metadata.dart"
},
"_http": {
- "uri": "_http/http.dart"
+ "uri": "../../sdk/lib/_http/http.dart"
},
"_js_primitives": {
- "uri": "_internal/js_dev_runtime/private/js_primitives.dart"
+ "uri": "../../sdk/lib/_internal/js_dev_runtime/private/js_primitives.dart"
},
"_js_helper": {
- "uri": "_internal/js_dev_runtime/private/js_helper.dart"
+ "uri": "../../sdk/lib/_internal/js_dev_runtime/private/js_helper.dart"
},
"js": {
- "uri": "_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart"
+ "uri": "../../sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart"
},
"_js_mirrors": {
- "uri": "_internal/js_dev_runtime/private/js_mirrors.dart"
+ "uri": "../../sdk/lib/_internal/js_dev_runtime/private/js_mirrors.dart"
},
"html_common": {
- "uri": "html/html_common/html_common_dart2js.dart"
+ "uri": "../../sdk/lib/html/html_common/html_common_dart2js.dart"
},
"_native_typed_data": {
- "uri": "_internal/js_dev_runtime/private/native_typed_data.dart"
+ "uri": "../../sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart"
},
"core": {
- "patches": "_internal/js_dev_runtime/patch/core_patch.dart",
- "uri": "core/core.dart"
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart",
+ "uri": "../../sdk/lib/core/core.dart"
},
"js_util": {
- "uri": "_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
+ "uri": "../../sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
},
"collection": {
- "patches": "_internal/js_dev_runtime/patch/collection_patch.dart",
- "uri": "collection/collection.dart"
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart",
+ "uri": "../../sdk/lib/collection/collection.dart"
},
"typed_data": {
- "patches": "_internal/js_dev_runtime/patch/typed_data_patch.dart",
- "uri": "typed_data/typed_data.dart"
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart",
+ "uri": "../../sdk/lib/typed_data/typed_data.dart"
},
"web_audio": {
- "uri": "web_audio/dart2js/web_audio_dart2js.dart"
+ "uri": "../../sdk/lib/web_audio/dart2js/web_audio_dart2js.dart"
},
"html": {
- "uri": "html/dart2js/html_dart2js.dart"
+ "uri": "../../sdk/lib/html/dart2js/html_dart2js.dart"
},
"developer": {
- "patches": "_internal/js_dev_runtime/patch/developer_patch.dart",
- "uri": "developer/developer.dart"
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart",
+ "uri": "../../sdk/lib/developer/developer.dart"
},
"isolate": {
- "patches": "_internal/js_dev_runtime/patch/isolate_patch.dart",
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/isolate_patch.dart",
"supported": false,
- "uri": "isolate/isolate.dart"
+ "uri": "../../sdk/lib/isolate/isolate.dart"
},
"web_gl": {
- "uri": "web_gl/dart2js/web_gl_dart2js.dart"
+ "uri": "../../sdk/lib/web_gl/dart2js/web_gl_dart2js.dart"
},
"indexed_db": {
- "uri": "indexed_db/dart2js/indexed_db_dart2js.dart"
+ "uri": "../../sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart"
},
"convert": {
- "patches": "_internal/js_dev_runtime/patch/convert_patch.dart",
- "uri": "convert/convert.dart"
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/convert_patch.dart",
+ "uri": "../../sdk/lib/convert/convert.dart"
},
"_isolate_helper": {
- "uri": "_internal/js_dev_runtime/private/isolate_helper.dart"
+ "uri": "../../sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart"
},
"math": {
- "patches": "_internal/js_dev_runtime/patch/math_patch.dart",
- "uri": "math/math.dart"
+ "patches": "../../sdk/lib/_internal/js_dev_runtime/patch/math_patch.dart",
+ "uri": "../../sdk/lib/math/math.dart"
},
"_foreign_helper": {
- "uri": "_internal/js_dev_runtime/private/foreign_helper.dart"
+ "uri": "../../sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart"
},
"web_sql": {
- "uri": "web_sql/dart2js/web_sql_dart2js.dart"
+ "uri": "../../sdk/lib/web_sql/dart2js/web_sql_dart2js.dart"
},
"svg": {
- "uri": "svg/dart2js/svg_dart2js.dart"
+ "uri": "../../sdk/lib/svg/dart2js/svg_dart2js.dart"
}
}
},
"dart2js_server": {
"libraries": {
"async": {
- "patches": "_internal/js_runtime/lib/async_patch.dart",
- "uri": "async/async.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/async_patch.dart",
+ "uri": "../../sdk/lib/async/async.dart"
},
"mirrors": {
- "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart",
"supported": false,
- "uri": "mirrors/mirrors.dart"
+ "uri": "../../sdk/lib/mirrors/mirrors.dart"
},
"_interceptors": {
- "uri": "_internal/js_runtime/lib/interceptors.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/interceptors.dart"
},
"_js_embedded_names": {
- "uri": "_internal/js_runtime/lib/shared/embedded_names.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart"
},
"io": {
- "patches": "_internal/js_runtime/lib/io_patch.dart",
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/io_patch.dart",
"supported": false,
- "uri": "io/io.dart"
+ "uri": "../../sdk/lib/io/io.dart"
},
"_internal": {
- "patches": "_internal/js_runtime/lib/internal_patch.dart",
- "uri": "internal/internal.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/internal_patch.dart",
+ "uri": "../../sdk/lib/internal/internal.dart"
},
"_async_await_error_codes": {
- "uri": "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart"
},
"_http": {
- "uri": "_http/http.dart"
+ "uri": "../../sdk/lib/_http/http.dart"
},
"_js_helper": {
- "uri": "_internal/js_runtime/lib/js_helper.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/js_helper.dart"
},
"_js_primitives": {
- "uri": "_internal/js_runtime/lib/js_primitives.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/js_primitives.dart"
},
"js": {
- "uri": "js/dart2js/js_dart2js.dart"
+ "uri": "../../sdk/lib/js/dart2js/js_dart2js.dart"
},
"_recipe_syntax": {
- "uri": "_internal/js_runtime/lib/shared/recipe_syntax.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart"
},
"_native_typed_data": {
- "uri": "_internal/js_runtime/lib/native_typed_data.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/native_typed_data.dart"
},
"core": {
- "patches": "_internal/js_runtime/lib/core_patch.dart",
- "uri": "core/core.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/core_patch.dart",
+ "uri": "../../sdk/lib/core/core.dart"
},
"_js_names": {
- "uri": "_internal/js_runtime/lib/js_names.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/js_names.dart"
},
"js_util": {
- "uri": "js_util/dart2js/js_util_dart2js.dart"
+ "uri": "../../sdk/lib/js_util/dart2js/js_util_dart2js.dart"
},
"collection": {
- "patches": "_internal/js_runtime/lib/collection_patch.dart",
- "uri": "collection/collection.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/collection_patch.dart",
+ "uri": "../../sdk/lib/collection/collection.dart"
},
"typed_data": {
- "patches": "_internal/js_runtime/lib/typed_data_patch.dart",
- "uri": "typed_data/typed_data.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart",
+ "uri": "../../sdk/lib/typed_data/typed_data.dart"
},
"isolate": {
- "patches": "_internal/js_runtime/lib/isolate_patch.dart",
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/isolate_patch.dart",
"supported": false,
- "uri": "isolate/isolate.dart"
+ "uri": "../../sdk/lib/isolate/isolate.dart"
},
"developer": {
- "patches": "_internal/js_runtime/lib/developer_patch.dart",
- "uri": "developer/developer.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/developer_patch.dart",
+ "uri": "../../sdk/lib/developer/developer.dart"
},
"_js": {
- "patches": "js/_js_server.dart",
- "uri": "js/_js.dart"
+ "patches": "../../sdk/lib/js/_js_server.dart",
+ "uri": "../../sdk/lib/js/_js.dart"
},
"convert": {
- "patches": "_internal/js_runtime/lib/convert_patch.dart",
- "uri": "convert/convert.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/convert_patch.dart",
+ "uri": "../../sdk/lib/convert/convert.dart"
},
"math": {
- "patches": "_internal/js_runtime/lib/math_patch.dart",
- "uri": "math/math.dart"
+ "patches": "../../sdk/lib/_internal/js_runtime/lib/math_patch.dart",
+ "uri": "../../sdk/lib/math/math.dart"
},
"_foreign_helper": {
- "uri": "_internal/js_runtime/lib/foreign_helper.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/foreign_helper.dart"
},
"_rti": {
- "uri": "_internal/js_runtime/lib/rti.dart"
+ "uri": "../../sdk/lib/_internal/js_runtime/lib/rti.dart"
}
}
}
diff --git a/sdk_nnbd/lib/libraries.yaml b/sdk_nnbd/lib/libraries.yaml
index 31a800e..ce07502 100644
--- a/sdk_nnbd/lib/libraries.yaml
+++ b/sdk_nnbd/lib/libraries.yaml
@@ -17,140 +17,140 @@
vm:
libraries:
_builtin:
- uri: "_internal/vm/bin/builtin.dart"
+ uri: "../../sdk/lib/_internal/vm/bin/builtin.dart"
_internal:
- uri: "internal/internal.dart"
+ uri: "../../sdk/lib/internal/internal.dart"
patches:
- - "_internal/vm/lib/internal_patch.dart"
- - "_internal/vm/lib/class_id_fasta.dart"
- - "_internal/vm/lib/print_patch.dart"
- - "_internal/vm/lib/symbol_patch.dart"
- - "internal/patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/internal_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/class_id_fasta.dart"
+ - "../../sdk/lib/_internal/vm/lib/print_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/symbol_patch.dart"
+ - "../../sdk/lib/internal/patch.dart"
async:
- uri: "async/async.dart"
+ uri: "../../sdk/lib/async/async.dart"
patches:
- - "_internal/vm/lib/async_patch.dart"
- - "_internal/vm/lib/deferred_load_patch.dart"
- - "_internal/vm/lib/schedule_microtask_patch.dart"
- - "_internal/vm/lib/timer_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/async_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/deferred_load_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/schedule_microtask_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/timer_patch.dart"
collection:
- uri: "collection/collection.dart"
+ uri: "../../sdk/lib/collection/collection.dart"
patches:
- - "_internal/vm/lib/collection_patch.dart"
- - "_internal/vm/lib/compact_hash.dart"
+ - "../../sdk/lib/_internal/vm/lib/collection_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/compact_hash.dart"
convert:
- uri: "convert/convert.dart"
- patches: "_internal/vm/lib/convert_patch.dart"
+ uri: "../../sdk/lib/convert/convert.dart"
+ patches: "../../sdk/lib/_internal/vm/lib/convert_patch.dart"
core:
- uri: "core/core.dart"
+ uri: "../../sdk/lib/core/core.dart"
patches:
- - "_internal/vm/lib/core_patch.dart"
- - "_internal/vm/lib/array.dart"
- - "_internal/vm/lib/array_patch.dart"
- - "_internal/vm/lib/bigint_patch.dart"
- - "_internal/vm/lib/bool_patch.dart"
- - "_internal/vm/lib/date_patch.dart"
- - "_internal/vm/lib/double.dart"
- - "_internal/vm/lib/double_patch.dart"
- - "_internal/vm/lib/errors_patch.dart"
- - "_internal/vm/lib/expando_patch.dart"
- - "_internal/vm/lib/function.dart"
- - "_internal/vm/lib/function_patch.dart"
- - "_internal/vm/lib/growable_array.dart"
- - "_internal/vm/lib/identical_patch.dart"
- - "_internal/vm/lib/immutable_map.dart"
- - "_internal/vm/lib/integers.dart"
- - "_internal/vm/lib/integers_patch.dart"
- - "_internal/vm/lib/invocation_mirror_patch.dart"
- - "_internal/vm/lib/lib_prefix.dart"
- - "_internal/vm/lib/map_patch.dart"
- - "_internal/vm/lib/null_patch.dart"
- - "_internal/vm/lib/object_patch.dart"
- - "_internal/vm/lib/regexp_patch.dart"
- - "_internal/vm/lib/stacktrace.dart"
- - "_internal/vm/lib/stopwatch_patch.dart"
- - "_internal/vm/lib/string_buffer_patch.dart"
- - "_internal/vm/lib/string_patch.dart"
- - "_internal/vm/lib/type_patch.dart"
- - "_internal/vm/lib/uri_patch.dart"
- - "_internal/vm/lib/weak_property.dart"
+ - "../../sdk/lib/_internal/vm/lib/core_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/array.dart"
+ - "../../sdk/lib/_internal/vm/lib/array_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/bigint_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/bool_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/date_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/double.dart"
+ - "../../sdk/lib/_internal/vm/lib/double_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/errors_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/expando_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/function.dart"
+ - "../../sdk/lib/_internal/vm/lib/function_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/growable_array.dart"
+ - "../../sdk/lib/_internal/vm/lib/identical_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/immutable_map.dart"
+ - "../../sdk/lib/_internal/vm/lib/integers.dart"
+ - "../../sdk/lib/_internal/vm/lib/integers_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/invocation_mirror_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/lib_prefix.dart"
+ - "../../sdk/lib/_internal/vm/lib/map_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/null_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/object_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/regexp_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/stacktrace.dart"
+ - "../../sdk/lib/_internal/vm/lib/stopwatch_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/string_buffer_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/string_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/type_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/uri_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/weak_property.dart"
developer:
- uri: "developer/developer.dart"
+ uri: "../../sdk/lib/developer/developer.dart"
patches:
- - "_internal/vm/lib/developer.dart"
- - "_internal/vm/lib/profiler.dart"
- - "_internal/vm/lib/timeline.dart"
+ - "../../sdk/lib/_internal/vm/lib/developer.dart"
+ - "../../sdk/lib/_internal/vm/lib/profiler.dart"
+ - "../../sdk/lib/_internal/vm/lib/timeline.dart"
ffi:
- uri: "ffi/ffi.dart"
+ uri: "../../sdk/lib/ffi/ffi.dart"
patches:
- - "_internal/vm/lib/ffi_patch.dart"
- - "_internal/vm/lib/ffi_dynamic_library_patch.dart"
- - "_internal/vm/lib/ffi_native_type_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/ffi_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/ffi_dynamic_library_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart"
wasm:
- uri: "wasm/wasm.dart"
+ uri: "../../sdk/lib/wasm/wasm.dart"
patches:
- - "_internal/vm/lib/wasm_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/wasm_patch.dart"
_http:
- uri: "_http/http.dart"
+ uri: "../../sdk/lib/_http/http.dart"
io:
- uri: "io/io.dart"
+ uri: "../../sdk/lib/io/io.dart"
patches:
- - "_internal/vm/bin/common_patch.dart"
- - "_internal/vm/bin/directory_patch.dart"
- - "_internal/vm/bin/eventhandler_patch.dart"
- - "_internal/vm/bin/file_patch.dart"
- - "_internal/vm/bin/file_system_entity_patch.dart"
- - "_internal/vm/bin/filter_patch.dart"
- - "_internal/vm/bin/io_service_patch.dart"
- - "_internal/vm/bin/namespace_patch.dart"
- - "_internal/vm/bin/platform_patch.dart"
- - "_internal/vm/bin/process_patch.dart"
- - "_internal/vm/bin/socket_patch.dart"
- - "_internal/vm/bin/stdio_patch.dart"
- - "_internal/vm/bin/secure_socket_patch.dart"
- - "_internal/vm/bin/sync_socket_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/common_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/directory_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/eventhandler_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/file_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/file_system_entity_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/filter_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/io_service_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/namespace_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/platform_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/process_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/socket_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/stdio_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/secure_socket_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/sync_socket_patch.dart"
isolate:
- uri: "isolate/isolate.dart"
+ uri: "../../sdk/lib/isolate/isolate.dart"
patches:
- - "_internal/vm/lib/isolate_patch.dart"
- - "_internal/vm/lib/timer_impl.dart"
+ - "../../sdk/lib/_internal/vm/lib/isolate_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/timer_impl.dart"
math:
- uri: "math/math.dart"
- patches: "_internal/vm/lib/math_patch.dart"
+ uri: "../../sdk/lib/math/math.dart"
+ patches: "../../sdk/lib/_internal/vm/lib/math_patch.dart"
mirrors:
- uri: "mirrors/mirrors.dart"
+ uri: "../../sdk/lib/mirrors/mirrors.dart"
patches:
- - "_internal/vm/lib/mirrors_patch.dart"
- - "_internal/vm/lib/mirrors_impl.dart"
- - "_internal/vm/lib/mirror_reference.dart"
+ - "../../sdk/lib/_internal/vm/lib/mirrors_patch.dart"
+ - "../../sdk/lib/_internal/vm/lib/mirrors_impl.dart"
+ - "../../sdk/lib/_internal/vm/lib/mirror_reference.dart"
nativewrappers:
- uri: "html/dartium/nativewrappers.dart"
+ uri: "../../sdk/lib/html/dartium/nativewrappers.dart"
cli:
- uri: "cli/cli.dart"
+ uri: "../../sdk/lib/cli/cli.dart"
patches:
- - "_internal/vm/bin/cli_patch.dart"
+ - "../../sdk/lib/_internal/vm/bin/cli_patch.dart"
typed_data:
- uri: "typed_data/typed_data.dart"
- patches: "_internal/vm/lib/typed_data_patch.dart"
+ uri: "../../sdk/lib/typed_data/typed_data.dart"
+ patches: "../../sdk/lib/_internal/vm/lib/typed_data_patch.dart"
_vmservice:
- uri: "vmservice/vmservice.dart"
+ uri: "../../sdk/lib/vmservice/vmservice.dart"
vmservice_io:
uri: "../../runtime/bin/vmservice/vmservice_io.dart"
@@ -158,210 +158,210 @@
dart2js:
libraries:
async:
- uri: "async/async.dart"
- patches: "_internal/js_runtime/lib/async_patch.dart"
+ uri: "../../sdk/lib/async/async.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/async_patch.dart"
collection:
- uri: "collection/collection.dart"
- patches: "_internal/js_runtime/lib/collection_patch.dart"
+ uri: "../../sdk/lib/collection/collection.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/collection_patch.dart"
convert:
- uri: "convert/convert.dart"
- patches: "_internal/js_runtime/lib/convert_patch.dart"
+ uri: "../../sdk/lib/convert/convert.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/convert_patch.dart"
core:
- uri: "core/core.dart"
- patches: "_internal/js_runtime/lib/core_patch.dart"
+ uri: "../../sdk/lib/core/core.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/core_patch.dart"
developer:
- uri: "developer/developer.dart"
- patches: "_internal/js_runtime/lib/developer_patch.dart"
+ uri: "../../sdk/lib/developer/developer.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/developer_patch.dart"
html:
- uri: "html/dart2js/html_dart2js.dart"
+ uri: "../../sdk/lib/html/dart2js/html_dart2js.dart"
html_common:
- uri: "html/html_common/html_common_dart2js.dart"
+ uri: "../../sdk/lib/html/html_common/html_common_dart2js.dart"
indexed_db:
- uri: "indexed_db/dart2js/indexed_db_dart2js.dart"
+ uri: "../../sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart"
_http:
- uri: "_http/http.dart"
+ uri: "../../sdk/lib/_http/http.dart"
io:
- uri: "io/io.dart"
- patches: "_internal/js_runtime/lib/io_patch.dart"
+ uri: "../../sdk/lib/io/io.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/io_patch.dart"
supported: false
isolate:
- uri: "isolate/isolate.dart"
- patches: "_internal/js_runtime/lib/isolate_patch.dart"
+ uri: "../../sdk/lib/isolate/isolate.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/isolate_patch.dart"
supported: false
js:
- uri: "js/dart2js/js_dart2js.dart"
+ uri: "../../sdk/lib/js/dart2js/js_dart2js.dart"
_js:
- uri: "js/_js.dart"
- patches: "js/_js_client.dart"
+ uri: "../../sdk/lib/js/_js.dart"
+ patches: "../../sdk/lib/js/_js_client.dart"
js_util:
- uri: "js_util/dart2js/js_util_dart2js.dart"
+ uri: "../../sdk/lib/js_util/dart2js/js_util_dart2js.dart"
math:
- uri: "math/math.dart"
- patches: "_internal/js_runtime/lib/math_patch.dart"
+ uri: "../../sdk/lib/math/math.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/math_patch.dart"
mirrors:
- uri: "mirrors/mirrors.dart"
- patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
+ uri: "../../sdk/lib/mirrors/mirrors.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart"
supported: false
typed_data:
- uri: "typed_data/typed_data.dart"
- patches: "_internal/js_runtime/lib/typed_data_patch.dart"
+ uri: "../../sdk/lib/typed_data/typed_data.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart"
_native_typed_data:
- uri: "_internal/js_runtime/lib/native_typed_data.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/native_typed_data.dart"
svg:
- uri: "svg/dart2js/svg_dart2js.dart"
+ uri: "../../sdk/lib/svg/dart2js/svg_dart2js.dart"
web_audio:
- uri: "web_audio/dart2js/web_audio_dart2js.dart"
+ uri: "../../sdk/lib/web_audio/dart2js/web_audio_dart2js.dart"
web_gl:
- uri: "web_gl/dart2js/web_gl_dart2js.dart"
+ uri: "../../sdk/lib/web_gl/dart2js/web_gl_dart2js.dart"
web_sql:
- uri: "web_sql/dart2js/web_sql_dart2js.dart"
+ uri: "../../sdk/lib/web_sql/dart2js/web_sql_dart2js.dart"
_internal:
- uri: "internal/internal.dart"
- patches: "_internal/js_runtime/lib/internal_patch.dart"
+ uri: "../../sdk/lib/internal/internal.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/internal_patch.dart"
_js_helper:
- uri: "_internal/js_runtime/lib/js_helper.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/js_helper.dart"
_rti:
- uri: "_internal/js_runtime/lib/rti.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/rti.dart"
_interceptors:
- uri: "_internal/js_runtime/lib/interceptors.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/interceptors.dart"
_foreign_helper:
- uri: "_internal/js_runtime/lib/foreign_helper.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/foreign_helper.dart"
_js_names:
- uri: "_internal/js_runtime/lib/js_names.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/js_names.dart"
_js_primitives:
- uri: "_internal/js_runtime/lib/js_primitives.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/js_primitives.dart"
_js_embedded_names:
- uri: "_internal/js_runtime/lib/shared/embedded_names.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart"
_async_await_error_codes:
- uri: "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart"
_recipe_syntax:
- uri: "_internal/js_runtime/lib/shared/recipe_syntax.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart"
_metadata:
- uri: "html/html_common/metadata.dart"
+ uri: "../../sdk/lib/html/html_common/metadata.dart"
dart2js_server:
libraries:
async:
- uri: "async/async.dart"
- patches: "_internal/js_runtime/lib/async_patch.dart"
+ uri: "../../sdk/lib/async/async.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/async_patch.dart"
collection:
- uri: "collection/collection.dart"
- patches: "_internal/js_runtime/lib/collection_patch.dart"
+ uri: "../../sdk/lib/collection/collection.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/collection_patch.dart"
convert:
- uri: "convert/convert.dart"
- patches: "_internal/js_runtime/lib/convert_patch.dart"
+ uri: "../../sdk/lib/convert/convert.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/convert_patch.dart"
core:
- uri: "core/core.dart"
- patches: "_internal/js_runtime/lib/core_patch.dart"
+ uri: "../../sdk/lib/core/core.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/core_patch.dart"
developer:
- uri: "developer/developer.dart"
- patches: "_internal/js_runtime/lib/developer_patch.dart"
+ uri: "../../sdk/lib/developer/developer.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/developer_patch.dart"
_http:
- uri: "_http/http.dart"
+ uri: "../../sdk/lib/_http/http.dart"
io:
- uri: "io/io.dart"
- patches: "_internal/js_runtime/lib/io_patch.dart"
+ uri: "../../sdk/lib/io/io.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/io_patch.dart"
supported: false
isolate:
- uri: "isolate/isolate.dart"
- patches: "_internal/js_runtime/lib/isolate_patch.dart"
+ uri: "../../sdk/lib/isolate/isolate.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/isolate_patch.dart"
supported: false
js:
- uri: "js/dart2js/js_dart2js.dart"
+ uri: "../../sdk/lib/js/dart2js/js_dart2js.dart"
_js:
- uri: "js/_js.dart"
- patches: "js/_js_server.dart"
+ uri: "../../sdk/lib/js/_js.dart"
+ patches: "../../sdk/lib/js/_js_server.dart"
js_util:
- uri: "js_util/dart2js/js_util_dart2js.dart"
+ uri: "../../sdk/lib/js_util/dart2js/js_util_dart2js.dart"
math:
- uri: "math/math.dart"
- patches: "_internal/js_runtime/lib/math_patch.dart"
+ uri: "../../sdk/lib/math/math.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/math_patch.dart"
mirrors:
- uri: "mirrors/mirrors.dart"
- patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
+ uri: "../../sdk/lib/mirrors/mirrors.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart"
supported: false
typed_data:
- uri: "typed_data/typed_data.dart"
- patches: "_internal/js_runtime/lib/typed_data_patch.dart"
+ uri: "../../sdk/lib/typed_data/typed_data.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/typed_data_patch.dart"
_native_typed_data:
- uri: "_internal/js_runtime/lib/native_typed_data.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/native_typed_data.dart"
_internal:
- uri: "internal/internal.dart"
- patches: "_internal/js_runtime/lib/internal_patch.dart"
+ uri: "../../sdk/lib/internal/internal.dart"
+ patches: "../../sdk/lib/_internal/js_runtime/lib/internal_patch.dart"
_js_helper:
- uri: "_internal/js_runtime/lib/js_helper.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/js_helper.dart"
_rti:
- uri: "_internal/js_runtime/lib/rti.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/rti.dart"
_interceptors:
- uri: "_internal/js_runtime/lib/interceptors.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/interceptors.dart"
_foreign_helper:
- uri: "_internal/js_runtime/lib/foreign_helper.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/foreign_helper.dart"
_js_names:
- uri: "_internal/js_runtime/lib/js_names.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/js_names.dart"
_js_primitives:
- uri: "_internal/js_runtime/lib/js_primitives.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/js_primitives.dart"
_js_embedded_names:
- uri: "_internal/js_runtime/lib/shared/embedded_names.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart"
_async_await_error_codes:
- uri: "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/shared/async_await_error_codes.dart"
_recipe_syntax:
- uri: "_internal/js_runtime/lib/shared/recipe_syntax.dart"
+ uri: "../../sdk/lib/_internal/js_runtime/lib/shared/recipe_syntax.dart"
dartdevc:
libraries:
@@ -369,105 +369,105 @@
uri: "_internal/js_dev_runtime/private/ddc_runtime/runtime.dart"
_debugger:
- uri: "_internal/js_dev_runtime/private/debugger.dart"
+ uri: "../../sdk/lib/_internal/js_dev_runtime/private/debugger.dart"
_foreign_helper:
- uri: "_internal/js_dev_runtime/private/foreign_helper.dart"
+ uri: "../../sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart"
_http:
- uri: "_http/http.dart"
+ uri: "../../sdk/lib/_http/http.dart"
_interceptors:
- uri: "_internal/js_dev_runtime/private/interceptors.dart"
+ uri: "../../sdk/lib/_internal/js_dev_runtime/private/interceptors.dart"
_internal:
- uri: "internal/internal.dart"
- patches: "_internal/js_dev_runtime/patch/internal_patch.dart"
+ uri: "../../sdk/lib/internal/internal.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart"
_isolate_helper:
- uri: "_internal/js_dev_runtime/private/isolate_helper.dart"
+ uri: "../../sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart"
_js_helper:
- uri: "_internal/js_dev_runtime/private/js_helper.dart"
+ uri: "../../sdk/lib/_internal/js_dev_runtime/private/js_helper.dart"
_js_mirrors:
- uri: "_internal/js_dev_runtime/private/js_mirrors.dart"
+ uri: "../../sdk/lib/_internal/js_dev_runtime/private/js_mirrors.dart"
_js_primitives:
- uri: "_internal/js_dev_runtime/private/js_primitives.dart"
+ uri: "../../sdk/lib/_internal/js_dev_runtime/private/js_primitives.dart"
_metadata:
- uri: "html/html_common/metadata.dart"
+ uri: "../../sdk/lib/html/html_common/metadata.dart"
_native_typed_data:
- uri: "_internal/js_dev_runtime/private/native_typed_data.dart"
+ uri: "../../sdk/lib/_internal/js_dev_runtime/private/native_typed_data.dart"
async:
- uri: "async/async.dart"
- patches: "_internal/js_dev_runtime/patch/async_patch.dart"
+ uri: "../../sdk/lib/async/async.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart"
collection:
- uri: "collection/collection.dart"
- patches: "_internal/js_dev_runtime/patch/collection_patch.dart"
+ uri: "../../sdk/lib/collection/collection.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart"
convert:
- uri: "convert/convert.dart"
- patches: "_internal/js_dev_runtime/patch/convert_patch.dart"
+ uri: "../../sdk/lib/convert/convert.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/convert_patch.dart"
core:
- uri: "core/core.dart"
- patches: "_internal/js_dev_runtime/patch/core_patch.dart"
+ uri: "../../sdk/lib/core/core.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart"
developer:
- uri: "developer/developer.dart"
- patches: "_internal/js_dev_runtime/patch/developer_patch.dart"
+ uri: "../../sdk/lib/developer/developer.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/developer_patch.dart"
io:
- uri: "io/io.dart"
- patches: "_internal/js_dev_runtime/patch/io_patch.dart"
+ uri: "../../sdk/lib/io/io.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart"
supported: false
isolate:
- uri: "isolate/isolate.dart"
- patches: "_internal/js_dev_runtime/patch/isolate_patch.dart"
+ uri: "../../sdk/lib/isolate/isolate.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/isolate_patch.dart"
supported: false
mirrors:
- uri: "mirrors/mirrors.dart"
- patches: "_internal/js_dev_runtime/patch/mirrors_patch.dart"
+ uri: "../../sdk/lib/mirrors/mirrors.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/mirrors_patch.dart"
supported: false
math:
- uri: "math/math.dart"
- patches: "_internal/js_dev_runtime/patch/math_patch.dart"
+ uri: "../../sdk/lib/math/math.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/math_patch.dart"
typed_data:
- uri: "typed_data/typed_data.dart"
- patches: "_internal/js_dev_runtime/patch/typed_data_patch.dart"
+ uri: "../../sdk/lib/typed_data/typed_data.dart"
+ patches: "../../sdk/lib/_internal/js_dev_runtime/patch/typed_data_patch.dart"
html:
- uri: "html/dart2js/html_dart2js.dart"
+ uri: "../../sdk/lib/html/dart2js/html_dart2js.dart"
html_common:
- uri: "html/html_common/html_common_dart2js.dart"
+ uri: "../../sdk/lib/html/html_common/html_common_dart2js.dart"
indexed_db:
- uri: "indexed_db/dart2js/indexed_db_dart2js.dart"
+ uri: "../../sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart"
js:
- uri: "_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart"
+ uri: "../../sdk/lib/_internal/js_dev_runtime/lib/js/dart2js/js_dart2js.dart"
js_util:
- uri: "_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
+ uri: "../../sdk/lib/_internal/js_dev_runtime/lib/js_util/dart2js/js_util_dart2js.dart"
svg:
- uri: "svg/dart2js/svg_dart2js.dart"
+ uri: "../../sdk/lib/svg/dart2js/svg_dart2js.dart"
web_audio:
- uri: "web_audio/dart2js/web_audio_dart2js.dart"
+ uri: "../../sdk/lib/web_audio/dart2js/web_audio_dart2js.dart"
web_gl:
- uri: "web_gl/dart2js/web_gl_dart2js.dart"
+ uri: "../../sdk/lib/web_gl/dart2js/web_gl_dart2js.dart"
web_sql:
- uri: "web_sql/dart2js/web_sql_dart2js.dart"
+ uri: "../../sdk/lib/web_sql/dart2js/web_sql_dart2js.dart"
diff --git a/tests/co19/update.sh b/tests/co19/update.sh
new file mode 100755
index 0000000..b4b5ff0
--- /dev/null
+++ b/tests/co19/update.sh
@@ -0,0 +1,71 @@
+#!/usr/bin/env bash
+# Uploads a new version of the co19 CIPD package.
+# This script requires access to the dart-build-access group, which EngProd has.
+
+set -e
+set -x
+
+if [ ! -e tests/co19 ]; then
+ echo "$0: error: Run this script at the root of the Dart SDK" >&2
+ exit 1
+fi
+
+# Find the latest co19 commit.
+rm -rf tests/co19/src.git
+git clone https://dart.googlesource.com/co19 tests/co19/src.git
+CO19=tests/co19/src.git
+OLD=$(gclient getdep --var=co19_rev)
+NEW=$(cd $CO19 && git fetch origin && git rev-parse origin/master)
+
+git fetch origin
+git branch cl-co19-roll-co19-to-$NEW origin/master
+git checkout cl-co19-roll-co19-to-$NEW
+
+# Build a cipd package of the commit.
+BUILD_ID=$(bb add \
+ -commit https://dart.googlesource.com/co19/+/$NEW \
+ -json \
+ dart/ci/co19-roller \
+ | jq '.id' \
+ | tr -d '"')
+bb collect -interval 10s $BUILD_ID
+
+# Update DEPS:
+gclient setdep --var=co19_rev=$NEW
+
+# Make a nice commit. Don't include the '#' character to avoid referencing Dart
+# SDK issues.
+git commit DEPS -m \
+ "$(printf "[co19] Roll co19 to $NEW\n\n" &&
+ cd $CO19 &&
+ git log --date='format:%Y-%m-%d' --pretty='format:%ad %ae %s' \
+ $OLD..$NEW | tr -d '#')"
+
+rm -rf tests/co19/src.git
+
+GIT_EDITOR=true git cl upload
+ISSUE=$(git config --get branch.cl-co19-roll-co19-to-$NEW.gerritissue)
+
+BUILDERS=$(jq '.builder_configurations|
+ map(select(.steps|
+ any(.arguments|
+ select(.!=null)|
+ any(.=="co19"))))|
+ map(.builders)|
+ flatten|
+ sort' \
+ tools/bots/test_matrix.json \
+ | tr -d '[",]')
+
+git cl try -B dart/try $(for BUILDER in $BUILDERS; do echo -b $BUILDER-try; done)
+
+git cl web
+
+set +x
+cat << EOF
+
+Wait for the builders to finish. If any failed, pre-approve them:
+
+ tools/sdks/dart-sdk/bin/dart tools/approve_results.dart \
+ -p https://dart-review.googlesource.com/c/sdk/+/$ISSUE
+EOF
diff --git a/tests/co19_2/co19_2-co19.status b/tests/co19_2/co19_2-co19.status
new file mode 100644
index 0000000..0d2914b
--- /dev/null
+++ b/tests/co19_2/co19_2-co19.status
@@ -0,0 +1,265 @@
+# Copyright (c) 2019, 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.
+
+[ $compiler != fasta ]
+Language/Classes/Abstract_Instance_Members/inherited_t13: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Abstract_Instance_Members/inherited_t14: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Abstract_Instance_Members/inherited_t15: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Abstract_Instance_Members/invocation_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Abstract_Instance_Members/invocation_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Abstract_Instance_Members/override_default_value_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Abstract_Instance_Members/override_less_positional_parameters_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Abstract_Instance_Members/override_more_required_parameters_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Abstract_Instance_Members/override_no_named_parameters_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Abstract_Instance_Members/override_not_a_subtype_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Abstract_Instance_Members/same_name_static_method_in_superclass_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Constant_Constructors/name_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Constant_Constructors/not_a_constant_in_superclass_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Constant_Constructors/superinitializer_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Constant_Constructors/superinitializer_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/name_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/name_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/redirecting_constructor_call_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/redirecting_constructor_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/redirecting_to_itself_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/redirecting_to_itself_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/redirecting_to_itself_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/return_type_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/return_wrong_type_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/return_wrong_type_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Factories/return_wrong_type_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Generative_Constructors/execution_of_a_superinitializer_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Generative_Constructors/formal_parameter_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Generative_Constructors/formal_parameter_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Generative_Constructors/formal_parameter_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Generative_Constructors/implicit_superinitializer_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Generative_Constructors/implicit_superinitializer_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Generative_Constructors/initializers_t17: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Generative_Constructors/name_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/Generative_Constructors/superinitializer_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/implicit_constructor_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/implicit_constructor_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/name_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/wrong_name_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Constructors/wrong_name_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Getters/instance_getter_t13: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Getters/instance_getter_t14: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Getters/override_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Getters/same_name_method_t13: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Getters/same_name_method_t14: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Getters/type_object_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_different_default_values_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_fewer_parameters_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_more_parameters_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_named_parameters_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_named_parameters_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_named_parameters_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_named_parameters_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_named_parameters_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_subtype_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_subtype_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_subtype_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_subtype_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_subtype_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/override_subtype_t12: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/same_name_getter_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/same_name_setter_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Variables/definition_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Variables/type_aliases_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Variables/type_aliases_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Instance_Variables/type_aliases_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Setters/syntax_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Static_Methods/declaration_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Static_Variables/inheritance_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Static_Variables/type_alias_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/Inheritance_and_Overriding/abstract_method_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/Inheritance_and_Overriding/inheritance_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/Inheritance_and_Overriding/inheritance_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/Inheritance_and_Overriding/inheritance_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/Inheritance_and_Overriding/overriding_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/Inheritance_and_Overriding/overriding_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/Inheritance_and_Overriding/overriding_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/extends_clause_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/superclass_of_itself_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/superclass_of_itself_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superclasses/transition_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superinterfaces/dynamic_type_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superinterfaces/implicit_interface_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superinterfaces/itself_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superinterfaces/more_than_once_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superinterfaces/no_member_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superinterfaces/no_member_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superinterfaces/superclass_as_superinterface_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superinterfaces/superclass_as_superinterface_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superinterfaces/superclass_as_superinterface_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Classes/Superinterfaces/syntax_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Enums/restrictions_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Enums/restrictions_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Enums/restrictions_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Enums/restrictions_t12: Skip # github.com/dart-lang/language/issues/115
+Language/Enums/syntax_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Expressions/Instance_Creation/New/type_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Expressions/Instance_Creation/New/type_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/Superbounded_types/typedef3_A01_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/Superbounded_types/typedef3_A01_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/Superbounded_types/typedef3_A01_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/Superbounded_types/typedef3_A01_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/Superbounded_types/typedef3_A01_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/Superbounded_types/typedef3_A01_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/parameter_A01_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/parameter_A01_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/parameter_A02_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/parameter_A03_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/parameter_A04_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/parameter_A09_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/syntax_t20: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/syntax_t21: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/syntax_t22: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/syntax_t23: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/syntax_t24: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/syntax_t25: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/syntax_t27: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/syntax_t28: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/syntax_t29: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/syntax_t30: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A01_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A01_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A01_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A01_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A01_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A01_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A01_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A01_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A01_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A04_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A04_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t12: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t13: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A06_t14: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A07_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A08_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A09_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A09_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Generics/typedef_A10_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/inheritance_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/inheritance_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/inheritance_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/inheritance_t12: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/inheritance_t13: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/inheritance_t14: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/not_overriden_members_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/not_overriden_members_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_getters_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_getters_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_getters_type_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_getters_type_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_getters_type_t12: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_members_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/Inheritance_and_Overriding/same_name_method_and_getter_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/definition_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Interfaces/Superinterfaces/superinterface_of_itself_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/abstract_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/abstract_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/abstract_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/abstract_t12: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/abstract_t13: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/deferred_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/implicit_constructor_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/implicit_constructor_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/initializers_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/initializers_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/initializers_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/interfaces_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/interfaces_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/superclass_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/superclass_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/superinterfaces_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/superinterfaces_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/superinterfaces_t12: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/superinterfaces_t13: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/superinterfaces_t14: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/syntax_t26: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/warning_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Application/wrong_mixin_type_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/Mixin_Composition/order_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Mixins/declaring_constructor_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t07: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t08: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t09: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t10: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t11: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/built-in_types_t12: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/scope_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/scope_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/scope_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/scope_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/self_reference_t19: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/self_reference_t20: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/self_reference_t21: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/self_reference_t22: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/self_reference_t23: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/self_reference_t24: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/self_reference_t25: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/syntax_t01: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/syntax_t02: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/syntax_t03: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/syntax_t04: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/syntax_t05: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/syntax_t06: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/syntax_t20: Skip # github.com/dart-lang/language/issues/115
+Language/Types/Type_Aliases/syntax_t21: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Instantiate-to-bound/nonfunction_typedef/dynamic/*: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Instantiate-to-bound/nonfunction_typedef/static/*: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_FutureOr_l1_t01: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_FutureOr_l1_t02: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_l1_t01: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_l1_t02: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_l1_t03: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_l1_t04: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_l2_t01: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_l2_t02: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_typedef_l1_t01: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_typedef_l1_t02: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_typedef_l1_t03: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_typedef_l1_t04: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_typedef_l1_t05: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_typedef_l1_t07: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/dynamic/typedef1_typedef_l1_t08: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_FutureOr_l1_t01: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_FutureOr_l1_t02: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_l1_t01: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_l1_t02: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_l1_t03: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_l1_t04: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_l2_t01: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_l2_t02: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_typedef_l1_t01: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_typedef_l1_t02: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_typedef_l1_t03: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_typedef_l1_t04: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_typedef_l1_t05: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_typedef_l1_t06: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_typedef_l1_t07: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/Simple-bounds/static/typedef1_typedef_l1_t08: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/regression/32903_t02: Skip # github.com/dart-lang/language/issues/115
+LanguageFeatures/regression/34560_t02: Skip # github.com/dart-lang/language/issues/115
diff --git a/tests/co19_2/update.sh b/tests/co19_2/update.sh
index 3fb0933..db2c88f 100755
--- a/tests/co19_2/update.sh
+++ b/tests/co19_2/update.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Uploads a new version of the co19 CIPD packages.
+# Uploads a new version of the co19_2 CIPD package.
# This script requires access to the dart-build-access group, which EngProd has.
set -e
@@ -25,6 +25,7 @@
BUILD_ID=$(bb add \
-commit https://dart.googlesource.com/co19/+/$NEW \
-json \
+ -p variant=legacy \
dart/ci/co19-roller \
| jq '.id' \
| tr -d '"')
@@ -36,7 +37,7 @@
# Make a nice commit. Don't include the '#' character to avoid referencing Dart
# SDK issues.
git commit DEPS -m \
- "$(printf "[co19] Roll co19 to $NEW\n\n" &&
+ "$(printf "[co19] Roll co19_2 to $NEW\n\n" &&
cd $CO19 &&
git log --date='format:%Y-%m-%d' --pretty='format:%ad %ae %s' \
$OLD..$NEW | tr -d '#')"
diff --git a/tests/compiler/dart2js/analyses/analysis_helper.dart b/tests/compiler/dart2js/analyses/analysis_helper.dart
index cea60ab..211c911 100644
--- a/tests/compiler/dart2js/analyses/analysis_helper.dart
+++ b/tests/compiler/dart2js/analyses/analysis_helper.dart
@@ -75,6 +75,9 @@
ir.ConstantEvaluator _constantEvaluator;
+ @override
+ ir.StaticTypeContext staticTypeContext;
+
StaticTypeVisitorBase(
ir.Component component, ir.ClassHierarchy classHierarchy)
: super(
@@ -103,10 +106,12 @@
// Skip synthetic .dill members.
return;
}
+ staticTypeContext = new ir.StaticTypeContext(node, typeEnvironment);
variableScopeModel =
new ScopeModel.from(node, _constantEvaluator).variableScopeModel;
super.visitProcedure(node);
variableScopeModel = null;
+ staticTypeContext = null;
}
@override
@@ -115,10 +120,12 @@
// Skip synthetic .dill members.
return;
}
+ staticTypeContext = new ir.StaticTypeContext(node, typeEnvironment);
variableScopeModel =
new ScopeModel.from(node, _constantEvaluator).variableScopeModel;
super.visitField(node);
variableScopeModel = null;
+ staticTypeContext = null;
}
@override
@@ -127,10 +134,12 @@
// Skip synthetic .dill members.
return;
}
+ staticTypeContext = new ir.StaticTypeContext(node, typeEnvironment);
variableScopeModel =
new ScopeModel.from(node, _constantEvaluator).variableScopeModel;
super.visitConstructor(node);
variableScopeModel = null;
+ staticTypeContext = null;
}
}
@@ -292,9 +301,7 @@
enclosingClass = enclosingClass.parent;
}
try {
- typeEnvironment.thisType =
- enclosingClass is ir.Class ? enclosingClass.thisType : null;
- return node.getStaticType(typeEnvironment);
+ return node.getStaticType(staticTypeContext);
} catch (e) {
// The static type computation crashes on type errors. Use `dynamic`
// as static type.
diff --git a/tests/compiler/dart2js/analyses/api_allowed.json b/tests/compiler/dart2js/analyses/api_allowed.json
index 9a02f59..b988fc0 100644
--- a/tests/compiler/dart2js/analyses/api_allowed.json
+++ b/tests/compiler/dart2js/analyses/api_allowed.json
@@ -178,20 +178,6 @@
"Dynamic invocation of 'where'.": 1,
"Dynamic access of 'single'.": 1
},
- "org-dartlang-sdk:///sdk/lib/_internal/js_runtime/lib/core_patch.dart": {
- "Dynamic access of 'dart.core::_digits'.": 2,
- "Dynamic invocation of '<'.": 2,
- "Dynamic invocation of '[]'.": 17,
- "Dynamic invocation of '+'.": 2,
- "Dynamic invocation of 'dart.core::_absSubSetSign'.": 3,
- "Dynamic invocation of 'dart.core::_absAndNotSetSign'.": 2,
- "Dynamic invocation of 'dart.core::_absAddSetSign'.": 2,
- "Dynamic invocation of 'dart.core::_absXorSetSign'.": 1,
- "Dynamic invocation of '[]='.": 2,
- "Dynamic invocation of '&'.": 6,
- "Dynamic invocation of '-'.": 1,
- "Dynamic invocation of '>='.": 1
- },
"org-dartlang-sdk:///sdk/lib/core/errors.dart": {
"Dynamic access of 'length'.": 2
},
@@ -239,4 +225,4 @@
"Dynamic access of 'port'.": 1,
"Dynamic invocation of 'dart._http::_toJSON'.": 1
}
-}
\ No newline at end of file
+}
diff --git a/tests/compiler/dart2js/analyses/dart2js_allowed.json b/tests/compiler/dart2js/analyses/dart2js_allowed.json
index ff6c98a..f62235b 100644
--- a/tests/compiler/dart2js/analyses/dart2js_allowed.json
+++ b/tests/compiler/dart2js/analyses/dart2js_allowed.json
@@ -183,21 +183,12 @@
"third_party/pkg/dart2js_info/lib/binary_serialization.dart": {
"Dynamic invocation of 'cast'.": 1
},
- "pkg/compiler/lib/src/inferrer/inferrer_engine.dart": {
- "Dynamic access of 'isVoid'.": 1,
- "Dynamic access of 'isDynamic'.": 1,
- "Dynamic access of 'isInterfaceType'.": 1,
- "Dynamic access of 'element'.": 1
- },
"pkg/compiler/lib/src/js_backend/checked_mode_helpers.dart": {
"Dynamic access of 'name'.": 1
},
"pkg/compiler/lib/src/universe/side_effects.dart": {
"Dynamic access of 'universe.side_effects::_flags'.": 1
},
- "pkg/compiler/lib/src/native/enqueue.dart": {
- "Dynamic access of 'isDynamic'.": 1
- },
"pkg/compiler/lib/src/ssa/builder_kernel.dart": {
"Dynamic update to 'instantiatedTypes'.": 1,
"Dynamic update to 'sideEffects'.": 1,
@@ -206,8 +197,6 @@
"Dynamic invocation of 'addSuccessor'.": 1
},
"pkg/compiler/lib/src/ssa/types.dart": {
- "Dynamic access of 'isVoid'.": 1,
- "Dynamic access of 'isDynamic'.": 1,
"Dynamic access of 'treatAsDynamic'.": 1,
"Dynamic access of 'element'.": 1
},
diff --git a/tests/compiler/dart2js/analyses/static_type_visitor_test.dart b/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
index d546a06..44c73c0 100644
--- a/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
+++ b/tests/compiler/dart2js/analyses/static_type_visitor_test.dart
@@ -40,14 +40,14 @@
// as static type.
return const ir.DynamicType();
}
- ir.TreeNode enclosingClass = node;
- while (enclosingClass != null && enclosingClass is! ir.Class) {
- enclosingClass = enclosingClass.parent;
+ ir.TreeNode enclosingMember = node;
+ while (enclosingMember != null && enclosingMember is! ir.Member) {
+ enclosingMember = enclosingMember.parent;
}
try {
- typeEnvironment.thisType =
- enclosingClass is ir.Class ? enclosingClass.thisType : null;
- return node.getStaticType(typeEnvironment);
+ staticTypeContext =
+ new ir.StaticTypeContext(enclosingMember, typeEnvironment);
+ return node.getStaticType(staticTypeContext);
} catch (e) {
// The static type computation crashes on type errors. Use `dynamic`
// as static type.
diff --git a/tests/compiler/dart2js/equivalence/check_helpers.dart b/tests/compiler/dart2js/equivalence/check_helpers.dart
index ee1aa14..1b7ae3a 100644
--- a/tests/compiler/dart2js/equivalence/check_helpers.dart
+++ b/tests/compiler/dart2js/equivalence/check_helpers.dart
@@ -441,6 +441,23 @@
}
@override
+ visitLegacyType(LegacyType type, _) {
+ visit(type.baseType);
+ sb.write('*');
+ }
+
+ @override
+ visitNullableType(NullableType type, _) {
+ visit(type.baseType);
+ sb.write('?');
+ }
+
+ @override
+ visitNeverType(NeverType type, _) {
+ sb.write('Never');
+ }
+
+ @override
visitDynamicType(DynamicType type, _) {
sb.write('dynamic');
}
@@ -458,7 +475,7 @@
@override
visitTypedefType(TypedefType type, _) {
sb.write(type.element.name);
- if (type.typeArguments.any((type) => !type.isDynamic)) {
+ if (type.typeArguments.any((type) => type is! DynamicType)) {
sb.write('<');
visitTypes(type.typeArguments);
sb.write('>');
@@ -468,7 +485,7 @@
@override
visitInterfaceType(InterfaceType type, _) {
sb.write(type.element.name);
- if (type.typeArguments.any((type) => !type.isDynamic)) {
+ if (type.typeArguments.any((type) => type is! DynamicType)) {
sb.write('<');
visitTypes(type.typeArguments);
sb.write('>');
diff --git a/tests/compiler/dart2js/helpers/shared_helper.dart b/tests/compiler/dart2js/helpers/shared_helper.dart
index d03dddc..ec3cc15 100644
--- a/tests/compiler/dart2js/helpers/shared_helper.dart
+++ b/tests/compiler/dart2js/helpers/shared_helper.dart
@@ -24,6 +24,23 @@
}
@override
+ void visitLegacyType(LegacyType type, StringBuffer sb) {
+ visit(type.baseType, sb);
+ sb.write('*');
+ }
+
+ @override
+ void visitNullableType(NullableType type, StringBuffer sb) {
+ visit(type.baseType, sb);
+ sb.write('?');
+ }
+
+ @override
+ void visitNeverType(NeverType type, StringBuffer sb) {
+ sb.write('Never');
+ }
+
+ @override
void visitVoidType(VoidType type, StringBuffer sb) {
sb.write('void');
}
diff --git a/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart b/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart
index 180375b..5a5e639 100644
--- a/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart
+++ b/tests/compiler/dart2js/model/cfe_constant_evaluation_test.dart
@@ -19,6 +19,7 @@
import 'package:compiler/src/kernel/element_map_impl.dart';
import 'package:front_end/src/api_unstable/dart2js.dart' as ir;
import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
import '../helpers/memory_compiler.dart';
class TestData {
@@ -575,6 +576,7 @@
Compiler compiler = result.compiler;
KernelFrontendStrategy frontEndStrategy = compiler.frontendStrategy;
KernelToElementMapImpl elementMap = frontEndStrategy.elementMap;
+ ir.TypeEnvironment typeEnvironment = elementMap.typeEnvironment;
KElementEnvironment elementEnvironment =
compiler.frontendStrategy.elementEnvironment;
ConstantValuefier constantValuefier = new ConstantValuefier(elementMap);
@@ -605,7 +607,8 @@
errors.add(context.first.code.name);
reportLocatedMessage(elementMap.reporter, message, context);
}, environment: environment, supportReevaluationForTesting: true);
- ir.Constant evaluatedConstant = evaluator.evaluate(initializer);
+ ir.Constant evaluatedConstant = evaluator.evaluate(
+ new ir.StaticTypeContext(node, typeEnvironment), initializer);
ConstantValue value = evaluatedConstant is! ir.UnevaluatedConstant
? constantValuefier.visitConstant(evaluatedConstant)
diff --git a/tests/compiler/dart2js/model/cfe_constant_test.dart b/tests/compiler/dart2js/model/cfe_constant_test.dart
index a6ff5a0..a35b457 100644
--- a/tests/compiler/dart2js/model/cfe_constant_test.dart
+++ b/tests/compiler/dart2js/model/cfe_constant_test.dart
@@ -52,7 +52,7 @@
KernelFrontendStrategy frontendStrategy = compiler.frontendStrategy;
KernelToElementMapImpl elementMap = frontendStrategy.elementMap;
ir.Member node = elementMap.getMemberNode(member);
- new ConstantDataExtractor(compiler.reporter, actualMap, elementMap)
+ new ConstantDataExtractor(compiler.reporter, actualMap, elementMap, member)
.run(node);
}
@@ -75,15 +75,17 @@
/// IR visitor for computing inference data for a member.
class ConstantDataExtractor extends IrDataExtractor<String> {
final KernelToElementMapImpl elementMap;
+ final MemberEntity member;
ConstantDataExtractor(DiagnosticReporter reporter,
- Map<Id, ActualData<String>> actualMap, this.elementMap)
+ Map<Id, ActualData<String>> actualMap, this.elementMap, this.member)
: super(reporter, actualMap);
@override
String computeNodeValue(Id id, ir.TreeNode node) {
if (node is ir.ConstantExpression) {
- return constantToText(elementMap.getConstantValue(node));
+ return constantToText(elementMap.getConstantValue(
+ elementMap.getStaticTypeContext(member), node));
}
return null;
}
diff --git a/tests/compiler/dart2js/model/type_substitution_test.dart b/tests/compiler/dart2js/model/type_substitution_test.dart
index 35730ab..85c5784 100644
--- a/tests/compiler/dart2js/model/type_substitution_test.dart
+++ b/tests/compiler/dart2js/model/type_substitution_test.dart
@@ -121,24 +121,24 @@
""");
InterfaceType Class_T_S = env["Class"];
Expect.isNotNull(Class_T_S);
- Expect.isTrue(Class_T_S.isInterfaceType);
+ Expect.isTrue(Class_T_S is InterfaceType);
Expect.equals(2, Class_T_S.typeArguments.length);
DartType T = Class_T_S.typeArguments[0];
Expect.isNotNull(T);
- Expect.isTrue(T.isTypeVariable);
+ Expect.isTrue(T is TypeVariableType);
DartType S = Class_T_S.typeArguments[1];
Expect.isNotNull(S);
- Expect.isTrue(S.isTypeVariable);
+ Expect.isTrue(S is TypeVariableType);
DartType intType = env['int'];
Expect.isNotNull(intType);
- Expect.isTrue(intType.isInterfaceType);
+ Expect.isTrue(intType is InterfaceType);
DartType StringType = env['String'];
Expect.isNotNull(StringType);
- Expect.isTrue(StringType.isInterfaceType);
+ Expect.isTrue(StringType is InterfaceType);
ClassEntity ListClass = env.getElement('List');
ClassEntity MapClass = env.getElement('Map');
diff --git a/tests/compiler/dart2js/rti/emission/future_or_as_type_argument.dart b/tests/compiler/dart2js/rti/emission/future_or_as_type_argument.dart
index 402f2bc..837f824 100644
--- a/tests/compiler/dart2js/rti/emission/future_or_as_type_argument.dart
+++ b/tests/compiler/dart2js/rti/emission/future_or_as_type_argument.dart
@@ -9,7 +9,7 @@
/*class: A:checkedInstance,checks=[],instance*/
class A<T> {}
-/*class: B:checks=[],typeArgument*/
+/*class: B:checkedTypeArgument,checks=[],typeArgument*/
class B {}
/*class: C:checks=[],typeArgument*/
diff --git a/tests/compiler/dart2js/rti/emission/future_or_type_argument.dart b/tests/compiler/dart2js/rti/emission/future_or_type_argument.dart
index 374a758..756d26f 100644
--- a/tests/compiler/dart2js/rti/emission/future_or_type_argument.dart
+++ b/tests/compiler/dart2js/rti/emission/future_or_type_argument.dart
@@ -10,7 +10,7 @@
/*class: A:checkedInstance,checks=[],instance*/
class A<T> {}
-/*class: B:checks=[],typeArgument*/
+/*class: B:checkedTypeArgument,checks=[],typeArgument*/
class B {}
/*class: C:checks=[],typeArgument*/
diff --git a/tests/compiler/dart2js/rti/rti_need_test_helper.dart b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
index 1514c94..32be3c8 100644
--- a/tests/compiler/dart2js/rti/rti_need_test_helper.dart
+++ b/tests/compiler/dart2js/rti/rti_need_test_helper.dart
@@ -204,6 +204,12 @@
bool visitType(DartType type, _) => false;
@override
+ bool visitLegacyType(LegacyType type, _) => visit(type.baseType, _);
+
+ @override
+ bool visitNullableType(NullableType type, _) => visit(type.baseType, _);
+
+ @override
bool visitInterfaceType(InterfaceType type, _) {
if (type.element == entity) return true;
return visitTypes(type.typeArguments);
diff --git a/tests/compiler/dart2js/static_type/static_type_test.dart b/tests/compiler/dart2js/static_type/static_type_test.dart
index c546b5f..ae9d9de 100644
--- a/tests/compiler/dart2js/static_type/static_type_test.dart
+++ b/tests/compiler/dart2js/static_type/static_type_test.dart
@@ -32,13 +32,14 @@
class StaticTypeDataComputer extends DataComputer<String> {
ir.TypeEnvironment _typeEnvironment;
- ir.TypeEnvironment getTypeEnvironment(KernelToElementMapImpl elementMap) {
+ ir.StaticTypeContext getStaticTypeContext(
+ KernelToElementMapImpl elementMap, ir.Member node) {
if (_typeEnvironment == null) {
ir.Component component = elementMap.env.mainComponent;
_typeEnvironment = new ir.TypeEnvironment(
new ir.CoreTypes(component), new ir.ClassHierarchy(component));
}
- return _typeEnvironment;
+ return new ir.StaticTypeContext(node, _typeEnvironment);
}
/// Compute type inference data for [member] from kernel based inference.
@@ -56,9 +57,11 @@
compiler.reporter,
actualMap,
new CachedStaticType(
- getTypeEnvironment(elementMap),
+ getStaticTypeContext(elementMap, node),
staticTypeCache,
- new ThisInterfaceType.from(node.enclosingClass?.thisType)))
+ new ThisInterfaceType.from(node.enclosingClass?.getThisType(
+ _typeEnvironment.coreTypes,
+ node.enclosingLibrary.nonNullable))))
.run(node);
}
diff --git a/tests/compiler/dart2js_extra/empty_negative_test.dart b/tests/compiler/dart2js_extra/empty_negative_test.dart
deleted file mode 100644
index 8b13789..0000000
--- a/tests/compiler/dart2js_extra/empty_negative_test.dart
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/tests/compiler/dart2js_extra/timer_negative_test.dart b/tests/compiler/dart2js_extra/timer_negative_test.dart
deleted file mode 100644
index 8d5c850..0000000
--- a/tests/compiler/dart2js_extra/timer_negative_test.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2012, 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.
-
-import 'dart:isolate';
-
-import 'async_helper.dart';
-
-void test(void onDone(bool success)) {
- Duration ms = const Duration(milliseconds: 1);
- int expected = 4;
-
- void timerCallback() {
- if (--expected == 0) onDone(false);
- }
-
- new Timer(ms * 0, timerCallback);
- new Timer(ms * 10, timerCallback);
- new Timer(ms * 100, timerCallback);
- new Timer(ms * 1000, timerCallback);
-}
-
-main() {
- asyncTest(test);
-}
diff --git a/tests/corelib/apply2_test.dart b/tests/corelib/apply2_test.dart
new file mode 100644
index 0000000..4973e87
--- /dev/null
+++ b/tests/corelib/apply2_test.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2012, 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.
+
+import "package:expect/expect.dart";
+
+apply(Function function, List? positional, Map<Symbol, dynamic>? named) {
+ return Function.apply(function, positional, named);
+}
+
+void throwsNSME(
+ Function function, List? positional, Map<Symbol, dynamic>? named) {
+ Expect.throwsNoSuchMethodError(() => apply(function, positional, named));
+}
+
+main() {
+ var c1 = () => 'c1';
+ var c2 = (a) => 'c2 $a';
+ var c3 = ([a = 1]) => 'c3 $a';
+ var c4 = ({a: 1}) => 'c4 $a';
+ var c5 = ({a: 1, b: 2}) => 'c5 $a $b';
+ var c6 = ({b: 1, a: 2}) => 'c6 $a $b';
+ var c7 = (x, {b: 1, a: 2}) => 'c7 $x $a $b';
+ var c8 = (x, y, [a = 2, b = 3]) => 'c8 $x $y $a $b';
+
+ Expect.equals('c1', apply(c1, null, null));
+ Expect.equals('c1', apply(c1, [], null));
+ Expect.equals('c1', apply(c1, [], {}));
+ Expect.equals('c1', apply(c1, null, {}));
+ throwsNSME(c1, [1], null);
+ throwsNSME(c1, [1], {#a: 2});
+ throwsNSME(c1, null, {#a: 2});
+
+ Expect.equals('c2 1', apply(c2, [1], null));
+ Expect.equals('c2 1', apply(c2, [1], {}));
+ throwsNSME(c2, null, null);
+ throwsNSME(c2, [], null);
+ throwsNSME(c2, null, {});
+ throwsNSME(c2, null, {#a: 1});
+ throwsNSME(c2, [2], {#a: 1});
+
+ Expect.equals('c3 1', apply(c3, null, null));
+ Expect.equals('c3 1', apply(c3, [], null));
+ Expect.equals('c3 2', apply(c3, [2], {}));
+ throwsNSME(c3, [1, 2], null);
+ throwsNSME(c3, null, {#a: 1});
+
+ Expect.equals('c4 1', apply(c4, [], null));
+ Expect.equals('c4 2', apply(c4, [], {#a: 2}));
+ Expect.equals('c4 1', apply(c4, null, null));
+ Expect.equals('c4 1', apply(c4, [], {}));
+ throwsNSME(c4, [1], {#a: 1});
+ throwsNSME(c4, [1], {});
+ throwsNSME(c4, [], {#a: 1, #b: 2});
+
+ Expect.equals('c5 1 2', apply(c5, [], null));
+ Expect.equals('c5 3 2', apply(c5, [], {#a: 3}));
+ Expect.equals('c5 1 2', apply(c5, null, null));
+ Expect.equals('c5 1 2', apply(c5, [], {}));
+ Expect.equals('c5 3 4', apply(c5, [], {#a: 3, #b: 4}));
+ Expect.equals('c5 4 3', apply(c5, [], {#b: 3, #a: 4}));
+ Expect.equals('c5 1 3', apply(c5, [], {#b: 3}));
+ throwsNSME(c5, [1], {#a: 1});
+ throwsNSME(c5, [1], {});
+ throwsNSME(c5, [], {#a: 1, #b: 2, #c: 3});
+
+ Expect.equals('c6 2 1', apply(c6, [], null));
+ Expect.equals('c6 3 1', apply(c6, [], {#a: 3}));
+ Expect.equals('c6 2 1', apply(c6, null, null));
+ Expect.equals('c6 2 1', apply(c6, [], {}));
+ Expect.equals('c6 3 4', apply(c6, [], {#a: 3, #b: 4}));
+ Expect.equals('c6 4 3', apply(c6, [], {#b: 3, #a: 4}));
+ Expect.equals('c6 2 3', apply(c6, [], {#b: 3}));
+ throwsNSME(c6, [1], {#a: 1});
+ throwsNSME(c6, [1], {});
+ throwsNSME(c6, [], {#a: 1, #b: 2, #c: 3});
+
+ Expect.equals('c7 7 2 1', apply(c7, [7], null));
+ Expect.equals('c7 7 3 1', apply(c7, [7], {#a: 3}));
+ Expect.equals('c7 7 2 1', apply(c7, [7], {}));
+ Expect.equals('c7 7 3 4', apply(c7, [7], {#a: 3, #b: 4}));
+ Expect.equals('c7 7 4 3', apply(c7, [7], {#b: 3, #a: 4}));
+ Expect.equals('c7 7 2 3', apply(c7, [7], {#b: 3}));
+ throwsNSME(c7, [], {#a: 1});
+ throwsNSME(c7, [], {});
+ throwsNSME(c7, [7], {#a: 1, #b: 2, #c: 3});
+
+ Expect.equals('c8 7 8 2 3', apply(c8, [7, 8], null));
+ Expect.equals('c8 7 8 2 3', apply(c8, [7, 8], {}));
+ Expect.equals('c8 7 8 3 3', apply(c8, [7, 8, 3], null));
+ Expect.equals('c8 7 8 3 4', apply(c8, [7, 8, 3, 4], null));
+ throwsNSME(c8, [], null);
+ throwsNSME(c8, [], {});
+ throwsNSME(c8, [1], null);
+ throwsNSME(c8, [7, 8, 9, 10, 11], null);
+}
diff --git a/tests/corelib/apply3_test.dart b/tests/corelib/apply3_test.dart
new file mode 100644
index 0000000..5bf1bce
--- /dev/null
+++ b/tests/corelib/apply3_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, 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.
+
+// Test [Function.apply] on user-defined classes that implement [noSuchMethod].
+
+import "package:expect/expect.dart";
+
+class F {
+ call([p1]) => "call";
+ noSuchMethod(Invocation invocation) => "NSM";
+}
+
+class G {
+ call() => '42';
+ noSuchMethod(Invocation invocation) => invocation;
+}
+
+class H {
+ call(required, {a}) => required + a;
+}
+
+main() {
+ Expect.equals('call', Function.apply(new F(), []));
+ Expect.equals('call', Function.apply(new F(), [1]));
+ Expect.throwsNoSuchMethodError(() => Function.apply(new F(), [1, 2]));
+ Expect.throwsNoSuchMethodError(() => Function.apply(new F(), [1, 2, 3]));
+
+ Expect.throwsNoSuchMethodError(() => Function.apply(new G(), [1], {#a: 42}));
+
+ // Test that [i] can be used to hit an existing method.
+ Expect.equals(43, new H().call(1, a: 42));
+ Expect.equals(43, Function.apply(new H(), [1], {#a: 42}));
+}
diff --git a/tests/corelib/apply4_test.dart b/tests/corelib/apply4_test.dart
new file mode 100644
index 0000000..fba4b9d
--- /dev/null
+++ b/tests/corelib/apply4_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2015, 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.
+
+import "package:expect/expect.dart";
+
+// Testing Function.apply calls work correctly for arities that are not
+// otherwise present in the program (and thus might not have stubs
+// generated).
+
+class A {
+ foo(x, [y, z, a, b, c, d = 99, e, f, g, h, i, j]) => "$x $d";
+}
+
+main() {
+ var a = new A();
+ var clos = a.foo;
+ Expect.equals(Function.apply(clos, ["well"]), "well 99");
+ Expect.equals(Function.apply(clos, ["well", 0, 2, 4, 3, 6, 9, 10]), "well 9");
+}
diff --git a/tests/corelib/apply5_test.dart b/tests/corelib/apply5_test.dart
new file mode 100644
index 0000000..5435f10
--- /dev/null
+++ b/tests/corelib/apply5_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2016, 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.
+
+import "package:expect/expect.dart";
+
+// Testing that, when compiled to JS, Function.apply works correctly for
+// functions with that will be invoked directly vs using .apply().
+
+class A {
+ foo([a = 10, b = 20, c = 30, d = 40, e = 50]) => "$a $b $c $d $e";
+}
+
+main() {
+ var a = new A();
+ var clos = a.foo;
+ Expect.equals(Function.apply(clos, []), "10 20 30 40 50");
+ Expect.equals(Function.apply(clos, [11]), "11 20 30 40 50");
+ Expect.equals(Function.apply(clos, [11, 21]), "11 21 30 40 50");
+ Expect.equals(Function.apply(clos, [11, 21, 31]), "11 21 31 40 50");
+ Expect.equals(Function.apply(clos, [11, 21, 31, 41]), "11 21 31 41 50");
+ Expect.equals(Function.apply(clos, [11, 21, 31, 41, 51]), "11 21 31 41 51");
+}
diff --git a/tests/corelib/apply_generic_function_test.dart b/tests/corelib/apply_generic_function_test.dart
new file mode 100644
index 0000000..b9e6e3e
--- /dev/null
+++ b/tests/corelib/apply_generic_function_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2018, 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.
+
+import "package:expect/expect.dart";
+import "symbol_map_helper.dart";
+
+// Testing Function.apply calls correctly with generic type arguments.
+// This test is not testing error handling, only that correct parameters
+// cause a correct call.
+
+test0<T extends num>(T i, T j, {required T a}) => i + j + a;
+
+main() {
+ test(res, func, list, map) {
+ map = symbolMapToStringMap(map);
+ Expect.equals(res, Function.apply(func, list, map));
+ }
+
+ test(42, test0, [10, 15], {"a": 17});
+}
diff --git a/tests/corelib/apply_test.dart b/tests/corelib/apply_test.dart
new file mode 100644
index 0000000..0958dab
--- /dev/null
+++ b/tests/corelib/apply_test.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2012, 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.
+
+import "package:expect/expect.dart";
+import "symbol_map_helper.dart";
+
+// Testing Function.apply calls correctly.
+// This test is not testing error handling, only that correct parameters
+// cause a correct call.
+
+int test0() => 42;
+int test0a({required int a}) => 37 + a;
+int test1(int i) => i + 1;
+int test1a(int i, {required int a}) => i + a;
+int test2(int i, int j) => i + j;
+int test2a(int i, int j, {required int a}) => i + j + a;
+
+class C {
+ int x = 10;
+ int foo(int y) => this.x + y;
+}
+
+class Callable {
+ int call(int x, int y) => x + y;
+}
+
+@pragma('dart2js:noInline')
+@pragma('dart2js:assumeDynamic')
+confuse(x) => x;
+
+main() {
+ testMap(res, func, map) {
+ Expect.equals(res, Function.apply(func, null, map));
+ Expect.equals(res, Function.apply(func, [], map));
+ }
+
+ testList(res, func, list) {
+ Expect.equals(res, Function.apply(func, list));
+ Expect.equals(res, Function.apply(func, list, null));
+ Expect.equals(res, Function.apply(func, list, new Map<Symbol, dynamic>()));
+ }
+
+ testListTyped(res, Function func, list) => testList(res, func, list);
+
+ test(res, func, list, map) {
+ Expect.equals(res, Function.apply(func, list, map));
+ }
+
+ testList(42, test0, null);
+ testList(42, test0, []);
+ testMap(42, test0a, {#a: 5});
+ testList(42, test1, [41]);
+ test(42, test1a, [20], {#a: 22});
+ testList(42, test2, [20, 22]);
+ test(42, test2a, [10, 15], {#a: 17});
+
+ // Test that "this" is correct when calling closurized functions.
+ var cfoo = new C().foo;
+ testList(42, cfoo, [32]);
+
+ // Test that apply works even with a different name.
+ var app = confuse(Function.apply);
+ Expect.equals(42, app(test2, [22, 20]));
+
+ // Test that apply can itself be applied.
+ Expect.equals(
+ 42,
+ Function.apply(Function.apply, [
+ test2,
+ [17, 25]
+ ]));
+
+ // Test that apply works on callable objects when it is passed to a method
+ // that expects Function (and not dynamic).
+ Expect.throws(() => testList(42, new Callable(), [13, 29])); //# 01: ok
+ testListTyped(42, new Callable(), [13, 29]); //# 02: ok
+}
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
new file mode 100644
index 0000000..834728b
--- /dev/null
+++ b/tests/corelib/corelib.status
@@ -0,0 +1,61 @@
+# Copyright (c) 2017, 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.
+
+[ $compiler == dartdevk ]
+regexp/lookbehind_test/01: Skip # Flaky in uncatchable way. Issue 36280
+
+[ $mode == debug ]
+regexp/pcre_test: Slow # Issue 22008
+
+[ $arch == x64 && $system == windows ]
+stopwatch_test: Skip # Flaky test due to expected performance behaviour.
+
+[ $builder_tag == obfuscated && $runtime == dart_precompiled ]
+apply_generic_function_test: SkipByDesign # Function.apply with named args
+apply_test: Skip # Uses new Symbol via symbolMapToStringMap helper
+dynamic_nosuchmethod_test: SkipByDesign # Expects names in NSM
+error_stack_trace1_test: SkipByDesign # Expects unobfuscated stack trace
+type_tostring_test: SkipByDesign # Expects names in Type.toString()
+
+[ $compiler != dart2analyzer && $compiler != dart2js && $compiler != dartdevc && $compiler != dartdevk ]
+bigint_js_test: SkipByDesign # JavaScript-specific test
+
+[ $compiler == dart2js && $runtime != none ]
+regexp/pcre_test: Slow # Issue 21593
+
+# We no longer expect Dart2 tests to run with the standalone VM without the new
+# common front end, but for now we get better coverage by still running them in
+# checked mode, which is mostly Dart2-compatible.
+[ $compiler == none && !$checked && ($runtime == dart_precompiled || $runtime == vm) ]
+*: SkipByDesign
+
+[ $runtime != none && ($compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk) ]
+int_parse_with_limited_ints_test: Skip # Requires fixed-size int64 support.
+typed_data_with_limited_ints_test: Skip # Requires fixed-size int64 support.
+
+[ $arch == simarm || $arch == simarm64 ]
+bigint_parse_radix_test: Skip # Issue 31659
+bigint_test: Skip # Issue 31659
+
+[ $compiler == dartdevc || $compiler == dartdevk ]
+bigint_test/03: SkipSlow # modPow is very slow
+bigint_test/15: SkipSlow # modPow is very slow
+int_parse_with_limited_ints_test: Skip # Requires fixed-size int64 support.
+typed_data_with_limited_ints_test: Skip # Requires fixed-size int64 support.
+uri_parse_test: Slow
+uri_test: Slow
+
+[ $compiler == dartkb || $compiler == dartkp ]
+bigint_parse_radix_test: Slow # --no_intrinsify
+bigint_test/03: SkipSlow # --no_intrinsify
+bigint_test/15: SkipSlow # --no_intrinsify
+
+[ $runtime == dart_precompiled || $runtime == vm ]
+regexp/global_test: Skip # Issue 21709
+regexp/pcre_test: Slow
+
+[ $hot_reload || $hot_reload_rollback ]
+bigint_parse_radix_test: Skip # Issue 31659. Issue 34361.
+bigint_test: Skip # Issue 31659
+integer_parsed_mul_div_vm_test: Slow # Slow
diff --git a/tests/corelib_2/date_time_parse_test.dart b/tests/corelib_2/date_time_parse_test.dart
index 6b3d58d..23b8b02 100644
--- a/tests/corelib_2/date_time_parse_test.dart
+++ b/tests/corelib_2/date_time_parse_test.dart
@@ -17,14 +17,14 @@
check(new DateTime(2012, 02, 27, 13, 27), "2012-02-27 13:27:00");
if (supportsMicroseconds) {
check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
- "2012-02-27 13:27:00.123456z");
+ "2012-02-27 13:27:00.1234567891234z");
check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
- "2012-02-27 13:27:00,123456z");
+ "2012-02-27 13:27:00,1234567891234z");
} else {
- check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
- "2012-02-27 13:27:00.123z");
- check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
- "2012-02-27 13:27:00,123z");
+ check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 0),
+ "2012-02-27 13:27:00.1234567891234z");
+ check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 0),
+ "2012-02-27 13:27:00,1234567891234z");
}
check(new DateTime(2012, 02, 27, 13, 27), "20120227 13:27:00");
check(new DateTime(2012, 02, 27, 13, 27), "20120227T132700");
diff --git a/tests/language/aborting_switch_case_test.dart b/tests/language/aborting_switch_case_test.dart
new file mode 100644
index 0000000..b8c7fe4
--- /dev/null
+++ b/tests/language/aborting_switch_case_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, 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.
+
+// Regression test for dart2js that used to be confused when inlining
+// method that always aborts in a switch case.
+
+import "package:expect/expect.dart";
+
+foo() {
+ throw 42;
+}
+
+main() {
+ var exception;
+ try {
+ switch (42) {
+ case 42:
+ foo();
+ foo();
+ break;
+ }
+ } catch (e) {
+ exception = e;
+ }
+ Expect.equals(42, exception);
+}
diff --git a/tests/language/abstract_beats_arguments_test.dart b/tests/language/abstract_beats_arguments_test.dart
new file mode 100644
index 0000000..d6687b4
--- /dev/null
+++ b/tests/language/abstract_beats_arguments_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2015, 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.
+
+import "package:expect/expect.dart";
+
+// TODO(rnystrom): This test should be renamed since now it's just about
+// testing that constructing an abstract class generates an error.
+
+abstract class A {
+ A() {}
+}
+
+void main() {
+ /*@compile-error=unspecified*/ new A();
+}
diff --git a/tests/language/abstract_equal_test.dart b/tests/language/abstract_equal_test.dart
new file mode 100644
index 0000000..bcfb3e8
--- /dev/null
+++ b/tests/language/abstract_equal_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, 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.
+
+class A {
+ bool operator ==(other);
+ const A();
+}
+
+class B implements A {
+ const B();
+}
+
+class C extends A {
+ const C();
+}
+
+class Invalid {
+ bool operator ==(other) => false;
+ const Invalid();
+}
+
+class D implements Invalid {
+ const D();
+}
+
+main() {
+ print(const {A(): 1});
+ print(const {B(): 2});
+ print(const {C(): 3});
+ print(const {D(): 4});
+}
diff --git a/tests/language/abstract_exact_selector_test.dart b/tests/language/abstract_exact_selector_test.dart
new file mode 100644
index 0000000..a35adda
--- /dev/null
+++ b/tests/language/abstract_exact_selector_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2013, 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.
+
+// Regression test for dart2js that used to duplicate some `Object`
+// methods to handle `noSuchMethod`.
+
+import "package:expect/expect.dart";
+import "compiler_annotations.dart";
+
+abstract //# 01: compile-time error
+ class Foo {
+ noSuchMethod(im) => 42;
+}
+
+@DontInline()
+returnFoo() {
+ (() => 42)();
+ return new Foo();
+}
+
+class Bar {
+ operator ==(other) => false;
+}
+
+var a = [false, true, new Object(), new Bar()];
+
+main() {
+ if (a[0] as bool) {
+ // This `==` call will make the compiler create a selector with an
+ // exact `TypeMask` of `Foo`. Since `Foo` is abstract, such a call
+ // cannot happen, but we still used to generate a `==` method on
+ // the `Object` class to handle `noSuchMethod`.
+ print(returnFoo() == 42);
+ } else {
+ Expect.isFalse(a[2] == 42);
+ }
+}
diff --git a/tests/language/abstract_factory_constructor_test.dart b/tests/language/abstract_factory_constructor_test.dart
new file mode 100644
index 0000000..90713ca
--- /dev/null
+++ b/tests/language/abstract_factory_constructor_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2012, 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.
+// Dart test program for constructors and initializers.
+
+// Exercises issue 2282, factory constructors in abstract classes should
+// not emit a static type warning
+
+class B extends A1 {
+ B() {}
+ method() {}
+}
+
+abstract class A1 {
+ A1() {}
+ method(); // Abstract.
+ factory A1.make() {
+ return new B();
+ }
+}
+
+class A2 {
+ // Intentionally abstract method.
+ method(); //# 00: compile-time error
+ A2.make() {}
+}
+
+main() {
+ new A1.make();
+ new A2.make(); //# 00: continued
+}
diff --git a/tests/language/abstract_getter2_test.dart b/tests/language/abstract_getter2_test.dart
new file mode 100644
index 0000000..e1240c5
--- /dev/null
+++ b/tests/language/abstract_getter2_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2016, 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.
+
+import "package:expect/expect.dart";
+
+class A {
+ int get x => 100;
+}
+
+abstract class B extends A {
+ int _x = 0;
+
+ int get x;
+ set x(int v) {
+ _x = v;
+ }
+}
+
+class C extends B {
+ int get x => super.x;
+}
+
+class GetterConcrete {
+ var _foo;
+
+ get foo => _foo;
+ set foo(x) => _foo = x;
+
+ var _bar;
+
+ get bar => _bar;
+ set bar(x) => _bar = x;
+}
+
+class AbstractGetterOverride1 extends GetterConcrete {
+ get foo;
+ set bar(x);
+}
+
+class AbstractGetterOverride2 extends Object with GetterConcrete {
+ get foo;
+ set bar(x);
+}
+
+void main() {
+ B b = new C();
+ b.x = 42;
+ Expect.equals(b._x, 42);
+ Expect.equals(b.x, 100);
+
+ /// Tests that overriding either the getter or setter with an abstract member
+ /// has no effect.
+ /// Regression test for https://github.com/dart-lang/sdk/issues/29914
+ var c1 = AbstractGetterOverride1()
+ ..foo = 123
+ ..bar = 456;
+ Expect.equals(c1.foo, 123);
+ Expect.equals(c1.bar, 456);
+
+ var c2 = AbstractGetterOverride2()
+ ..foo = 123
+ ..bar = 456;
+ Expect.equals(c2.foo, 123);
+ Expect.equals(c2.bar, 456);
+}
diff --git a/tests/language/abstract_getter_test.dart b/tests/language/abstract_getter_test.dart
new file mode 100644
index 0000000..73d43a3
--- /dev/null
+++ b/tests/language/abstract_getter_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2012, 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.
+
+import "package:expect/expect.dart";
+
+// Test to ensure that an abstract getter is not mistaken for a field.
+
+class Foo {
+ // Intentionally abstract:
+ get i; //# 01: compile-time error
+}
+
+class Bar {}
+
+checkIt(f) {
+ Expect.throwsNoSuchMethodError(() => f.i = 'hi'); // //# 01: continued
+ Expect.throwsNoSuchMethodError(() => print(f.i)); // //# 01: continued
+ Expect.throwsNoSuchMethodError(() => print(f.i())); // //# 01: continued
+}
+
+main() {
+ checkIt(new Foo());
+ checkIt(new Bar());
+}
diff --git a/tests/language/abstract_method_test.dart b/tests/language/abstract_method_test.dart
new file mode 100644
index 0000000..4532789
--- /dev/null
+++ b/tests/language/abstract_method_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2014, 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.
+
+import "package:expect/expect.dart";
+
+// Checks that abstract instance methods are correctly resolved.
+
+int get length => throw "error: top-level getter called";
+set height(x) {
+ throw "error: top-level setter called";
+}
+
+width() {
+ throw "error: top-level function called";
+}
+
+abstract class A {
+ int get length; // Abstract instance getter.
+ set height(int x); // Abstract instance setter.
+ int width(); // Abstract instance method.
+
+ // Must resolve to non-abstract length getter in subclass.
+ get useLength => length;
+ // Must resolve to non-abstract height setter in subclass.
+ setHeight(x) => height = x;
+ // Must resolve to non-abstract width() method in subclass.
+ useWidth() => width();
+}
+
+class A1 extends A {
+ int length; // Implies a length getter.
+ int? height; // Implies a height setter.
+ int width() => 345;
+ A1(this.length);
+}
+
+main() {
+ var a = new A1(123);
+ Expect.equals(123, a.useLength);
+ a.setHeight(234);
+ Expect.equals(234, a.height);
+ Expect.equals(345, a.useWidth());
+ print([a.useLength, a.height, a.useWidth()]);
+}
diff --git a/tests/language/abstract_object_method_test.dart b/tests/language/abstract_object_method_test.dart
new file mode 100644
index 0000000..2d4af77c
--- /dev/null
+++ b/tests/language/abstract_object_method_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2013, 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.
+
+import "package:expect/expect.dart";
+
+class A {
+ noSuchMethod(_) {
+ Expect.fail('Should not reach here');
+ }
+}
+
+class B extends A {
+ operator ==(other);
+}
+
+class C extends B {}
+
+var a = [new C()];
+
+main() {
+ C c = a[0];
+ a.add(c);
+ Expect.isTrue(c == a[1]);
+}
diff --git a/tests/language/abstract_override_adds_optional_args_concrete_subclass_test.dart b/tests/language/abstract_override_adds_optional_args_concrete_subclass_test.dart
new file mode 100644
index 0000000..12a023f
--- /dev/null
+++ b/tests/language/abstract_override_adds_optional_args_concrete_subclass_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2017, 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.
+
+class A {
+ void foo() {}
+}
+
+abstract class B extends A {
+ // If this class were concrete, there would be a problem, since `new
+ // B().foo(42)` would be statically allowed, but would lead to invalid
+ // arguments being passed to A.foo. But since the class is abstract, there is
+ // no problem.
+ void foo([x]);
+}
+
+class /*@compile-error=unspecified*/ C extends B {
+ // However, there is a problem here because this class is concrete and doesn't
+ // override foo.
+}
+
+void f(B b) {
+ b.foo();
+}
+
+main() {
+ f(new C());
+}
diff --git a/tests/language/abstract_override_adds_optional_args_concrete_test.dart b/tests/language/abstract_override_adds_optional_args_concrete_test.dart
new file mode 100644
index 0000000..b8232e8
--- /dev/null
+++ b/tests/language/abstract_override_adds_optional_args_concrete_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2017, 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.
+
+class A {
+ void foo() {}
+}
+
+class B extends A {
+ // This class declaration violates soundness, since it allows `new
+ // B().foo(42)`, which would lead to invalid arguments being passed to A.foo.
+ void /*@compile-error=unspecified*/ foo([x]);
+}
+
+void f(B b) {
+ b.foo();
+}
+
+main() {
+ f(new B());
+}
diff --git a/tests/language/abstract_override_adds_optional_args_supercall_test.dart b/tests/language/abstract_override_adds_optional_args_supercall_test.dart
new file mode 100644
index 0000000..2a2bf3e
--- /dev/null
+++ b/tests/language/abstract_override_adds_optional_args_supercall_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2017, 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.
+
+class A {
+ void foo() {}
+}
+
+abstract class B extends A {
+ // If this class were concrete, there would be a problem, since `new
+ // B().foo(42)` would be statically allowed, but would lead to invalid
+ // arguments being passed to A.foo. But since the class is abstract, there is
+ // no problem.
+ void foo([x]);
+}
+
+class C extends B {
+ void foo([x]) {
+ // But it is a problem to try to pass `x` along to super, since the super
+ // method is A.foo.
+ super.foo(/*@compile-error=unspecified*/ x);
+ }
+}
+
+void f(B b) {
+ b.foo(42);
+}
+
+main() {
+ f(new C());
+}
diff --git a/tests/language/abstract_override_adds_optional_args_test.dart b/tests/language/abstract_override_adds_optional_args_test.dart
new file mode 100644
index 0000000..d139307
--- /dev/null
+++ b/tests/language/abstract_override_adds_optional_args_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2017, 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.
+
+// This test exercises a corner case of override checking that is safe from a
+// soundness perspective, but which we haven't decided whether or not to allow
+// from a usability perspective.
+
+class A {
+ void foo() {}
+}
+
+abstract class B extends A {
+ // If this class were concrete, there would be a problem, since `new
+ // B().foo(42)` would be statically allowed, but would lead to invalid
+ // arguments being passed to A.foo. But since the class is abstract, there is
+ // no problem.
+ void foo([x]);
+}
+
+class C extends B {
+ void foo([x]) {
+ super.foo();
+ }
+}
+
+void f(B b) {
+ b.foo(42);
+}
+
+main() {
+ f(new C());
+}
diff --git a/tests/language/abstract_syntax_test.dart b/tests/language/abstract_syntax_test.dart
new file mode 100644
index 0000000..fba3725
--- /dev/null
+++ b/tests/language/abstract_syntax_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2012, 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.
+
+import "package:expect/expect.dart";
+
+main() {
+ var b = new B();
+ Expect.equals(42, b.foo());
+}
+
+class A {
+ foo(); // //# 00: compile-time error
+ static bar(); // //# 01: syntax error
+}
+
+class B extends A {
+ foo() => 42;
+ bar() => 87;
+}
diff --git a/tests/language/compiler_annotations.dart b/tests/language/compiler_annotations.dart
new file mode 100644
index 0000000..c920add
--- /dev/null
+++ b/tests/language/compiler_annotations.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2013, 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.
+
+library compiler_annotations;
+
+// This library contains annotations useful for testing.
+
+// TODO(ngeoffray): Implement in dart2js.
+class DontInline {
+ const DontInline();
+}
diff --git a/tests/language/language.status b/tests/language/language.status
new file mode 100644
index 0000000..796193b
--- /dev/null
+++ b/tests/language/language.status
@@ -0,0 +1,46 @@
+# Copyright (c) 2017, 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.
+
+[ $compiler != dart2analyzer ]
+switch_case_warn_test: Skip # Analyzer only, see language_analyzer2.status
+
+[ $compiler != fasta ]
+nonfunction_type_aliases/*: Skip # github.com/dart-lang/language/issues/115
+
+[ $compiler == none ]
+invalid_returns/*: Skip # https://github.com/dart-lang/sdk/issues/34013
+void/*: Skip # https://github.com/dart-lang/sdk/issues/34013
+
+[ $compiler == spec_parser ]
+double_literals/*: Skip # https://github.com/dart-lang/sdk/issues/34355
+invalid_returns/*: Skip # https://github.com/dart-lang/sdk/issues/34015
+mixin_declaration/*: Skip # See https://github.com/dart-lang/language/issues/7
+void/*: Skip # https://github.com/dart-lang/sdk/issues/34015
+
+[ $mode == debug ]
+large_class_declaration_test: Slow
+
+[ $mode == product ]
+assertion_test: SkipByDesign # Requires checked mode.
+generic_test: SkipByDesign # Requires checked mode.
+issue13474_test: SkipByDesign # Requires checked mode.
+map_literal4_test: SkipByDesign # Requires checked mode.
+named_parameters_type_test/01: SkipByDesign # Requires checked mode.
+named_parameters_type_test/02: SkipByDesign # Requires checked mode.
+named_parameters_type_test/03: SkipByDesign # Requires checked mode.
+positional_parameters_type_test/01: SkipByDesign # Requires checked mode.
+positional_parameters_type_test/02: SkipByDesign # Requires checked mode.
+regress_29784_test/02: SkipByDesign # Requires checked mode.
+stacktrace_demangle_ctors_test: SkipByDesign # Names are not scrubbed.
+type_checks_in_factory_method_test: SkipByDesign # Requires checked mode.
+
+[ $compiler != dart2js && $compiler != dartdevc && !$checked ]
+function_type/*: Skip # Needs checked mode.
+
+[ $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $mode == debug && $runtime == vm ]
+built_in_identifier_type_annotation_test/set: Crash # Not supported by legacy VM front-end.
+
+[ $hot_reload || $hot_reload_rollback ]
+issue_22780_test/01: Crash # Issue 29094
+vm/optimized_stacktrace_test: Slow
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
new file mode 100644
index 0000000..372d94b
--- /dev/null
+++ b/tests/language/language_analyzer.status
@@ -0,0 +1,11 @@
+# Copyright (c) 2017, 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.
+
+# Sections in this file should contain "$compiler == dart2analyzer".
+
+[ $compiler == dart2analyzer ]
+large_class_declaration_test: Slow
+vm/debug_break_enabled_vm_test: Skip
+vm/debug_break_vm_test/*: Skip
+vm/regress_27201_test: SkipByDesign # Loads bad library, so will always crash.
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
new file mode 100644
index 0000000..64bc2b8
--- /dev/null
+++ b/tests/language/language_dart2js.status
@@ -0,0 +1,31 @@
+# Copyright (c) 2017, 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.
+# Sections in this file should contain "$compiler == dart2js".
+
+[ $compiler == dart2js ]
+mixin_method_override_test/G5: Skip # Issue 34354
+vm/*: SkipByDesign # Tests for the VM.
+
+[ $compiler != dart2js ]
+minify_closure_variable_collision_test: SkipByDesign # Regression test for dart2js
+
+[ $builder_tag == dart2js_production && $compiler == dart2js ]
+control_flow_collections/for_non_bool_condition_test: Crash # Issue 36442
+
+[ $compiler == dart2js && $runtime == chromeOnAndroid ]
+override_field_test/02: Slow # TODO(kasperl): Please triage.
+
+[ $compiler == dart2js && $runtime == d8 ]
+conditional_import_string_test: SkipByDesign # No XHR in d8
+conditional_import_test: SkipByDesign # No XHR in d8
+
+[ $compiler == dart2js && $runtime == jsshell ]
+await_for_test: Skip # Jsshell does not provide periodic timers, Issue 7728
+
+[ $compiler == dart2js && $system == windows ]
+canonicalization_hashing_memoize_array_test: Skip # Issue 37631
+canonicalization_hashing_memoize_instance_test: Skip # Issue 37631
+canonicalization_hashing_shallow_collision_array_test: Skip # Issue 37631
+canonicalization_hashing_shallow_collision_instance_test: Skip # Issue 37631
+
diff --git a/tests/language/language_dartdevc.status b/tests/language/language_dartdevc.status
new file mode 100644
index 0000000..1aed49b
--- /dev/null
+++ b/tests/language/language_dartdevc.status
@@ -0,0 +1,23 @@
+# Copyright (c) 2017, 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.
+
+# Sections in this file should contain "$compiler == dartdevc" or dartdevk.
+[ $compiler == dartdevc ]
+const_double_in_int_op_test/dd6: Skip # Triple shift
+const_double_in_int_op_test/di6: Skip # Triple shift
+const_double_in_int_op_test/id6: Skip # Triple shift
+const_double_in_int_op_test/ii6: Skip # Triple shift
+extension_methods/*: SkipByDesign # Analyzer DDC is expected to be turned down before releasing extension methods.
+large_class_declaration_test: Slow
+nnbd/*: Skip
+variance/*: SkipByDesign # Analyzer DDC is expected to be turned down before releasing variance.
+
+[ $compiler == dartdevk && !$checked ]
+assertion_initializer_const_error2_test/*: SkipByDesign # DDC does not support non-checked mode.
+
+[ $compiler == dartdevc || $compiler == dartdevk ]
+asyncstar_throw_in_catch_test: Skip # Times out. Issue 29920
+int64_literal_test/*: Skip # This is testing Dart 2.0 int64 semantics.
+superinterface_variance/*: Skip # Issue dart-lang/language#113
+vm/*: SkipByDesign # VM only tests.; VM only tests.
diff --git a/tests/language/language_kernel.status b/tests/language/language_kernel.status
new file mode 100644
index 0000000..9b43134
--- /dev/null
+++ b/tests/language/language_kernel.status
@@ -0,0 +1,152 @@
+# Copyright (c) 2017, 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.
+
+
+[ $compiler == app_jitk ]
+no_main_test/01: Crash
+vm/regress_27671_test: SkipByDesign # Relies on string comparison of exception message which may return '<optimized out>'
+web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
+
+[ $compiler == dartkp ]
+web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
+
+[ $compiler == fasta ]
+async_await_syntax_test/e5: Crash # Assertion error: continuation.dart: Failed assertion: 'node.expression == null || node.expression is NullLiteral': is not true.
+async_await_syntax_test/e6: Crash # Assertion error: continuation.dart: Failed assertion: 'node.expression == null || node.expression is NullLiteral': is not true.
+web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
+
+[ $fasta ]
+nnbd/*: Skip
+superinterface_variance/abstract_class_error_test/27: Crash # Issue dart-lang/language#113
+superinterface_variance/concrete_class_error_test/27: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/27: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/37: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/38: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/40: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/41: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/42: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/43: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/44: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/46: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/47: Crash # Issue dart-lang/language#113
+superinterface_variance/mixin_error_test/48: Crash # Issue dart-lang/language#113
+
+[ $builder_tag == obfuscated && $compiler == dartkp ]
+generic_function_dcall_test/01: SkipByDesign # Prints type names
+many_named_arguments_test: SkipByDesign # Checks names of arguments
+mixin_generic_test: SkipByDesign # Prints type names
+mixin_mixin3_test: SkipByDesign # Prints type names
+mixin_mixin5_test: SkipByDesign # Prints type names
+mixin_mixin6_test: SkipByDesign # Prints type names
+mixin_mixin_bound2_test: SkipByDesign # Prints type names
+symbol_literal_test/02: SkipByDesign # We don't obfuscate const Symbol constructor
+type_literal_test: SkipByDesign # Uses lots of strings with type names in them
+vm/bool_check_stack_traces_test: SkipByDesign # Looks for filenames in stacktrace output
+vm/no_such_args_error_message_vm_test: SkipByDesign # Looks for function name in error message
+vm/no_such_method_error_message_callable_vm_test: SkipByDesign # Expects unobfuscated method names
+vm/no_such_method_error_message_vm_test: SkipByDesign # Looks for unobfuscated name in error message
+vm/regress_28325_test: SkipByDesign # Looks for filename in stack trace
+
+[ $compiler == dartk && $mode == debug && ($hot_reload || $hot_reload_rollback) ]
+inference_enum_list_test: Skip # Issue 35885
+
+[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
+vm/precompiled_static_initializer_test: Slow
+
+# ==== dartkp + dart_precompiled status lines ====
+[ $compiler == dartkp && $runtime == dart_precompiled ]
+assert_with_type_test_or_cast_test: Crash
+const_evaluation_test: SkipByDesign
+ct_const2_test: Skip # Incompatible flag: --compile_all
+deferred_redirecting_factory_test: Crash # Issue 23408, KernelVM bug: Deferred loading kernel issue 30273.
+deopt_inlined_function_lazy_test: Skip # Incompatible flag: --deoptimize-alot
+enum_mirror_test: SkipByDesign
+export_ambiguous_main_test: Skip # Issue 29895 Fail Issue 14763
+export_double_same_main_test: Skip # Issue 29895 Crash Issue 29895
+field_increment_bailout_test: SkipByDesign
+generic_methods_recursive_bound_test/03: Crash
+hello_dart_test: Skip # Incompatible flag: --compile_all
+implicit_closure_test: Skip # Incompatible flag: --use_slow_path
+instance_creation_in_function_annotation_test: SkipByDesign
+invocation_mirror2_test: SkipByDesign
+invocation_mirror_invoke_on2_test: SkipByDesign
+invocation_mirror_invoke_on_test: SkipByDesign
+issue21079_test: SkipByDesign
+main_not_a_function_test: Skip
+many_overridden_no_such_method_test: SkipByDesign
+mixin_illegal_super_use_test: Skip # Issues 24478 and 23773
+mixin_illegal_superclass_test: Skip # Issues 24478 and 23773
+no_main_test/01: Skip
+no_such_method_test: SkipByDesign
+null_test/mirrors: Skip # Uses mirrors.
+null_test/none: SkipByDesign
+overridden_no_such_method_test: SkipByDesign
+redirecting_factory_reflection_test: SkipByDesign
+regress_13462_0_test: SkipByDesign
+regress_13462_1_test: SkipByDesign
+regress_18535_test: SkipByDesign
+regress_28255_test: SkipByDesign
+vm/causal_async_exception_stack2_test: SkipByDesign
+vm/causal_async_exception_stack_test: SkipByDesign
+vm/closure_memory_retention_test: Skip # KernelVM bug: Hits OOM
+vm/reflect_core_vm_test: SkipByDesign
+vm/regress_27671_test: Skip # Unsupported
+vm/regress_29145_test: Skip # Issue 29145
+
+[ $compiler == dartkp && $runtime == dart_precompiled && $checked ]
+assertion_initializer_const_error2_test/cc01: Crash
+assertion_initializer_const_error2_test/cc02: Crash
+assertion_initializer_const_error2_test/cc03: Crash
+assertion_initializer_const_error2_test/cc04: Crash
+assertion_initializer_const_error2_test/cc05: Crash
+assertion_initializer_const_error2_test/cc06: Crash
+assertion_initializer_const_error2_test/cc07: Crash
+assertion_initializer_const_error2_test/cc08: Crash
+assertion_initializer_const_error2_test/cc09: Crash
+assertion_initializer_const_error2_test/cc10: Crash
+assertion_initializer_const_error2_test/cc11: Crash
+
+[ $compiler == dartkp && $system == windows ]
+disassemble_test: Slow
+
+[ $mode == debug && $runtime == vm && ($compiler == app_jitk || $compiler == dartk || $compiler == dartkb) ]
+deopt_inlined_function_lazy_test: Skip
+
+[ $mode == debug && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
+async_star_test/01: Crash
+async_star_test/05: Crash
+
+[ $mode == debug && ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
+enum_duplicate_test/02: Crash # Issue 34606
+enum_duplicate_test/none: Crash # Issue 34606
+enum_private_test/01: Crash # Issue 34606
+enum_test: Crash # Issue 34606
+
+[ $mode == product && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+vm/causal_async_exception_stack2_test: SkipByDesign
+vm/causal_async_exception_stack_test: SkipByDesign
+
+# ===== dartk + vm status lines =====
+[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+ct_const2_test: Crash # Flaky
+disassemble_test: Slow, Crash # dartbug.com/34971
+mixin_illegal_super_use_test: Skip # Issues 24478 and 23773
+mixin_illegal_superclass_test: Skip # Issues 24478 and 23773
+no_main_test/01: Skip
+vm/closure_memory_retention_test: Skip # KernelVM bug: Hits OOM
+vm/regress_29145_test: Skip # Issue 29145
+web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
+
+[ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
+symbol_conflict_test: Slow
+
+[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
+async_star_test/01: Skip # Timeout
+async_star_test/02: Skip # Timeout
+async_star_test/03: Skip # Timeout
+async_star_test/04: Skip # Timeout
+async_star_test/05: Skip # Timeout
+async_star_test/none: Skip # Timeout
+type_constants_test/none: Skip # Deferred libraries and hot reload.
+
diff --git a/tests/language/language_precompiled.status b/tests/language/language_precompiled.status
new file mode 100644
index 0000000..d7e999b
--- /dev/null
+++ b/tests/language/language_precompiled.status
@@ -0,0 +1,44 @@
+# Copyright (c) 2017, 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.
+# Sections in this file should start with "$runtime == dart_precompiled".
+
+[ $arch == arm64 && $runtime == dart_precompiled ]
+large_class_declaration_test: SkipSlow # Uses too much memory.
+setter4_test: MissingCompileTimeError
+
+[ $arch == ia32 && $runtime == dart_precompiled ]
+vm/regress_24517_test: Pass, Fail # Issue 24517.
+
+[ $compiler != dart2analyzer && $runtime == dart_precompiled ]
+mixin_mixin2_test: Skip
+
+[ $compiler == dartkp && $runtime == dart_precompiled ]
+async_star/async_star_await_for_test: RuntimeError
+async_star/async_star_cancel_test: RuntimeError
+async_star/async_star_test: RuntimeError
+
+[ $runtime == dart_precompiled && $minified ]
+cyclic_type_test/*: Skip
+enum_duplicate_test/*: Skip # Uses Enum.toString()
+enum_private_test/*: Skip # Uses Enum.toString()
+enum_test: Skip # Uses Enum.toString()
+full_stacktrace1_test: Skip
+full_stacktrace2_test: Skip
+full_stacktrace3_test: Skip
+mixin_generic_test: Skip
+mixin_mixin3_test: Skip
+mixin_mixin5_test: Skip
+mixin_mixin6_test: Skip
+mixin_mixin_bound2_test: Skip
+mixin_mixin_type_arguments_test: Skip
+mixin_super_2_test: Skip
+no_such_method_dispatcher_test: Skip # Uses new Symbol()
+vm/no_such_args_error_message_vm_test: Skip
+vm/no_such_method_error_message_callable_vm_test: Skip
+vm/no_such_method_error_message_vm_test: Skip
+vm/regress_28325_test: Skip
+
+[ $runtime == dart_precompiled && ($mode == product || $minified) ]
+stacktrace_rethrow_error_test: SkipByDesign # obfuscation/minification and instruction deduplication cause names of frames to be mangled (expected)
+stacktrace_rethrow_nonerror_test: SkipByDesign # obfuscation/minification and instruction deduplication cause names of frames to be mangled (expected)
diff --git a/tests/language/language_spec_parser.status b/tests/language/language_spec_parser.status
new file mode 100644
index 0000000..8ba5051
--- /dev/null
+++ b/tests/language/language_spec_parser.status
@@ -0,0 +1,18 @@
+# Copyright (c) 2017, 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.
+
+[ $compiler == spec_parser ]
+built_in_identifier_prefix_test: Skip # A built-in identifier can _not_ be a prefix.
+closure_type_test: Pass # Marked as RuntimeError for all in language_2.status.
+const_native_factory_test: Skip # Uses `native`.
+deep_nesting_expression_test: Skip # JVM stack overflow.
+deep_nesting_statement_test: Skip # JVM stack overflow.
+double_invalid_test: Skip # Contains illegaly formatted double.
+issue_1751477_test: Skip # Times out: 9 levels, exponential blowup => 430 secs.
+large_class_declaration_test: Skip # JVM stack overflow.
+nnbd/syntax/opt_out_nnbd_modifiers_test: Skip # Requires opt-out of NNBD.
+nnbd/syntax/pre_nnbd_modifiers_test: Skip # Requires opt-out of NNBD.
+variance: Skip # Not yet supported.
+vm/debug_break_enabled_vm_test/01: Fail # Uses debug break.
+vm/debug_break_enabled_vm_test/none: Fail # Uses debug break.
diff --git a/tests/language/language_vm.status b/tests/language/language_vm.status
new file mode 100644
index 0000000..ceb8ec6
--- /dev/null
+++ b/tests/language/language_vm.status
@@ -0,0 +1,32 @@
+# Copyright (c) 2017, 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.
+# Sections in this file should contain "$runtime == vm".
+
+[ $compiler == dartkp ]
+assertion_initializer_const_error2_test/cc01: MissingCompileTimeError # Not reporting failed assert() at compile time.
+assertion_initializer_const_error2_test/cc02: MissingCompileTimeError # Not reporting failed assert() at compile time.
+assertion_initializer_const_error2_test/cc03: MissingCompileTimeError # Not reporting failed assert() at compile time.
+assertion_initializer_const_error2_test/cc04: MissingCompileTimeError # Not reporting failed assert() at compile time.
+assertion_initializer_const_error2_test/cc05: MissingCompileTimeError # Not reporting failed assert() at compile time.
+assertion_initializer_const_error2_test/cc06: MissingCompileTimeError # Not reporting failed assert() at compile time.
+assertion_initializer_const_error2_test/cc07: MissingCompileTimeError # Not reporting failed assert() at compile time.
+assertion_initializer_const_error2_test/cc08: MissingCompileTimeError # Not reporting failed assert() at compile time.
+assertion_initializer_const_error2_test/cc09: MissingCompileTimeError # Not reporting failed assert() at compile time.
+assertion_initializer_const_error2_test/cc10: MissingCompileTimeError # Not reporting failed assert() at compile time.
+assertion_initializer_const_error2_test/cc11: MissingCompileTimeError # Not reporting failed assert() at compile time.
+
+[ $runtime == vm ]
+async_star/async_star_await_for_test: RuntimeError
+async_star/async_star_cancel_test: RuntimeError
+async_star/async_star_test: RuntimeError
+
+[ $arch == arm64 && $runtime == vm ]
+closure_cycles_test: Pass, Slow
+large_class_declaration_test: SkipSlow # Uses too much memory.
+
+[ $arch == ia32 && $mode == release && $runtime == vm ]
+deep_nesting_expression_test/01: Crash, Pass # Issue 31496
+
+[ $runtime == dart_precompiled || $runtime == vm ]
+superinterface_variance/*: Skip # Issue dart-lang/language#113
diff --git a/tests/language/nonfunction_type_aliases/basic_syntax_test.dart b/tests/language/nonfunction_type_aliases/basic_syntax_test.dart
new file mode 100644
index 0000000..4b153c9
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/basic_syntax_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases,non-nullable
+
+typedef T0 = void;
+typedef T1 = Function;
+typedef T2<X> = List<X>;
+typedef T3<X, Y> = Map<X, Y>;
+typedef T4 = void Function();
+typedef T5<X> = X Function(X, {X name});
+typedef T6<X, Y> = X Function(Y, [Map<Y, Y>]);
+typedef T7<X extends String, Y extends List<X>> = X Function(Y, [Map<Y, Y>]);
+
+void main() {
+ // ignore:unused_local_variable
+ var ensure_usage = [T0, T1, T2, T3, T4, T5, T6, T7];
+}
diff --git a/tests/language/nonfunction_type_aliases/nnbd_syntax_test.dart b/tests/language/nonfunction_type_aliases/nnbd_syntax_test.dart
new file mode 100644
index 0000000..9939bb0
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/nnbd_syntax_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases,non-nullable
+
+typedef T0 = Function?;
+typedef T1<X> = List<X?>?;
+typedef T2<X, Y> = Map<X?, Y?>?;
+typedef T3 = Never? Function(void)?;
+typedef T4<X> = X? Function(X?, {required X? name})?;
+typedef T5<X extends String, Y extends List<X?>> =
+ X? Function(Y?, [Map<Y, Y?>]);
+
+void main() {
+ // ignore:unused_local_variable
+ var ensure_usage = [T0, T1, T2, T3, T4, T5];
+}
diff --git a/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart b/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
index 6ca87af..a2aea8c 100644
--- a/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
+++ b/tests/language_2/extension_methods/static_extension_getter_setter_conflicts_test.dart
@@ -82,11 +82,11 @@
E0(c0)[0] += 0;
// ^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_EXTENSION_OPERATOR
- // [cfe] The method '[]' isn't defined for the class 'dynamic'.
+ // [cfe] The method '[]' isn't defined for the class 'C0'.
E0(c0)[0]++;
// ^^^
// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_EXTENSION_OPERATOR
- // [cfe] The method '[]' isn't defined for the class 'dynamic'.
+ // [cfe] The method '[]' isn't defined for the class 'C0'.
}
// Conflicting extensions.
diff --git a/tests/language_2/function_type_parameter2_negative_test.dart b/tests/language_2/function_type_parameter2_negative_test.dart
deleted file mode 100644
index b1e92c6..0000000
--- a/tests/language_2/function_type_parameter2_negative_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Test that we detect that a function literal is not
-// a compile time constant.
-
-class FunctionTypeParameterNegativeTest {
- static var formatter;
-
- static SetFormatter([String fmt(int i) = (i) => "$i"]) {
- formatter = fmt;
- }
-
- static void testMain() {
- SetFormatter();
- }
-}
-
-main() {
- FunctionTypeParameterNegativeTest.testMain();
-}
diff --git a/tests/language_2/function_type_parameter3_test.dart b/tests/language_2/function_type_parameter3_test.dart
new file mode 100644
index 0000000..cb79201
--- /dev/null
+++ b/tests/language_2/function_type_parameter3_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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.
+
+/// Test that we detect that a function literal is not
+/// a compile time constant.
+
+test([String fmt(int i) = (i) => "$i"]) {}
+// ^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.NON_CONSTANT_DEFAULT_VALUE
+// [cfe] Not a constant expression.
+// ^
+// [cfe] Not a constant expression.
+
+main() {
+ test();
+}
diff --git a/tests/language_2/function_type_parameter_negative_test.dart b/tests/language_2/function_type_parameter_negative_test.dart
deleted file mode 100644
index 9e2f006..0000000
--- a/tests/language_2/function_type_parameter_negative_test.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Test that we detect that a function literal is not a compile time constant.
-
-class A {
- static Function func;
-
- static SetFunc([String fmt(int i) = (i) => "$i"]) {
- func = fmt;
- }
-}
-
-main() {
- A.SetFunc();
-}
diff --git a/tests/language_2/getter_declaration_negative_test.dart b/tests/language_2/getter_declaration_negative_test.dart
deleted file mode 100644
index 813b8d3..0000000
--- a/tests/language_2/getter_declaration_negative_test.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2011, 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.
-//
-// Test that a getter has no arguments
-get m(var extraParam) {
- return null;
-}
-
-main() {
- m;
-}
-
diff --git a/tests/language_2/getter_declaration_test.dart b/tests/language_2/getter_declaration_test.dart
new file mode 100644
index 0000000..6ccc137
--- /dev/null
+++ b/tests/language_2/getter_declaration_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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.
+
+/// Test that a getter takes no parameters.
+get m(extraParam) {
+// ^
+// [analyzer] SYNTACTIC_ERROR.GETTER_WITH_PARAMETERS
+// [cfe] A getter can't have formal parameters.
+ return null;
+}
+
+main() {
+ m;
+}
diff --git a/tests/language_2/inst_field_initializer1_negative_test.dart b/tests/language_2/inst_field_initializer1_negative_test.dart
deleted file mode 100644
index af446c7..0000000
--- a/tests/language_2/inst_field_initializer1_negative_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2011, 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.
-// Catch illegal access to 'this' in initialized instance fields.
-
-class A {
- A() {}
- int x = 5;
- int arr = new List(x); // Illegal access to 'this'.
- // Also not a compile const expression.
-}
-
-void main() {
- var foo = new A();
-}
diff --git a/tests/language_2/inst_field_initializer1_test.dart b/tests/language_2/inst_field_initializer1_test.dart
new file mode 100644
index 0000000..550a03e
--- /dev/null
+++ b/tests/language_2/inst_field_initializer1_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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.
+
+/// Catch illegal access to 'this' in initialized instance fields.
+
+class A {
+ var x = 5;
+ var arr = [x]; // Illegal access to 'this'.
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER
+ // [cfe] Can't access 'this' in a field initializer to read 'x'.
+}
+
+void main() {
+ A();
+}
diff --git a/tests/language_2/instance_call_wrong_argument_count_negative_test.dart b/tests/language_2/instance_call_wrong_argument_count_negative_test.dart
deleted file mode 100644
index a64a728..0000000
--- a/tests/language_2/instance_call_wrong_argument_count_negative_test.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2011, 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.
-// Test mismatch in argument counts.
-
-class InstanceCallWrongArgumentCountNegativeTest {
- static void testMain() {
- Niederhorn nh = new Niederhorn();
- nh.goodCall(1, 2, 3);
- // Bad call.
- nh.goodCall(1, 2, 3, 4);
- }
-}
-
-class Niederhorn {
- Niederhorn() {}
- int goodCall(int a, int b, int c) {
- return a + b;
- }
-}
-
-main() {
- InstanceCallWrongArgumentCountNegativeTest.testMain();
-}
diff --git a/tests/language_2/instance_call_wrong_argument_count_test.dart b/tests/language_2/instance_call_wrong_argument_count_test.dart
new file mode 100644
index 0000000..8f0c710
--- /dev/null
+++ b/tests/language_2/instance_call_wrong_argument_count_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+/// Test mismatch in argument counts.
+
+class Niederhorn {
+ int goodCall(int a, int b, int c) {
+ return a + b;
+ }
+}
+
+main() {
+ var niederhorn = Niederhorn();
+ niederhorn.goodCall(1, 2, 3);
+ niederhorn.goodCall(1, 2, 3, 4);
+ // ^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+ // [cfe] Too many positional arguments: 3 allowed, but 4 found.
+}
diff --git a/tests/language_2/instance_method2_negative_test.dart b/tests/language_2/instance_method2_negative_test.dart
deleted file mode 100644
index c0243bf9..0000000
--- a/tests/language_2/instance_method2_negative_test.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Dart test to check that we correctly flag the use of an
-// instance method (as a closure) from a static method.
-
-class Goofy {
- String instMethod() {
- return "woof";
- }
-
- static Function bark() {
- return instMethod; // Should get error here.
- }
-}
-
-class InstanceMethod2NegativeTest {
- static testMain() {
- var s = Goofy.bark();
- }
-}
-
-main() {
- InstanceMethod2NegativeTest.testMain();
-}
diff --git a/tests/language_2/instance_method2_test.dart b/tests/language_2/instance_method2_test.dart
new file mode 100644
index 0000000..de92967
--- /dev/null
+++ b/tests/language_2/instance_method2_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, 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.
+
+/// Check that we correctly flag the use of an instance method (as a closure)
+/// from a static method.
+
+class Goofy {
+ String instMethod() {
+ return "woof";
+ }
+
+ static Function bark() {
+ return instMethod;
+ // ^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INSTANCE_MEMBER_ACCESS_FROM_STATIC
+ // [cfe] Getter not found: 'instMethod'.
+ }
+}
+
+main() {
+ var s = Goofy.bark();
+}
diff --git a/tests/language_2/instance_method_negative_test.dart b/tests/language_2/instance_method_negative_test.dart
deleted file mode 100644
index ec9eaad..0000000
--- a/tests/language_2/instance_method_negative_test.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Dart test to check that we correctly flag the use of an
-// instance method from a static method.
-
-class Goofy {
- String instMethod() {
- return "woof";
- }
-
- static String bark() {
- return instMethod(); // Should get error here.
- }
-}
-
-class InstanceMethodNegativeTest {
- static testMain() {
- var s = Goofy.bark();
- }
-}
-
-main() {
- InstanceMethodNegativeTest.testMain();
-}
diff --git a/tests/language_2/instance_method_test.dart b/tests/language_2/instance_method_test.dart
new file mode 100644
index 0000000..f2de913
--- /dev/null
+++ b/tests/language_2/instance_method_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, 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.
+
+/// Check that we correctly flag the use of an instance method from a static
+/// method.
+
+class Goofy {
+ String instMethod() {
+ return "woof";
+ }
+
+ static String bark() {
+ return instMethod();
+ // ^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INSTANCE_MEMBER_ACCESS_FROM_STATIC
+ // [cfe] Method not found: 'instMethod'.
+ }
+}
+
+main() {
+ Goofy.bark();
+}
diff --git a/tests/language_2/interface2_negative_test.dart b/tests/language_2/interface2_negative_test.dart
deleted file mode 100644
index c4a23b1..0000000
--- a/tests/language_2/interface2_negative_test.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2012, 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.
-// Dart test program for testing wrong abstract class reference:
-// A class must implement a known interface.
-
-class Interface2NegativeTest implements BooHoo {
- static testMain() {}
-}
-
-main() {
- Interface2NegativeTest.testMain();
-}
diff --git a/tests/language_2/interface2_test.dart b/tests/language_2/interface2_test.dart
new file mode 100644
index 0000000..7b8282c
--- /dev/null
+++ b/tests/language_2/interface2_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, 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.
+
+/// A class must implement a known interface.
+
+class Interface2NegativeTest implements BooHoo {}
+// ^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_NON_CLASS
+// [cfe] Type 'BooHoo' not found.
+// ^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.UNDEFINED_CLASS
+
+main() {
+ Interface2NegativeTest();
+}
diff --git a/tests/language_2/interface_static_method_negative_test.dart b/tests/language_2/interface_static_method_negative_test.dart
deleted file mode 100644
index 5e8a83c..0000000
--- a/tests/language_2/interface_static_method_negative_test.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2012, 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.
-
-abstract class A {
- static void foo();
-}
-
-class InterfaceStaticMethodNegativeTest {
-
- static testMain() {
- var a = new A();
- }
-}
-
-main() {
- InterfaceStaticMethodNegativeTest.testMain();
-}
diff --git a/tests/language_2/interface_static_method_test.dart b/tests/language_2/interface_static_method_test.dart
new file mode 100644
index 0000000..9170aac
--- /dev/null
+++ b/tests/language_2/interface_static_method_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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.
+
+abstract class A {
+ static void foo();
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_FUNCTION_BODY
+ // [cfe] Expected a function body or '=>'.
+}
+
+main() {
+ A();
+//^
+// [analyzer] STATIC_WARNING.NEW_WITH_ABSTRACT_CLASS
+// [cfe] The class 'A' is abstract and can't be instantiated.
+}
diff --git a/tests/language_2/interface_static_non_final_fields_negative_test.dart b/tests/language_2/interface_static_non_final_fields_negative_test.dart
deleted file mode 100644
index 9da2007..0000000
--- a/tests/language_2/interface_static_non_final_fields_negative_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2012, 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.
-
-abstract class A {
- static var a;
-}
-
-class InterfaceStaticNonConstFieldsNegativeTest {
- static testMain() {}
-}
-
-main() {
- InterfaceStaticNonFinalFieldsNegativeTest.testMain();
-}
diff --git a/tests/language_2/is_not_class1_negative_test.dart b/tests/language_2/is_not_class1_negative_test.dart
deleted file mode 100644
index 5fafbbd..0000000
--- a/tests/language_2/is_not_class1_negative_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test program for catch that we expect a class after an 'is'.
-
-class A {
- const A();
-}
-
-class IsNotClass1NegativeTest {
- static testMain() {
- var a = new A();
-
- if (a is "A") {
- return 0;
- }
- return 0;
- }
-}
-
-main() {
- IsNotClass1NegativeTest.testMain();
-}
diff --git a/tests/language_2/is_not_class1_test.dart b/tests/language_2/is_not_class1_test.dart
new file mode 100644
index 0000000..6de8f8b
--- /dev/null
+++ b/tests/language_2/is_not_class1_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2011, 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.
+
+/// Test that we expect a class after an 'is'.
+class A {}
+
+main() {
+ var a = A();
+ if (a is "A") return 0;
+ // [error line 10, column 12, length 0]
+ // [analyzer] STATIC_WARNING.TYPE_TEST_WITH_UNDEFINED_NAME
+ // [cfe] Expected ')' before this.
+ // ^^^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected a type, but got '"A"'.
+ // ^^^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TYPE_NAME
+ // [cfe] This couldn't be parsed.
+}
diff --git a/tests/language_2/is_not_class4_negative_test.dart b/tests/language_2/is_not_class4_negative_test.dart
deleted file mode 100644
index 84ef5ed1..0000000
--- a/tests/language_2/is_not_class4_negative_test.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test program to test that the parser emits an error when
-// two 'is' expressions follow each other.
-
-class A {
- const A();
-}
-
-class IsNotClass4NegativeTest {
- static testMain() {
- var a = new A();
-
- if (a is A is A) {
- return 0;
- }
- return 0;
- }
-}
-
-main() {
- IsNotClass4NegativeTest.testMain();
-}
diff --git a/tests/language_2/is_not_class4_test.dart b/tests/language_2/is_not_class4_test.dart
new file mode 100644
index 0000000..a3adae2
--- /dev/null
+++ b/tests/language_2/is_not_class4_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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.
+
+/// Test that the parser emits an error when one 'is' expression follows
+/// another.
+class A {}
+
+main() {
+ var a = A();
+ if (a is A is A) return 0;
+ // ^^
+ // [analyzer] SYNTACTIC_ERROR.UNEXPECTED_TOKEN
+ // [cfe] Unexpected token 'is'.
+}
diff --git a/tests/language_2/issue1578_negative_test.dart b/tests/language_2/issue1578_negative_test.dart
deleted file mode 100644
index ff3d0d7..0000000
--- a/tests/language_2/issue1578_negative_test.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// Regression test for issue 1578.
-
-]~<)$
diff --git a/tests/language_2/issue1578_test.dart b/tests/language_2/issue1578_test.dart
new file mode 100644
index 0000000..ad355ae
--- /dev/null
+++ b/tests/language_2/issue1578_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2012, 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.
+
+// Regression test for issue 1578.
+
+]~<)$
+// [error line 7, column 1, length 1]
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE
+// [cfe] Expected a declaration, but got ']'.
+// [error line 7, column 2, length 1]
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE
+// [cfe] Expected a declaration, but got '~'.
+//^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE
+// [cfe] Expected a declaration, but got '<'.
+// ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_EXECUTABLE
+// [cfe] Expected a declaration, but got ')'.
+// ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ';' after this.
+// ^
+// [analyzer] SYNTACTIC_ERROR.MISSING_CONST_FINAL_VAR_OR_TYPE
+// [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 8902133..796193b 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -5,6 +5,9 @@
[ $compiler != dart2analyzer ]
switch_case_warn_test: Skip # Analyzer only, see language_analyzer2.status
+[ $compiler != fasta ]
+nonfunction_type_aliases/*: Skip # github.com/dart-lang/language/issues/115
+
[ $compiler == none ]
invalid_returns/*: Skip # https://github.com/dart-lang/sdk/issues/34013
void/*: Skip # https://github.com/dart-lang/sdk/issues/34013
diff --git a/tests/language_2/language_2_spec_parser.status b/tests/language_2/language_2_spec_parser.status
index 7cd6359..8ba5051 100644
--- a/tests/language_2/language_2_spec_parser.status
+++ b/tests/language_2/language_2_spec_parser.status
@@ -9,56 +9,10 @@
deep_nesting_expression_test: Skip # JVM stack overflow.
deep_nesting_statement_test: Skip # JVM stack overflow.
double_invalid_test: Skip # Contains illegaly formatted double.
-getter_declaration_negative_test: Fail # Negative, uses getter with parameter.
-inst_field_initializer1_negative_test: Skip # Negative, not syntax.
-instance_call_wrong_argument_count_negative_test: Skip # Negative, not syntax.
-instance_method2_negative_test: Skip # Negative, not syntax.
-instance_method_negative_test: Skip # Negative, not syntax.
-interface2_negative_test: Skip # Negative, not syntax.
-interface_static_method_negative_test: Skip # Negative, not syntax.
-interface_static_non_final_fields_negative_test: Skip # Negative, not syntax.
-is_not_class1_negative_test: Fail # Negative, uses `a is "A"`.
-is_not_class4_negative_test: Fail # Negative, uses `a is A is A`.
-issue1578_negative_test: Fail # Negative, is line noise.
issue_1751477_test: Skip # Times out: 9 levels, exponential blowup => 430 secs.
large_class_declaration_test: Skip # JVM stack overflow.
-list_literal2_negative_test: Skip # Negative, not syntax.
-list_literal_negative_test: Fail # Negative, uses `new List<int>[1, 2]`.
-map_literal2_negative_test: Skip # Negative, not syntax.
-map_literal_negative_test: Fail # Negative, uses `new Map<int>{..}`.
-new_expression1_negative_test: Fail # Negative, uses `new id`.
-new_expression2_negative_test: Fail # Negative, uses `new id(`.
-new_expression3_negative_test: Fail # Negative, uses `new id(...`.
nnbd/syntax/opt_out_nnbd_modifiers_test: Skip # Requires opt-out of NNBD.
nnbd/syntax/pre_nnbd_modifiers_test: Skip # Requires opt-out of NNBD.
-no_such_method_negative_test: Skip # Negative, not syntax.
-non_const_super_negative_test: Skip # Negative, not syntax.
-operator1_negative_test: Fail # Negative, declares static operator.
-operator2_negative_test: Fail # Negative, declares `operator ===`.
-override_field_method1_negative_test: Skip # Negative, not syntax.
-override_field_method2_negative_test: Skip # Negative, not syntax.
-override_field_method4_negative_test: Skip # Negative, not syntax.
-override_field_method5_negative_test: Skip # Negative, not syntax.
-parameter_initializer1_negative_test: Skip # Negative, not syntax.
-parameter_initializer2_negative_test: Skip # Negative, not syntax.
-parameter_initializer3_negative_test: Skip # Negative, not syntax.
-parameter_initializer4_negative_test: Skip # Negative, not syntax.
-parameter_initializer6_negative_test: Skip # Negative, not syntax.
-private_member1_negative_test: Skip # Negative, not syntax.
-private_member2_negative_test: Skip # Negative, not syntax.
-private_member3_negative_test: Skip # Negative, not syntax.
-script1_negative_test: Skip # Negative, not syntax.
-script2_negative_test: Skip # Negative, not syntax.
-string_escape4_negative_test: Fail # Negative, uses newline in string literal.
-string_interpolate1_negative_test: Fail # Negative, misplaced '$'.
-string_interpolate2_negative_test: Fail # Negative, misplaced '$'.
-string_unicode1_negative_test: Skip # Negative, not syntax.
-string_unicode2_negative_test: Skip # Negative, not syntax.
-string_unicode3_negative_test: Skip # Negative, not syntax.
-string_unicode4_negative_test: Skip # Negative, not syntax.
-switch1_negative_test: Fail # Negative, `default` clause not last.
-test_negative_test: Fail # Negative, uses non-terminated string literal.
-unary_plus_negative_test: Fail # Negative, uses non-existing unary plus.
variance: Skip # Not yet supported.
vm/debug_break_enabled_vm_test/01: Fail # Uses debug break.
vm/debug_break_enabled_vm_test/none: Fail # Uses debug break.
diff --git a/tests/language_2/list_literal2_negative_test.dart b/tests/language_2/list_literal2_negative_test.dart
deleted file mode 100644
index 08e9cc8..0000000
--- a/tests/language_2/list_literal2_negative_test.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2011, 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.
-//
-// Dart test program const map literals.
-
-class ListLiteral2NegativeTest<T> {
- test() {
- try {
- var m = const <T>[0, 1]; // Type parameter is not allowed with const.
- } on TypeError catch (error) {}
- }
-}
-
-main() {
- var t = new ListLiteral2NegativeTest<int>();
- t.test();
-}
diff --git a/tests/language_2/list_literal5_test.dart b/tests/language_2/list_literal5_test.dart
new file mode 100644
index 0000000..81969be
--- /dev/null
+++ b/tests/language_2/list_literal5_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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.
+
+/// Legacy compound literal syntax that should go away.
+
+main() {
+ new List<int>[1, 2];
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected '(' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ']' before this.
+}
diff --git a/tests/language_2/list_literal6_test.dart b/tests/language_2/list_literal6_test.dart
new file mode 100644
index 0000000..7d6e3d9
--- /dev/null
+++ b/tests/language_2/list_literal6_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+/// Dart test program const map literals.
+
+class ListLiteral2NegativeTest<T> {
+ test() {
+ // Type parameter is not allowed with const.
+ var m = const <T>[];
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_TYPE_ARGUMENT_IN_CONST_LIST
+ // [cfe] Type variables can't be used as constants.
+ }
+}
+
+main() {
+ ListLiteral2NegativeTest<int>().test();
+}
diff --git a/tests/language_2/list_literal_negative_test.dart b/tests/language_2/list_literal_negative_test.dart
deleted file mode 100644
index 4c9ad6d..0000000
--- a/tests/language_2/list_literal_negative_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2011, 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.
-// Legacy compound literal syntax that should go away.
-
-class ListLiteralNegativeTest {
-
- static testMain() {
- var funny = new List<int>[1, 2];
- }
-}
-
-main() {
- ListLiteralNegativeTest.testMain();
-}
diff --git a/tests/language_2/map_literal13_test.dart b/tests/language_2/map_literal13_test.dart
new file mode 100644
index 0000000..f32082d
--- /dev/null
+++ b/tests/language_2/map_literal13_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2019, 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.
+
+/// Legacy compound literal syntax that should go away.
+
+main() {
+ var map = new Map<int>{ "a": 1, "b": 2, "c": 3 };
+ // ^^^^^^^^
+ // [analyzer] STATIC_WARNING.NEW_WITH_INVALID_TYPE_PARAMETERS
+ // [cfe] Expected 2 type arguments.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected '(' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^^^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+ // [cfe] Expected an identifier, but got ':'.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.UNEXPECTED_TOKEN
+ // [cfe] Unexpected token ':'.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+ // [cfe] Expected an identifier, but got ','.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.UNEXPECTED_TOKEN
+ // [cfe] Unexpected token ','.
+ // ^^^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+ // [cfe] Expected an identifier, but got ':'.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.UNEXPECTED_TOKEN
+ // [cfe] Unexpected token ':'.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+ // [cfe] Expected an identifier, but got ','.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.UNEXPECTED_TOKEN
+ // [cfe] Unexpected token ','.
+ // ^^^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+ // [cfe] Expected an identifier, but got ':'.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.UNEXPECTED_TOKEN
+ // [cfe] Unexpected token ':'.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected ';' after this.
+}
diff --git a/tests/language_2/map_literal14_test.dart b/tests/language_2/map_literal14_test.dart
new file mode 100644
index 0000000..4351eb9
--- /dev/null
+++ b/tests/language_2/map_literal14_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+/// Dart test program const map literals.
+
+class MapLiteral2NegativeTest<T> {
+ test() {
+ var m = const <String, T>{};
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_TYPE_ARGUMENT_IN_CONST_MAP
+ // [cfe] Type variables can't be used as constants.
+ }
+}
+
+main() {
+ MapLiteral2NegativeTest<int>().test();
+}
diff --git a/tests/language_2/map_literal2_negative_test.dart b/tests/language_2/map_literal2_negative_test.dart
deleted file mode 100644
index c2b47ee..0000000
--- a/tests/language_2/map_literal2_negative_test.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2011, 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.
-// VMOptions=--enable_type_checks
-//
-// Dart test program const map literals.
-
-class MapLiteral2NegativeTest<T> {
- test() {
- var m = const <String, T>{"a": 0}; /*@compile-error=unspecified*/
- }
-}
-
-main() {
- var t = new MapLiteral2NegativeTest<int>();
- t.test();
-}
diff --git a/tests/language_2/map_literal_negative_test.dart b/tests/language_2/map_literal_negative_test.dart
deleted file mode 100644
index dd4b65d..0000000
--- a/tests/language_2/map_literal_negative_test.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2011, 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.
-// Legacy compound literal syntax that should go away.
-
-class MapLiteralNegativeTest {
- static testMain() {
- var map = new Map<int>{ "a": 1, "b": 2, "c": 3 };
- }
-}
-
-main() {
- MapLiteralNegativeTest.testMain();
-}
diff --git a/tests/language_2/new_expression1_negative_test.dart b/tests/language_2/new_expression1_negative_test.dart
deleted file mode 100644
index 4ed4882..0000000
--- a/tests/language_2/new_expression1_negative_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2011, 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.
-
-class NewExpressionNegativeTest {
- NewExpressionNegativeTest() { }
-
- static void testMain() {
- new NewExpressionNegativeTest;
- }
- }
-
-main() {
- NewExpressionNegativeTest.testMain();
-}
diff --git a/tests/language_2/new_expression1_test.dart b/tests/language_2/new_expression1_test.dart
new file mode 100644
index 0000000..b06ff2a
--- /dev/null
+++ b/tests/language_2/new_expression1_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2019, 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.
+
+class C {}
+
+main() {
+ new C;
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected '(' after this.
+}
diff --git a/tests/language_2/new_expression2_negative_test.dart b/tests/language_2/new_expression2_negative_test.dart
deleted file mode 100644
index 90e3c2f..0000000
--- a/tests/language_2/new_expression2_negative_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2011, 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.
-
-class NewExpressionNegativeTest {
- NewExpressionNegativeTest() { }
-
- static void testMain() {
- new NewExpressionNegativeTest(;
- }
- }
-
-main() {
- NewExpressionNegativeTest.testMain();
-}
diff --git a/tests/language_2/new_expression2_test.dart b/tests/language_2/new_expression2_test.dart
new file mode 100644
index 0000000..6695b3b
--- /dev/null
+++ b/tests/language_2/new_expression2_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+class C {}
+
+main() {
+ new C(;
+ // ^
+ // [cfe] Can't find ')' to match '('.
+ // ^
+ // [cfe] Too many positional arguments: 0 allowed, but 1 found.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+ // [cfe] Expected an identifier, but got ';'.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+}
diff --git a/tests/language_2/new_expression3_negative_test.dart b/tests/language_2/new_expression3_negative_test.dart
deleted file mode 100644
index 50b2d44..0000000
--- a/tests/language_2/new_expression3_negative_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2011, 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.
-
-class NewExpressionNegativeTest {
- NewExpressionNegativeTest() { }
-
- static void testMain() {
- new NewExpressionNegativeTest(...;
- }
- }
-
-main() {
- NewExpressionNegativeTest.testMain();
-}
diff --git a/tests/language_2/new_expression3_test.dart b/tests/language_2/new_expression3_test.dart
new file mode 100644
index 0000000..ee1edff
--- /dev/null
+++ b/tests/language_2/new_expression3_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+class C {}
+
+main() {
+ new C(...;
+ // ^
+ // [cfe] Can't find ')' to match '('.
+ // ^
+ // [cfe] Too many positional arguments: 0 allowed, but 1 found.
+ // ^^^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+ // [cfe] Expected an identifier, but got '...'.
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+}
diff --git a/tests/language_2/nnbd/syntax/late_modifier_edge_cases_test.dart b/tests/language_2/nnbd/syntax/late_modifier_edge_cases_test.dart
new file mode 100644
index 0000000..45a0dcd
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/late_modifier_edge_cases_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+import 'package:expect/expect.dart';
+
+class A {
+ late int lateField = initLateField();
+
+ int initLateField() {
+ lateField = 456;
+ Expect.equals(456, lateField);
+ return 123;
+ }
+
+ late final int lateFinalField = initLateFinalField();
+
+ int count = 0;
+ int initLateFinalField() {
+ if (count == 5) return count;
+ return ++count + lateFinalField;
+ }
+
+ static late int staticLateField = initStaticLateField();
+
+ static int initStaticLateField() {
+ staticLateField = 456;
+ Expect.equals(456, staticLateField);
+ return 123;
+ }
+
+ static late final int staticLateFinalField = initStaticLateFinalField();
+
+ static int staticCount = 0;
+ static int initStaticLateFinalField() {
+ if (staticCount == 5) return staticCount;
+ return ++staticCount + staticLateFinalField;
+ }
+}
+
+lateFieldWithInitThatWritesIntermediateValue() {
+ A a = A();
+ Expect.equals(123, a.lateField);
+ Expect.throws(() => print(a.lateFinalField));
+ Expect.equals(5, a.lateFinalField);
+ Expect.equals(123, A.staticLateField);
+ Expect.throws(() => print(A.staticLateFinalField));
+ Expect.equals(5, A.staticLateFinalField);
+}
+
+main() {
+ lateFieldWithInitThatWritesIntermediateValue();
+}
diff --git a/tests/language_2/nnbd/syntax/late_modifier_final_local_var_test.dart b/tests/language_2/nnbd/syntax/late_modifier_final_local_var_test.dart
new file mode 100644
index 0000000..9deb9c5
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/late_modifier_final_local_var_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+import 'package:expect/expect.dart';
+
+int initCalls = 0;
+int init() {
+ ++initCalls;
+ return 123;
+}
+
+main() {
+ late final int fieldWithInit = init();
+ Expect.equals(0, initCalls);
+ Expect.equals(123, fieldWithInit);
+ Expect.equals(1, initCalls);
+ Expect.equals(123, fieldWithInit);
+ Expect.equals(1, initCalls);
+
+ late final int fieldWithNoInit;
+ Expect.throws(
+ () => fieldWithNoInit, (error) => error is LateInitializationError);
+ fieldWithNoInit = 123;
+ Expect.equals(123, fieldWithNoInit);
+ Expect.throws(() => {fieldWithNoInit = 456},
+ (error) => error is LateInitializationError);
+ Expect.equals(123, fieldWithNoInit);
+}
diff --git a/tests/language_2/nnbd/syntax/late_modifier_global_var_test.dart b/tests/language_2/nnbd/syntax/late_modifier_global_var_test.dart
new file mode 100644
index 0000000..7a7f9c9
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/late_modifier_global_var_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+import 'package:expect/expect.dart';
+
+int initCalls = 0;
+int init() {
+ ++initCalls;
+ return 123;
+}
+
+late int varWithInit = init();
+late int varWithInit2 = init();
+late int? varWithInit3 = init();
+late int varWithTrivialInit = 123;
+late int? varWithNullInit = null;
+late int varWithNoInit;
+late final int finalVarWithInit = init();
+late final int finalVarWithTrivialInit = 123;
+late final int? finalVarWithNullInit = null;
+late final int finalVarWithNoInit;
+
+main() {
+ Expect.equals(0, initCalls);
+ Expect.equals(123, varWithInit);
+ Expect.equals(123, varWithTrivialInit);
+ Expect.equals(null, varWithNullInit);
+ Expect.throws(
+ () => varWithNoInit, (error) => error is LateInitializationError);
+ Expect.equals(1, initCalls);
+ Expect.equals(123, varWithInit);
+ Expect.equals(123, varWithTrivialInit);
+ Expect.equals(null, varWithNullInit);
+ Expect.throws(
+ () => varWithNoInit, (error) => error is LateInitializationError);
+ Expect.equals(1, initCalls);
+ varWithInit = 456;
+ varWithTrivialInit = 456;
+ varWithNullInit = 456;
+ varWithNoInit = 456;
+ Expect.equals(1, initCalls);
+ Expect.equals(456, varWithInit);
+ Expect.equals(456, varWithTrivialInit);
+ Expect.equals(456, varWithNullInit);
+ Expect.equals(456, varWithNoInit);
+ Expect.equals(1, initCalls);
+ initCalls = 0;
+
+ Expect.equals(0, initCalls);
+ varWithInit2 = 456;
+ Expect.equals(0, initCalls);
+ Expect.equals(456, varWithInit2);
+ Expect.equals(0, initCalls);
+
+ Expect.equals(0, initCalls);
+ varWithInit3 = null;
+ Expect.equals(0, initCalls);
+ Expect.equals(null, varWithInit3);
+ Expect.equals(0, initCalls);
+
+ Expect.equals(0, initCalls);
+ Expect.equals(123, finalVarWithInit);
+ Expect.equals(123, finalVarWithTrivialInit);
+ Expect.equals(null, finalVarWithNullInit);
+ Expect.equals(1, initCalls);
+ Expect.equals(123, finalVarWithInit);
+ Expect.equals(123, finalVarWithTrivialInit);
+ Expect.equals(null, finalVarWithNullInit);
+ Expect.equals(1, initCalls);
+
+ Expect.throws(
+ () => finalVarWithNoInit, (error) => error is LateInitializationError);
+ finalVarWithNoInit = 123;
+ Expect.equals(123, finalVarWithNoInit);
+ Expect.throws(() => {finalVarWithNoInit = 456},
+ (error) => error is LateInitializationError);
+ Expect.equals(123, finalVarWithNoInit);
+}
diff --git a/tests/language_2/nnbd/syntax/late_modifier_local_var_test.dart b/tests/language_2/nnbd/syntax/late_modifier_local_var_test.dart
new file mode 100644
index 0000000..d52ff6f
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/late_modifier_local_var_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+import 'package:expect/expect.dart';
+
+int initCalls = 0;
+int init() {
+ ++initCalls;
+ return 123;
+}
+
+main() {
+ late int varWithInit = init();
+ late int varWithTrivialInit = 123;
+ late int? varWithNullInit = null;
+ late int varWithNoInit;
+ Expect.equals(0, initCalls);
+ Expect.equals(123, varWithInit);
+ Expect.equals(123, varWithTrivialInit);
+ Expect.equals(null, varWithNullInit);
+ Expect.throws(
+ () => varWithNoInit, (error) => error is LateInitializationError);
+ Expect.equals(1, initCalls);
+ Expect.equals(123, varWithInit);
+ Expect.equals(123, varWithTrivialInit);
+ Expect.equals(null, varWithNullInit);
+ Expect.throws(
+ () => varWithNoInit, (error) => error is LateInitializationError);
+ Expect.equals(1, initCalls);
+ varWithInit = 456;
+ varWithTrivialInit = 456;
+ varWithNullInit = 456;
+ varWithNoInit = 456;
+ Expect.equals(1, initCalls);
+ Expect.equals(456, varWithInit);
+ Expect.equals(456, varWithTrivialInit);
+ Expect.equals(456, varWithNullInit);
+ Expect.equals(456, varWithNoInit);
+ Expect.equals(1, initCalls);
+ initCalls = 0;
+
+ late int varWithInit2 = init();
+ Expect.equals(0, initCalls);
+ varWithInit2 = 456;
+ Expect.equals(0, initCalls);
+ Expect.equals(456, varWithInit2);
+ Expect.equals(0, initCalls);
+
+ late int? varWithInit3 = init();
+ Expect.equals(0, initCalls);
+ varWithInit3 = null;
+ Expect.equals(0, initCalls);
+ Expect.equals(null, varWithInit3);
+ Expect.equals(0, initCalls);
+
+ late int varWithCondInit = null ?? init();
+ var lambda = () {
+ Expect.equals(123, varWithCondInit);
+ Expect.equals(1, initCalls);
+ };
+ lambda();
+ lambda();
+ lambda();
+ initCalls = 0;
+
+ if (true) late int varNotInBlock = init();
+ Expect.equals(0, initCalls);
+}
diff --git a/tests/language_2/nnbd/syntax/late_modifier_static_final_field_test.dart b/tests/language_2/nnbd/syntax/late_modifier_static_final_field_test.dart
new file mode 100644
index 0000000..ff6e144
--- /dev/null
+++ b/tests/language_2/nnbd/syntax/late_modifier_static_final_field_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+import 'package:expect/expect.dart';
+
+int initCalls = 0;
+int init() {
+ ++initCalls;
+ return 123;
+}
+
+class A {
+ static late final int fieldWithInit = init();
+ static late final int fieldWithTrivialInit = 123;
+ static late final int? fieldWithNullInit = null;
+ static late final int fieldWithNoInit;
+}
+
+main() {
+ Expect.equals(0, initCalls);
+ Expect.equals(123, A.fieldWithInit);
+ Expect.equals(123, A.fieldWithTrivialInit);
+ Expect.equals(null, A.fieldWithNullInit);
+ Expect.equals(1, initCalls);
+ Expect.equals(123, A.fieldWithInit);
+ Expect.equals(123, A.fieldWithTrivialInit);
+ Expect.equals(null, A.fieldWithNullInit);
+ Expect.equals(1, initCalls);
+
+ Expect.throws(
+ () => A.fieldWithNoInit, (error) => error is LateInitializationError);
+ A.fieldWithNoInit = 123;
+ Expect.equals(123, A.fieldWithNoInit);
+ Expect.throws(() => {A.fieldWithNoInit = 456},
+ (error) => error is LateInitializationError);
+ Expect.equals(123, A.fieldWithNoInit);
+}
diff --git a/tests/language_2/no_such_method4_test.dart b/tests/language_2/no_such_method4_test.dart
new file mode 100644
index 0000000..23b2feb
--- /dev/null
+++ b/tests/language_2/no_such_method4_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+import 'package:expect/expect.dart';
+
+class NoSuchMethodNegativeTest {
+ foo() {
+ return 1;
+ }
+}
+
+main() {
+ var obj = new NoSuchMethodNegativeTest() as dynamic;
+ Expect.throwsNoSuchMethodError(() {
+ obj.moo();
+ });
+}
diff --git a/tests/language_2/no_such_method_negative_test.dart b/tests/language_2/no_such_method_negative_test.dart
deleted file mode 100644
index 7abd826..0000000
--- a/tests/language_2/no_such_method_negative_test.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test program testing that NoSuchMethodError stops the program.
-
-class NoSuchMethodNegativeTest {
- NoSuchMethodNegativeTest() {}
-
- foo() {
- return 1;
- }
-
- static testMain() {
- var obj = new NoSuchMethodNegativeTest();
- return obj.moo(); // NoSuchMethodError thrown here
- }
-}
-
-main() {
- NoSuchMethodNegativeTest.testMain();
-}
diff --git a/tests/language_2/non_const_super_negative_test.dart b/tests/language_2/non_const_super_negative_test.dart
deleted file mode 100644
index 32742e2..0000000
--- a/tests/language_2/non_const_super_negative_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2011, 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.
-// Check fails because const class extends from non const class.
-
-class Base {
- Base() {}
-}
-
-class Sub extends Base {
- const Sub(a) : a_ = a;
- final a_;
-}
-
-class NonConstSuperNegativeTest {
- static testMain() {
- var a = new Sub();
- }
-}
-
-main() {
- NonConstSuperNegativeTest.testMain();
-}
diff --git a/tests/language_2/non_const_super_test.dart b/tests/language_2/non_const_super_test.dart
new file mode 100644
index 0000000..06c9f73
--- /dev/null
+++ b/tests/language_2/non_const_super_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, 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.
+
+/// Check fails because const class extends from non const class.
+
+class Base {
+ Base() {}
+}
+
+class Sub extends Base {
+ const Sub(a) : a_ = a;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER
+ // [cfe] A constant constructor can't call a non-constant super constructor.
+ final a_;
+}
+
+main() {
+ Sub(0);
+}
diff --git a/tests/language_2/nonfunction_type_aliases/basic_syntax_test.dart b/tests/language_2/nonfunction_type_aliases/basic_syntax_test.dart
new file mode 100644
index 0000000..545f533
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/basic_syntax_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+typedef T0 = void;
+typedef T1 = Function;
+typedef T2<X> = List<X>;
+typedef T3<X, Y> = Map<X, Y>;
+typedef T4 = void Function();
+typedef T5<X> = X Function(X, {X name});
+typedef T6<X, Y> = X Function(Y, [Map<Y, Y>]);
+typedef T7<X extends String, Y extends List<X>> = X Function(Y, [Map<Y, Y>]);
+
+void main() {
+ // ignore:unused_local_variable
+ var ensure_usage = [T0, T1, T2, T3, T4, T5, T6, T7];
+}
diff --git a/tests/language_2/nonfunction_type_aliases/nnbd_syntax_test.dart b/tests/language_2/nonfunction_type_aliases/nnbd_syntax_test.dart
new file mode 100644
index 0000000..9939bb0
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/nnbd_syntax_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases,non-nullable
+
+typedef T0 = Function?;
+typedef T1<X> = List<X?>?;
+typedef T2<X, Y> = Map<X?, Y?>?;
+typedef T3 = Never? Function(void)?;
+typedef T4<X> = X? Function(X?, {required X? name})?;
+typedef T5<X extends String, Y extends List<X?>> =
+ X? Function(Y?, [Map<Y, Y?>]);
+
+void main() {
+ // ignore:unused_local_variable
+ var ensure_usage = [T0, T1, T2, T3, T4, T5];
+}
diff --git a/tests/language_2/operator1_negative_test.dart b/tests/language_2/operator1_negative_test.dart
deleted file mode 100644
index 7f9c24d..0000000
--- a/tests/language_2/operator1_negative_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011, 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.
-// Operator dart test program (operator functions cannot be static).
-
-class Helper {
- int i;
- Helper(int val) : i = val { }
- static operator +(int index) {
- return index;
- }
-}
-
-class Operator1NegativeTest {
- static testMain() {
- Helper obj = new Helper(10);
- }
-}
-
-main() {
- Operator1NegativeTest.testMain();
-}
diff --git a/tests/language_2/operator1_test.dart b/tests/language_2/operator1_test.dart
new file mode 100644
index 0000000..5ba6722
--- /dev/null
+++ b/tests/language_2/operator1_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+/// Operator functions cannot be static.
+
+class C {
+ static operator +(int index) {
+//^^^^^^
+// [analyzer] SYNTACTIC_ERROR.STATIC_OPERATOR
+// [cfe] Operators can't be static.
+ return index;
+ }
+}
+
+main() {
+ C();
+}
diff --git a/tests/language_2/operator2_negative_test.dart b/tests/language_2/operator2_negative_test.dart
deleted file mode 100644
index 5ee7096..0000000
--- a/tests/language_2/operator2_negative_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011, 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.
-// Operator dart test program (=== cannot have an operator function).
-
-class Helper {
- int i;
- Helper(int val) : i = val { }
- operator ===(int index) {
- return index;
- }
-}
-
-class Operator2NegativeTest {
- static testMain() {
- Helper obj = new Helper(10);
- }
-}
-
-main() {
- Operator2NegativeTest.testMain();
-}
diff --git a/tests/language_2/operator7_test.dart b/tests/language_2/operator7_test.dart
new file mode 100644
index 0000000..ff43b64
--- /dev/null
+++ b/tests/language_2/operator7_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+/// No "===" operator.
+
+class C {
+ operator ===(int index) {
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.UNSUPPORTED_OPERATOR
+ // [cfe] The '===' operator is not supported.
+ return index;
+ }
+}
+
+main() {
+ C();
+}
diff --git a/tests/language_2/override_field_method1_negative_test.dart b/tests/language_2/override_field_method1_negative_test.dart
deleted file mode 100644
index 4113590..0000000
--- a/tests/language_2/override_field_method1_negative_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test error for overriding field with method.
-
-class A {
- var foo;
-}
-
-class B extends A {
- foo() {} // method cannot override field.
-}
-
-class OverrideFieldMethod1NegativeTest {
- static testMain() {
- new B().foo();
- }
-}
-
-main() {
- OverrideFieldMethod1NegativeTest.testMain();
-}
diff --git a/tests/language_2/override_field_method1_test.dart b/tests/language_2/override_field_method1_test.dart
new file mode 100644
index 0000000..bee5869
--- /dev/null
+++ b/tests/language_2/override_field_method1_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+/// Overriding field with method.
+
+class A {
+ var foo;
+}
+
+class B extends A {
+ foo() {}
+//^^^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_METHOD_AND_FIELD
+// [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+main() {
+ B().foo();
+}
diff --git a/tests/language_2/override_field_method2_negative_test.dart b/tests/language_2/override_field_method2_negative_test.dart
deleted file mode 100644
index c695fb3..0000000
--- a/tests/language_2/override_field_method2_negative_test.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test error for overriding getter with method.
-
-class A {
- get foo {
- return 123;
- }
-}
-
-class B extends A {
- foo() {} // method cannot override getter.
-}
-
-class OverrideFieldMethod2NegativeTest {
- static testMain() {
- new B().foo();
- }
-}
-
-main() {
- OverrideFieldMethod2NegativeTest.testMain();
-}
diff --git a/tests/language_2/override_field_method2_test.dart b/tests/language_2/override_field_method2_test.dart
new file mode 100644
index 0000000..0b5e4b3
--- /dev/null
+++ b/tests/language_2/override_field_method2_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+/// Overriding getter with method.
+
+class A {
+ get foo => 123;
+}
+
+class B extends A {
+ foo() {}
+//^^^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_METHOD_AND_FIELD
+// [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+main() {
+ B().foo();
+}
diff --git a/tests/language_2/override_field_method3_test.dart b/tests/language_2/override_field_method3_test.dart
new file mode 100644
index 0000000..dbd5cfe
--- /dev/null
+++ b/tests/language_2/override_field_method3_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+/// Overriding method with field.
+
+class A {
+ foo() {}
+}
+
+class B extends A {
+ var foo;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_FIELD_AND_METHOD
+ // [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+main() {
+ B().foo;
+}
diff --git a/tests/language_2/override_field_method4_negative_test.dart b/tests/language_2/override_field_method4_negative_test.dart
deleted file mode 100644
index 65837e7..0000000
--- a/tests/language_2/override_field_method4_negative_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test error for overriding method with field.
-
-class A {
- foo() {}
-}
-
-class B extends A {
- var foo; // Field cannot override method.
-}
-
-class OverrideFieldMethod4NegativeTest {
- static testMain() {
- print(new B().foo);
- }
-}
-
-main() {
- OverrideFieldMethod4NegativeTest.testMain();
-}
diff --git a/tests/language_2/override_field_method4_test.dart b/tests/language_2/override_field_method4_test.dart
new file mode 100644
index 0000000..eecea07
--- /dev/null
+++ b/tests/language_2/override_field_method4_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+/// Overriding method with getter.
+
+class A {
+ foo() => 999;
+}
+
+class B extends A {
+ get foo => 123;
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.CONFLICTING_FIELD_AND_METHOD
+ // [cfe] Can't declare a member that conflicts with an inherited one.
+}
+
+main() {
+ B().foo;
+}
diff --git a/tests/language_2/override_field_method5_negative_test.dart b/tests/language_2/override_field_method5_negative_test.dart
deleted file mode 100644
index 7484c30..0000000
--- a/tests/language_2/override_field_method5_negative_test.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test error for overriding method with getter.
-
-class A {
- foo() {
- return 999;
- }
-}
-
-class B extends A {
- get foo {
- return 123;
- } // getter cannot override method
-}
-
-class OverrideFieldMethod5NegativeTest {
- static testMain() {
- print(new B().foo);
- }
-}
-
-main() {
- OverrideFieldMethod5NegativeTest.testMain();
-}
diff --git a/tests/language_2/parameter_initializer1_negative_test.dart b/tests/language_2/parameter_initializer1_negative_test.dart
deleted file mode 100644
index c433dce..0000000
--- a/tests/language_2/parameter_initializer1_negative_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Fails because this.x parameter is used in a function.
-
-class Foo {
- var x;
- Foo() {}
- foo(this.x) {
- }
-}
-
-
-class ParameterInitializer1NegativeTest {
- static testMain() {
- new Foo().foo(2);
- }
-}
-
-main() {
- ParameterInitializer1NegativeTest.testMain();
-}
diff --git a/tests/language_2/parameter_initializer1_test.dart b/tests/language_2/parameter_initializer1_test.dart
new file mode 100644
index 0000000..34465a4
--- /dev/null
+++ b/tests/language_2/parameter_initializer1_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+/// Fails because this.x parameter is used in a function.
+
+class Foo {
+ var x;
+ foo(this.x) {}
+ // ^^^^
+ // [analyzer] SYNTACTIC_ERROR.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
+ // [cfe] Field formal parameters can only be used in a constructor.
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
+}
+
+main() {
+ Foo().foo(2);
+}
diff --git a/tests/language_2/parameter_initializer2_negative_test.dart b/tests/language_2/parameter_initializer2_negative_test.dart
deleted file mode 100644
index c0758f5..0000000
--- a/tests/language_2/parameter_initializer2_negative_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Fails because this.x parameter is used in a setter.
-
-class Foo {
- var x;
- Foo() {}
- set y(this.x) {
- }
-}
-
-
-class ParameterInitializer2NegativeTest {
- static testMain() {
- (new Foo()).y = 2;
- }
-}
-
-main() {
- ParameterInitializer2NegativeTest.testMain();
-}
diff --git a/tests/language_2/parameter_initializer3_negative_test.dart b/tests/language_2/parameter_initializer3_negative_test.dart
deleted file mode 100644
index 8b4ec6b..0000000
--- a/tests/language_2/parameter_initializer3_negative_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Fails because this.x parameter is used in a factory.
-
-class Foo {
- var x;
- factory Foo(this.x) {
- return new Foo.named();
- }
- Foo.named() {}
-}
-
-class ParameterInitializer3NegativeTest {
- static testMain() {
- new Foo(2);
- }
-}
-
-main() {
- ParameterInitializer3NegativeTest.testMain();
-}
diff --git a/tests/language_2/parameter_initializer3_test.dart b/tests/language_2/parameter_initializer3_test.dart
new file mode 100644
index 0000000..bf81a6d
--- /dev/null
+++ b/tests/language_2/parameter_initializer3_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2011, 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.
+
+/// Fails because this.x parameter is used in a factory.
+
+class Foo {
+ var x;
+ factory Foo(this.x) => new Foo.named();
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.FIELD_INITIALIZER_FACTORY_CONSTRUCTOR
+ // [cfe] Field formal parameters can only be used in a constructor.
+ Foo.named() {}
+}
+
+main() {
+ Foo(2);
+}
diff --git a/tests/language_2/parameter_initializer4_negative_test.dart b/tests/language_2/parameter_initializer4_negative_test.dart
deleted file mode 100644
index 9b32fae..0000000
--- a/tests/language_2/parameter_initializer4_negative_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Fails because this.x parameter is used in a static function.
-
-class Foo {
- var x;
- static foo(this.x) {
- }
-}
-
-
-class ParameterInitializer4NegativeTest {
- static testMain() {
- Foo.foo();
- }
-}
-
-main() {
- ParameterInitializer4NegativeTest.testMain();
-}
diff --git a/tests/language_2/parameter_initializer4_test.dart b/tests/language_2/parameter_initializer4_test.dart
new file mode 100644
index 0000000..49cf633
--- /dev/null
+++ b/tests/language_2/parameter_initializer4_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+/// Fails because this.x parameter is used in a static function.
+
+class Foo {
+ var x;
+ static foo(this.x) {}
+ // ^^^^
+ // [analyzer] SYNTACTIC_ERROR.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
+ // [cfe] Field formal parameters can only be used in a constructor.
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
+}
+
+main() {
+ Foo.foo(1);
+}
diff --git a/tests/language_2/parameter_initializer6_negative_test.dart b/tests/language_2/parameter_initializer6_negative_test.dart
deleted file mode 100644
index 40a2231..0000000
--- a/tests/language_2/parameter_initializer6_negative_test.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012, 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.
-
-import "package:expect/expect.dart";
-
-// It is a compile-time error if a named formal parameter begins with an '_'
-
-class Foo {
- num _y;
- Foo.optional_private({this._y: 77}) {}
-}
-
-main() {
- var obj;
- obj = new Foo.optional_private(_y: 222);
- Expect.equals(222, obj._y);
-
- obj = new Foo.optional_private();
- Expect.equals(77, obj._y);
-}
diff --git a/tests/language_2/parameter_initializer6_test.dart b/tests/language_2/parameter_initializer6_test.dart
new file mode 100644
index 0000000..9a5ebda
--- /dev/null
+++ b/tests/language_2/parameter_initializer6_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+import "package:expect/expect.dart";
+
+/// It is a compile-time error if a named formal parameter begins with an '_'.
+
+class Foo {
+ num _y;
+ Foo.private({this._y: 77}) {}
+ // ^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.PRIVATE_OPTIONAL_PARAMETER
+ // ^
+ // [cfe] An optional named parameter can't start with '_'.
+}
+
+main() {
+ Foo.private(_y: 222);
+}
diff --git a/tests/language_2/parameter_initializer7_test.dart b/tests/language_2/parameter_initializer7_test.dart
new file mode 100644
index 0000000..b1bca78
--- /dev/null
+++ b/tests/language_2/parameter_initializer7_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+/// Fails because this.x parameter is used in a setter.
+
+class Foo {
+ var x;
+ set y(this.x) {}
+ // ^^^^
+ // [analyzer] SYNTACTIC_ERROR.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
+ // [cfe] Field formal parameters can only be used in a constructor.
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR
+}
+
+main() {
+ Foo().y = 2;
+}
diff --git a/tests/language_2/part_self_test.dart b/tests/language_2/part_self_test.dart
new file mode 100644
index 0000000..1f44de8
--- /dev/null
+++ b/tests/language_2/part_self_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2019, 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.
+
+part "part_self_test.dart";
+// ^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.PART_OF_NON_PART
+
+main() {
+ print('should not be able to recursively include self as library part');
+}
diff --git a/tests/language_2/private_member1_lib.dart b/tests/language_2/private_member1_lib.dart
new file mode 100644
index 0000000..fb6fdb2
--- /dev/null
+++ b/tests/language_2/private_member1_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, 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.
+
+import 'private_member1_test.dart';
+
+class B extends A {
+ bool _instanceField;
+}
diff --git a/tests/language_2/private_member1_lib_b.dart b/tests/language_2/private_member1_lib_b.dart
deleted file mode 100644
index b0f0bf5..0000000
--- a/tests/language_2/private_member1_lib_b.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2011, 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.
-
-library PrivateMemberLibB;
-
-import 'private_member1_negative_test.dart';
-
-class B extends A {
- bool _instanceField;
-}
diff --git a/tests/language_2/private_member1_negative_test.dart b/tests/language_2/private_member1_negative_test.dart
deleted file mode 100644
index 054bea9..0000000
--- a/tests/language_2/private_member1_negative_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2011, 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.
-
-library PrivateMemberLibA;
-
-import 'private_member1_lib_b.dart';
-
-class A {}
-
-class Test extends B {
- test() {
- _instanceField = true;
- }
-}
-
-void main() {
- new Test().test();
-}
diff --git a/tests/language_2/private_member1_test.dart b/tests/language_2/private_member1_test.dart
new file mode 100644
index 0000000..4a8ecb9
--- /dev/null
+++ b/tests/language_2/private_member1_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+import 'private_member1_lib.dart';
+
+class A {}
+
+class Test extends B {
+ test() {
+ _instanceField = true;
+// ^^^^^^^^^^^^^^
+// [analyzer] STATIC_WARNING.UNDEFINED_IDENTIFIER
+// [cfe] The setter '_instanceField' isn't defined for the class 'Test'.
+ }
+}
+
+void main() {
+ Test().test();
+}
diff --git a/tests/language_2/private_member2_lib.dart b/tests/language_2/private_member2_lib.dart
new file mode 100644
index 0000000..0b2590c
--- /dev/null
+++ b/tests/language_2/private_member2_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, 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.
+
+import 'private_member2_test.dart';
+
+class B extends A {
+ static bool _staticField;
+}
diff --git a/tests/language_2/private_member2_lib_b.dart b/tests/language_2/private_member2_lib_b.dart
deleted file mode 100644
index 1b60b38..0000000
--- a/tests/language_2/private_member2_lib_b.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2011, 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.
-
-library PrivateMemberLibB;
-
-import 'private_member2_negative_test.dart';
-
-class B extends A {
- static bool _staticField;
-}
diff --git a/tests/language_2/private_member2_negative_test.dart b/tests/language_2/private_member2_negative_test.dart
deleted file mode 100644
index 1846c01..0000000
--- a/tests/language_2/private_member2_negative_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2011, 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.
-
-library PrivateMemberLibA;
-
-import 'private_member2_lib_b.dart';
-
-class A {}
-
-class Test extends B {
- test() {
- _staticField = true;
- }
-}
-
-void main() {
- new Test().test();
-}
diff --git a/tests/language_2/private_member2_test.dart b/tests/language_2/private_member2_test.dart
new file mode 100644
index 0000000..15e3747
--- /dev/null
+++ b/tests/language_2/private_member2_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+import 'private_member2_lib.dart';
+
+class A {}
+
+class Test extends B {
+ test() {
+ _staticField = true;
+// ^^^^^^^^^^^^
+// [analyzer] STATIC_WARNING.UNDEFINED_IDENTIFIER
+// [cfe] The setter '_staticField' isn't defined for the class 'Test'.
+ }
+}
+
+void main() {
+ Test().test();
+}
diff --git a/tests/language_2/private_member3_lib_b.dart b/tests/language_2/private_member3_lib.dart
similarity index 60%
rename from tests/language_2/private_member3_lib_b.dart
rename to tests/language_2/private_member3_lib.dart
index 71beac6..00309f9 100644
--- a/tests/language_2/private_member3_lib_b.dart
+++ b/tests/language_2/private_member3_lib.dart
@@ -1,10 +1,8 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2019, 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.
-library PrivateMemberLibB;
-
-import 'private_member3_negative_test.dart';
+import 'private_member3_test.dart';
class B extends A {
bool _fun() {
diff --git a/tests/language_2/private_member3_negative_test.dart b/tests/language_2/private_member3_negative_test.dart
deleted file mode 100644
index 91052cb..0000000
--- a/tests/language_2/private_member3_negative_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2011, 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.
-
-library PrivateMemberLibA;
-
-import 'private_member3_lib_b.dart';
-
-class A {}
-
-class Test extends B {
- test() {
- _fun();
- }
-}
-
-void main() {
- new Test().test();
-}
diff --git a/tests/language_2/private_member3_test.dart b/tests/language_2/private_member3_test.dart
new file mode 100644
index 0000000..4e7675f
--- /dev/null
+++ b/tests/language_2/private_member3_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+import 'private_member3_lib.dart';
+
+class A {}
+
+class Test extends B {
+ test() {
+ _fun();
+// ^^^^
+// [analyzer] STATIC_TYPE_WARNING.UNDEFINED_METHOD
+// [cfe] The method '_fun' isn't defined for the class 'Test'.
+ }
+}
+
+void main() {
+ Test().test();
+}
diff --git a/tests/language_2/regress_124683_test.dart b/tests/language_2/regress_124683_test.dart
new file mode 100644
index 0000000..4efe4f6
--- /dev/null
+++ b/tests/language_2/regress_124683_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, 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.
+
+// Regression test for ddc failure triggered by
+// https://dart-review.googlesource.com/c/sdk/+/124683
+
+class Class {
+ String toString() {
+ void local() {}
+
+ return '${runtimeType.toString()}';
+ }
+}
+
+main() {
+ new Class().toString();
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js_extra/invalid_length_negative_test.dart b/tests/language_2/script1_lib.dart
similarity index 61%
rename from tests/compiler/dart2js_extra/invalid_length_negative_test.dart
rename to tests/language_2/script1_lib.dart
index 9836653..525b2ca 100644
--- a/tests/compiler/dart2js_extra/invalid_length_negative_test.dart
+++ b/tests/language_2/script1_lib.dart
@@ -1,7 +1,5 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2019, 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.
-main() {
- new List("foo");
-}
+int ok = 1;
diff --git a/tests/language_2/script1_negative_lib.dart b/tests/language_2/script1_negative_lib.dart
deleted file mode 100644
index 312103b..0000000
--- a/tests/language_2/script1_negative_lib.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Imported library has wrong order of import and source tags.
-
-library Script1NegativeLib;
-part "script_source.dart";
-import "script_lib.dart";
-
-class A {
- var a;
-}
diff --git a/tests/language_2/script1_negative_test.dart b/tests/language_2/script1_negative_test.dart
deleted file mode 100644
index e2af064..0000000
--- a/tests/language_2/script1_negative_test.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Imported library has wrong order of import and source tags.
-
-library Script1NegativeTest.dart;
-
-import "script1_negative_lib.dart";
-
-main() {
- print("Should not reach here.");
-}
diff --git a/tests/language_2/script1_part.dart b/tests/language_2/script1_part.dart
new file mode 100644
index 0000000..15bd30d
--- /dev/null
+++ b/tests/language_2/script1_part.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, 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.
+
+part of "script1_test.dart";
+
+const int scriptPart = 1;
diff --git a/tests/language_2/script1_test.dart b/tests/language_2/script1_test.dart
new file mode 100644
index 0000000..8d714e9
--- /dev/null
+++ b/tests/language_2/script1_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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.
+
+/// Wrong order of import and part directives.
+
+part "script1_part.dart";
+import "script1_lib.dart";
+// [error line 8, column 1, length 6]
+// [analyzer] SYNTACTIC_ERROR.IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE
+// [cfe] Import directives must precede part directives.
+
+main() {
+ print("Should not reach here.");
+}
diff --git a/tests/language_2/script2_negative_lib.dart b/tests/language_2/script2_negative_lib.dart
deleted file mode 100644
index c436080..0000000
--- a/tests/language_2/script2_negative_lib.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Imported library has source file with library tags.
-
-library Script2NegativeLib;
-
-import "script_lib.dart";
-part "script2_negative_source.dart";
-
-class A {
- var a;
-}
diff --git a/tests/language_2/script2_negative_source.dart b/tests/language_2/script2_negative_source.dart
deleted file mode 100644
index 1674541..0000000
--- a/tests/language_2/script2_negative_source.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Imported library has source file with library tags.
-
-library Script2NegativeSource;
-
-const int script_2_negative_source = 1;
diff --git a/tests/language_2/script2_negative_test.dart b/tests/language_2/script2_negative_test.dart
deleted file mode 100644
index 731eddb..0000000
--- a/tests/language_2/script2_negative_test.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Imported library has source file with library tags.
-
-library Script2NegativeTest.dart;
-
-import "script2_negative_lib.dart";
-
-main() {
- print("Should not reach here.");
-}
diff --git a/tests/language_2/script2_part.dart b/tests/language_2/script2_part.dart
new file mode 100644
index 0000000..44f24e8
--- /dev/null
+++ b/tests/language_2/script2_part.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2019, 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.
+
+library Script2Part;
+import "script_lib.dart";
+
+part of "script2_test.dart";
+
+const int scriptPart = 1;
diff --git a/tests/language_2/script2_test.dart b/tests/language_2/script2_test.dart
new file mode 100644
index 0000000..7ab8397
--- /dev/null
+++ b/tests/language_2/script2_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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.
+
+/// Part file has library and import directives.
+
+/*@compile-error=unspecified*/
+// TODO(rnystrom): Using the above tag instead of making this a static error
+// test because the error is reported in the part file and not in this file.
+// Static error tests only support errors reported in the main test file itself.
+part "script2_part.dart";
+
+main() {
+ print("Should not reach here.");
+}
diff --git a/tests/language_2/script_lib.dart b/tests/language_2/script_lib.dart
index 95a911d..eafca26 100644
--- a/tests/language_2/script_lib.dart
+++ b/tests/language_2/script_lib.dart
@@ -6,4 +6,4 @@
library ScriptLib;
-const int script_lib = 1;
+const int scriptLib = 1;
diff --git a/tests/language_2/setter_declaration2_negative_test.dart b/tests/language_2/setter_declaration2_negative_test.dart
deleted file mode 100644
index 617000b..0000000
--- a/tests/language_2/setter_declaration2_negative_test.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2011, 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.
-//
-// Test that a setter has a single argument
-
-// too few arguments
-set m() {}
-
-main() {
- m = 1;
-}
diff --git a/tests/language_2/setter_declaration_negative_test.dart b/tests/language_2/setter_declaration_negative_test.dart
deleted file mode 100644
index 3e66ea8..0000000
--- a/tests/language_2/setter_declaration_negative_test.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2011, 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.
-//
-// Test that a setter has a single argument
-
-// too many arguments
-set m(var value, var extra) {}
-
-main() {
- m = 1;
-}
diff --git a/tests/language_2/setter_declaration_test.dart b/tests/language_2/setter_declaration_test.dart
new file mode 100644
index 0000000..cc5e6a7
--- /dev/null
+++ b/tests/language_2/setter_declaration_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, 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.
+
+/// Test that a setter has a single argument.
+
+set tooFew() {}
+// ^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER
+// ^
+// [cfe] A setter should have exactly one formal parameter.
+
+set tooMany(var value, var extra) {}
+// ^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER
+// ^
+// [cfe] A setter should have exactly one formal parameter.
+
+main() {
+ tooFew = 1;
+ tooMany = 2;
+}
diff --git a/tests/language_2/source_self_negative_test.dart b/tests/language_2/source_self_negative_test.dart
deleted file mode 100644
index b9b2e7e..0000000
--- a/tests/language_2/source_self_negative_test.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2011, 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.
-
-// Dart test program importing the core library explicitly.
-
-library SourceSelfNegativeTest;
-
-part "source_self_negative_test.dart"; // recursive reference to self.
-
-main() {
- print('should not be able to recursively include self as library part');
-}
diff --git a/tests/language_2/static_call_wrong_argument_count_negative_test.dart b/tests/language_2/static_call_wrong_argument_count_negative_test.dart
deleted file mode 100644
index 2bc0509..0000000
--- a/tests/language_2/static_call_wrong_argument_count_negative_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011, 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.
-// Test mismatch in argument counts.
-
-class StaticCallWrongArgumentCountNegativeTest {
- static void testMain() {
- Niesen.goodCall(1, 2, 3);
- // Bad call.
- Niesen.goodCall(1, 2, 3, 4);
- }
-}
-
-class Niesen {
- static int goodCall(int a, int b, int c) {
- return a + b;
- }
-}
-
-main() {
- StaticCallWrongArgumentCountNegativeTest.testMain();
-}
diff --git a/tests/language_2/static_call_wrong_argument_count_test.dart b/tests/language_2/static_call_wrong_argument_count_test.dart
new file mode 100644
index 0000000..575c486
--- /dev/null
+++ b/tests/language_2/static_call_wrong_argument_count_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, 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.
+
+/// Test mismatch in argument counts.
+class Niesen {
+ static int goodCall(int a, int b, int c) {
+ return a + b;
+ }
+}
+
+main() {
+ Niesen.goodCall(1, 2, 3);
+
+ Niesen.goodCall(1, 2, 3, 4);
+ // ^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
+ // [cfe] Too many positional arguments: 3 allowed, but 4 found.
+}
diff --git a/tests/language_2/string_escape2_negative_test_helper.dart b/tests/language_2/string_escape2_negative_test_helper.dart
deleted file mode 100644
index 92c10d9..0000000
--- a/tests/language_2/string_escape2_negative_test_helper.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// An empty file, attempted sourced by string_escape2_negative_test.dart.
diff --git a/tests/language_2/string_escape3_negative_test_helper.dart b/tests/language_2/string_escape3_negative_test_helper.dart
deleted file mode 100644
index 2d14a8d..0000000
--- a/tests/language_2/string_escape3_negative_test_helper.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// An empty library, imported by string_escape3_negative_test.dart.
-
-library empty;
diff --git a/tests/language_2/string_escape4_negative_test.dart b/tests/language_2/string_escape4_negative_test.dart
deleted file mode 100644
index d12cdd2..0000000
--- a/tests/language_2/string_escape4_negative_test.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// Test that newlines cannot be escaped in strings.
-
-main() {
- print('Hello, World!\
-');
-}
diff --git a/tests/language_2/string_escape4_test.dart b/tests/language_2/string_escape4_test.dart
new file mode 100644
index 0000000..6f4efba
--- /dev/null
+++ b/tests/language_2/string_escape4_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2019, 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.
+
+// Test that newlines cannot be escaped in strings.
+
+main() {
+ // Note: The newline inside a string literal doesn't play nice with the
+ // static error updater tool, so if you need to tweak the static error
+ // expectations in this test, you may need to do so manually.
+ print('Hello, World!\
+');
+// [error line 11, column 8, length 1]
+// [cfe] Can't find ')' to match '('.
+// [error line 11, column 9, length 1]
+// [cfe] String starting with ' must end with '.
+// [error line 11, column 23, length 1]
+// [analyzer] SYNTACTIC_ERROR.INVALID_UNICODE_ESCAPE
+// [cfe] An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.
+// [error line 11, column 23, length 1]
+// [analyzer] SYNTACTIC_ERROR.UNTERMINATED_STRING_LITERAL
+// [error line 12, column 1, length 3]
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ';' after this.
+// [error line 12, column 1]
+// [cfe] String starting with ' must end with '.
+// [error line 12, column 3, length 1]
+// [analyzer] SYNTACTIC_ERROR.UNTERMINATED_STRING_LITERAL
+}
+// [error line 29, column 1, length 1]
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
diff --git a/tests/language_2/string_interpolate1_negative_test.dart b/tests/language_2/string_interpolate1_negative_test.dart
deleted file mode 100644
index 5a38e52..0000000
--- a/tests/language_2/string_interpolate1_negative_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test program testing that the interpolated identifier does not start
-// with '$'.
-
-class StringInterpolate1NegativeTest {
-
- static testMain() {
- var $x = 1;
- var s = "eins und $$x macht zwei.";
- print(s);
- }
-
-}
-
-main() {
- StringInterpolate1NegativeTest.testMain();
-}
diff --git a/tests/language_2/string_interpolate1_test.dart b/tests/language_2/string_interpolate1_test.dart
new file mode 100644
index 0000000..1bc80c0
--- /dev/null
+++ b/tests/language_2/string_interpolate1_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, 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.
+
+/// The interpolated identifier can't start with '$'.
+
+main() {
+ var $x = 1;
+ var s = "eins und $$x macht zwei.";
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+ // [cfe] A '$' has special meaning inside a string, and must be followed by an identifier or an expression in curly braces ({}).
+ // ^
+ // [analyzer] STATIC_WARNING.UNDEFINED_IDENTIFIER
+ // [cfe] Getter not found: 'x'.
+}
diff --git a/tests/language_2/string_interpolate2_negative_test.dart b/tests/language_2/string_interpolate2_negative_test.dart
deleted file mode 100644
index 0acbd7d..0000000
--- a/tests/language_2/string_interpolate2_negative_test.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test program testing that the interpolated identifier starts with an
-// ident start character.
-
-class StringInterpolate2NegativeTest {
-
- static testMain() {
- var $x = 1;
- var s = "eins und $-x macht zwei.";
- print(s);
- }
-
-}
-
-main() {
- StringInterpolate2NegativeTest.testMain();
-}
diff --git a/tests/language_2/string_interpolate3_test.dart b/tests/language_2/string_interpolate3_test.dart
new file mode 100644
index 0000000..ada7879
--- /dev/null
+++ b/tests/language_2/string_interpolate3_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2019, 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.
+
+/// The interpolated identifier must start with an identifier start character.
+
+main() {
+ var x = 1;
+ var s = "eins und $-x macht zwei.";
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+ // [cfe] A '$' has special meaning inside a string, and must be followed by an identifier or an expression in curly braces ({}).
+}
diff --git a/tests/language_2/string_unicode1_negative_test.dart b/tests/language_2/string_unicode1_negative_test.dart
deleted file mode 100644
index 72c06e14..0000000
--- a/tests/language_2/string_unicode1_negative_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2011, 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.
-
-class StringUnicode1NegativeTest {
-
- static testMain() {
- // (backslash) uXXXX must have exactly 4 hex digits
- String str = "Foo\u00";
- str = "Foo\uDEEMBar";
- }
-}
-
-main() {
- StringUnicode1NegativeTest.testMain();
-}
diff --git a/tests/language_2/string_unicode1_test.dart b/tests/language_2/string_unicode1_test.dart
new file mode 100644
index 0000000..04a9f5f
--- /dev/null
+++ b/tests/language_2/string_unicode1_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, 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.
+
+/// (backslash) uXXXX must have exactly 4 hex digits.
+
+main() {
+ var str = "Foo\u00";
+ // ^^^^
+ // [analyzer] SYNTACTIC_ERROR.INVALID_UNICODE_ESCAPE
+ // [cfe] An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.
+ str = "Foo\uDEEMBar";
+ // ^^^^^
+ // [analyzer] SYNTACTIC_ERROR.INVALID_UNICODE_ESCAPE
+ // [cfe] An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.
+}
diff --git a/tests/language_2/string_unicode2_negative_test.dart b/tests/language_2/string_unicode2_negative_test.dart
deleted file mode 100644
index c38040c..0000000
--- a/tests/language_2/string_unicode2_negative_test.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2011, 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.
-
-class StringUnicode2NegativeTest {
-
- static testMain() {
- // \u{X*} should have 1-6 hex digits
- String str = "Foo\u{}Bar";
- str = "Foo\u{000000000}Bar";
- str = "Foo\u{DEAF!}Bar";
- }
-}
-
-main() {
- StringUnicode2NegativeTest.testMain();
-}
diff --git a/tests/language_2/string_unicode2_test.dart b/tests/language_2/string_unicode2_test.dart
new file mode 100644
index 0000000..4624fbd
--- /dev/null
+++ b/tests/language_2/string_unicode2_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2019, 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.
+
+/// \u{X*} should have 1-6 hex digits.
+
+main() {
+ var str = "Foo\u{}Bar";
+ // ^^^^
+ // [analyzer] SYNTACTIC_ERROR.INVALID_UNICODE_ESCAPE
+ // [cfe] An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.
+ str = "Foo\u{000000000}Bar";
+ str = "Foo\u{DEAF!}Bar";
+ // ^^^^^^^^
+ // [analyzer] SYNTACTIC_ERROR.INVALID_UNICODE_ESCAPE
+ // [cfe] An escape sequence starting with '\u' must be followed by 4 hexadecimal digits or from 1 to 6 digits between '{' and '}'.
+}
diff --git a/tests/language_2/string_unicode3_negative_test.dart b/tests/language_2/string_unicode3_negative_test.dart
deleted file mode 100644
index 15cdf38..0000000
--- a/tests/language_2/string_unicode3_negative_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2011, 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.
-
-class StringUnicode3NegativeTest {
-
- static testMain() {
- // (backslash) xXX must have exactly 2 hex digits
- String str = "Foo\x0";
- str = "Foo\xF Bar";
- }
-}
-
-main() {
- StringUnicode3NegativeTest.testMain();
-}
diff --git a/tests/language_2/string_unicode3_test.dart b/tests/language_2/string_unicode3_test.dart
new file mode 100644
index 0000000..3c04303
--- /dev/null
+++ b/tests/language_2/string_unicode3_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, 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.
+
+/// Backslash xXX must have exactly 2 hex digits.
+
+main() {
+ var str = "Foo\x0";
+ // ^^^
+ // [analyzer] SYNTACTIC_ERROR.INVALID_HEX_ESCAPE
+ // [cfe] An escape sequence starting with '\x' must be followed by 2 hexadecimal digits.
+ str = "Foo\xF Bar";
+ // ^^^
+ // [analyzer] SYNTACTIC_ERROR.INVALID_HEX_ESCAPE
+ // [cfe] An escape sequence starting with '\x' must be followed by 2 hexadecimal digits.
+}
diff --git a/tests/language_2/string_unicode4_negative_test.dart b/tests/language_2/string_unicode4_negative_test.dart
deleted file mode 100644
index b4ee30f..0000000
--- a/tests/language_2/string_unicode4_negative_test.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2011, 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.
-
-class StringUnicode4NegativeTest {
-
- static testMain() {
- // Unicode escapes must refer to valid Unicode points and not surrogate characters
- String str = "Foo\u{FFFFFF}";
- str = "Foo\uD800";
- str = "Foo\uDC00";
- }
-}
-
-main() {
- StringUnicode4NegativeTest.testMain();
-}
diff --git a/tests/language_2/string_unicode4_test.dart b/tests/language_2/string_unicode4_test.dart
new file mode 100644
index 0000000..89095fa
--- /dev/null
+++ b/tests/language_2/string_unicode4_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, 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.
+
+/// Unicode escapes must refer to valid Unicode points and not surrogate
+/// characters.
+
+main() {
+ var str = "Foo\u{FFFFFF}";
+ // ^^^^^^^^^
+ // [analyzer] SYNTACTIC_ERROR.INVALID_CODE_POINT
+ // [cfe] The escape sequence starting with '\u' isn't a valid code point.
+ str = "Foo\uD800";
+ str = "Foo\uDC00";
+}
diff --git a/tests/language_2/switch1_negative_test.dart b/tests/language_2/switch1_negative_test.dart
deleted file mode 100644
index 5648b22..0000000
--- a/tests/language_2/switch1_negative_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2011, 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.
-// Check that default clause must be last case.
-
-class Switch1NegativeTest {
-
- static testMain() {
- var a = 5;
- var x;
- S: switch (a) {
- case 1: x = 1; break;
- case 6: x = 2; break S;
- default:
- case 8: break;
- }
- return a;
- }
-}
-
-main() {
- Switch1NegativeTest.testMain();
-}
diff --git a/tests/language_2/switch1_test.dart b/tests/language_2/switch1_test.dart
new file mode 100644
index 0000000..ffae0f2
--- /dev/null
+++ b/tests/language_2/switch1_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, 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.
+
+/// Check that default clause must be last case.
+
+main() {
+ var a = 5;
+ var x;
+ S: switch (a) {
+ case 1: x = 1; break;
+ case 6: x = 2; break S;
+ default:
+// ^
+// [cfe] Switch case may fall through to the next case.
+ case 8: break;
+// ^^^^
+// [analyzer] SYNTACTIC_ERROR.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE
+// [cfe] The default case should be the last case in a switch statement.
+ }
+ return a;
+}
diff --git a/tests/language_2/switch3_negative_test.dart b/tests/language_2/switch3_negative_test.dart
deleted file mode 100644
index 1232537..0000000
--- a/tests/language_2/switch3_negative_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011, 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.
-// Check that 'continue' to switch statement is illegal.
-
-class Switch3NegativeTest {
-
- static testMain() {
- var a = 5;
- var x;
- switch (a) {
- case 1: x = 1; break;
- case 6: x = 2; continue; // illegal jump target
- case 8: break;
- }
- return a;
- }
-}
-
-main() {
- Switch3NegativeTest.testMain();
-}
diff --git a/tests/language_2/switch3_test.dart b/tests/language_2/switch3_test.dart
new file mode 100644
index 0000000..cdcbdef
--- /dev/null
+++ b/tests/language_2/switch3_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, 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.
+
+/// Check that 'continue' to switch statement is illegal.
+
+main() {
+ var a = 5;
+ var x;
+ switch (a) {
+ case 1: x = 1; break;
+ case 6: x = 2; continue;
+// ^
+// [cfe] Switch case may fall through to the next case.
+// ^^^^^^^^
+// [analyzer] SYNTACTIC_ERROR.CONTINUE_WITHOUT_LABEL_IN_CASE
+// [cfe] A continue statement in a switch statement must have a label as a target.
+ case 8: break;
+ }
+ return a;
+}
diff --git a/tests/language_2/switch4_negative_test.dart b/tests/language_2/switch4_negative_test.dart
deleted file mode 100644
index e4f7723..0000000
--- a/tests/language_2/switch4_negative_test.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2011, 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.
-// Discover unresolved case labels.
-
-class Switch4NegativeTest {
- static testMain() {
- var a = 5;
- var x;
- switch (a) {
- case 1:
- x = 1;
- continue L; // unresolved forward reference
- case 6:
- x = 2;
- break;
- case 8:
- break;
- }
- return a;
- }
-}
-
-main() {
- Switch4NegativeTest.testMain();
-}
diff --git a/tests/language_2/switch4_test.dart b/tests/language_2/switch4_test.dart
new file mode 100644
index 0000000..d90fc65
--- /dev/null
+++ b/tests/language_2/switch4_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2019, 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.
+
+/// Discover unresolved case labels.
+
+main() {
+ var a = 5;
+ var x;
+ switch (a) {
+ case 1:
+ x = 1;
+ continue L;
+// ^
+// [cfe] Can't find label 'L'.
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.LABEL_UNDEFINED
+ case 6:
+ x = 2;
+ break;
+ case 8:
+ break;
+ }
+ return a;
+}
diff --git a/tests/language_2/switch5_negative_test.dart b/tests/language_2/switch5_negative_test.dart
deleted file mode 100644
index 639c983..0000000
--- a/tests/language_2/switch5_negative_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2011, 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.
-// Break' to case label is illegal.
-
-class Switch5NegativeTest {
- static testMain() {
- var a = 5;
- var x;
- switch (a) {
- L:
- case 1:
- x = 1;
- break;
- case 6:
- x = 2;
- break L; // illegal
- default:
- break;
- }
- return a;
- }
-}
-
-main() {
- Switch5NegativeTest.testMain();
-}
diff --git a/tests/language_2/switch5_test.dart b/tests/language_2/switch5_test.dart
new file mode 100644
index 0000000..7f23f3f
--- /dev/null
+++ b/tests/language_2/switch5_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+/// Break' to case label is illegal.
+
+main() {
+ var a = 5;
+ var x;
+ switch (a) {
+ L:
+ case 1:
+ x = 1;
+ break;
+ case 6:
+// ^
+// [cfe] Switch case may fall through to the next case.
+ x = 2;
+ break L;
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.BREAK_LABEL_ON_SWITCH_MEMBER
+ // [cfe] Can't break to 'L'.
+ default:
+ break;
+ }
+ return a;
+}
diff --git a/tests/language_2/switch7_negative_test.dart b/tests/language_2/switch7_negative_test.dart
deleted file mode 100644
index 7426f41..0000000
--- a/tests/language_2/switch7_negative_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2011, 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.
-// Illegal to reference a labeled case stmt with break
-
-class Switch7NegativeTest {
- static testMain() {
- var x = 1;
- L:
- while (true) {
- switch (x) {
- L:
- case 1: // Shadowing another label is OK.
- break L; // illegal, can't reference labeled case stmt from break
- }
- }
- }
-}
-
-main() {
- Switch7NegativeTest.testMain();
-}
diff --git a/tests/language_2/switch7_test.dart b/tests/language_2/switch7_test.dart
new file mode 100644
index 0000000..e47d7e5
--- /dev/null
+++ b/tests/language_2/switch7_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+/// Illegal to reference a labeled case statement with break.
+
+main() {
+ var x = 1;
+ L:
+ while (true) {
+ switch (x) {
+ L:
+ case 1: // Shadowing another label is OK.
+ break L; // Illegal, can't reference labeled case from break.
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.BREAK_LABEL_ON_SWITCH_MEMBER
+ // [cfe] Can't break to 'L'.
+ }
+ }
+}
diff --git a/tests/language_2/test_negative_test.dart b/tests/language_2/test_negative_test.dart
deleted file mode 100644
index 831d9dd..0000000
--- a/tests/language_2/test_negative_test.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2011, 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.
-// Dart test program which has a syntax error. This test is to
-// ensure that the resulting parse error message is correctly
-// displayed without being garbled.
-
-class Test {
- static foo() {
- return "hi
- }
- static testMain() {
- List a = {1 : 1};
- List b = {1 : 1};
- return a == b;
- }
-}
-
-main() {
- TestNegativeTest.testMain();
-}
diff --git a/tests/language_2/unary_plus_negative_test.dart b/tests/language_2/unary_plus_negative_test.dart
deleted file mode 100644
index 86f2942..0000000
--- a/tests/language_2/unary_plus_negative_test.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// There is no unary plus operator in Dart.
-
-main() {
- var a = 1;
- var b = +a; /*@compile-error=unspecified*/
-}
diff --git a/tests/language_2/unary_plus_test.dart b/tests/language_2/unary_plus_test.dart
new file mode 100644
index 0000000..ac6e9ce
--- /dev/null
+++ b/tests/language_2/unary_plus_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2019, 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.
+
+/// There is no unary plus operator in Dart.
+
+main() {
+ var a = 1;
+ var b = +a;
+ // ^
+ // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+ // [cfe] '+' is not a prefix operator.
+}
diff --git a/tests/language_2/variance/variance_downwards_inference_test.dart b/tests/language_2/variance/variance_downwards_inference_test.dart
index 7de0e22..b6cd329 100644
--- a/tests/language_2/variance/variance_downwards_inference_test.dart
+++ b/tests/language_2/variance/variance_downwards_inference_test.dart
@@ -26,6 +26,11 @@
void set y(S _value) {}
}
+class D<in T> {
+ D(T x, void Function(T) y) {}
+ void set x(T val) {}
+}
+
main() {
// int <: T <: Object
// Choose int
@@ -41,4 +46,8 @@
// int <: S <: Object
// Choose Object
C<Object, Object> c = new C(3, 3)..x+=1..y="hello";
+
+ // int <: T <: num
+ // Choose num due to contravariant heuristic.
+ D<int> d = new D(3, (num x) {})..x=2.2;
}
diff --git a/tests/language_2/variance/variance_in_field_error_test.dart b/tests/language_2/variance/variance_in_field_error_test.dart
index 2250cda..6419bf6 100644
--- a/tests/language_2/variance/variance_in_field_error_test.dart
+++ b/tests/language_2/variance/variance_in_field_error_test.dart
@@ -9,53 +9,70 @@
class A<in T> {
final T a = null;
// ^
- // [analyzer] unspecified
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
final T Function() b = () => null;
// ^
- // [analyzer] unspecified
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
T get c => null;
- // ^
- // [analyzer] unspecified
- // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+//^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+// ^
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
T d;
- //^
- // [analyzer] unspecified
- // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
covariant T e;
// ^
- // [analyzer] unspecified
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
}
mixin BMixin<in T> {
final T a = null;
// ^
- // [analyzer] unspecified
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
final T Function() b = () => null;
// ^
- // [analyzer] unspecified
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
T get c => null;
- // ^
- // [analyzer] unspecified
- // [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+//^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+// ^
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
T d;
- //^
- // [analyzer] unspecified
- // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
covariant T e;
// ^
- // [analyzer] unspecified
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+ // [cfe] Can't use 'in' type variable 'T' in an 'out' position.
+}
+
+abstract class C<in T> {
+ T get a;
+//^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+// ^
+// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
+}
+
+class D<in T> extends C<T> {
+ var a;
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
}
diff --git a/tests/language_2/variance/variance_in_inference_error_test.dart b/tests/language_2/variance/variance_in_inference_error_test.dart
index 35b994d..b481d4dd 100644
--- a/tests/language_2/variance/variance_in_inference_error_test.dart
+++ b/tests/language_2/variance/variance_in_inference_error_test.dart
@@ -15,51 +15,87 @@
class Middle extends Upper {}
class Lower extends Middle {}
+class ContraBound<in T> {
+ ContraBound(T x, void Function(T) y) {}
+}
+
Exactly<T> inferCovContra<T>(Covariant<T> x, Contravariant<T> y) => new Exactly<T>();
Exactly<T> inferContraContra<T>(Contravariant<T> x, Contravariant<T> y) => new Exactly<T>();
+Exactly<T> inferContraBound<T>(ContraBound<T> x) => new Exactly<T>();
main() {
Exactly<Upper> upper;
+ Exactly<Lower> lower;
+ // T <: Upper and T <: Middle.
+ // We choose Middle.
var inferredMiddle = inferContraContra(Contravariant<Upper>(), Contravariant<Middle>());
upper = inferredMiddle;
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^
+ // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
// [cfe] A value of type 'Exactly<Middle>' can't be assigned to a variable of type 'Exactly<Upper>'.
+ // T <: Upper and T <: Lower.
+ // We choose Lower.
var inferredLower = inferContraContra(Contravariant<Upper>(), Contravariant<Lower>());
upper = inferredLower;
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^
+ // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
// [cfe] A value of type 'Exactly<Lower>' can't be assigned to a variable of type 'Exactly<Upper>'.
// int <: T <: String is not a valid constraint.
inferCovContra(Covariant<int>(), Contravariant<String>());
- // ^
- // [analyzer] unspecified
- // [cfe] The argument type 'Contravariant<String>' can't be assigned to the parameter type 'Contravariant<int>'.
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+// ^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] The argument type 'Contravariant<String>' can't be assigned to the parameter type 'Contravariant<int>'.
// String <: T <: int is not a valid constraint.
inferCovContra(Covariant<String>(), Contravariant<int>());
- // ^
- // [analyzer] unspecified
- // [cfe] The argument type 'Contravariant<int>' can't be assigned to the parameter type 'Contravariant<String>'.
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+// ^^^^^^^^^^^^^^^^^^^^
+// [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+// [cfe] The argument type 'Contravariant<int>' can't be assigned to the parameter type 'Contravariant<String>'.
// Middle <: T <: Lower is not a valid constraint
inferCovContra(Covariant<Middle>(), Contravariant<Lower>());
- // ^
- // [analyzer] unspecified
- // [cfe] The constructor returns type 'Contravariant<Lower>' that isn't of expected type 'Contravariant<Middle>'.
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+// ^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_CAST_NEW_EXPR
+// [cfe] The constructor returns type 'Contravariant<Lower>' that isn't of expected type 'Contravariant<Middle>'.
// Upper <: T <: Lower is not a valid constraint
inferCovContra(Covariant<Upper>(), Contravariant<Lower>());
- // ^
- // [analyzer] unspecified
- // [cfe] The constructor returns type 'Contravariant<Lower>' that isn't of expected type 'Contravariant<Upper>'.
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+// ^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_CAST_NEW_EXPR
+// [cfe] The constructor returns type 'Contravariant<Lower>' that isn't of expected type 'Contravariant<Upper>'.
// Upper <: T <: Middle is not a valid constraint
inferCovContra(Covariant<Upper>(), Contravariant<Middle>());
- // ^
- // [analyzer] unspecified
- // [cfe] The constructor returns type 'Contravariant<Middle>' that isn't of expected type 'Contravariant<Upper>'.
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+// ^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_CAST_NEW_EXPR
+// [cfe] The constructor returns type 'Contravariant<Middle>' that isn't of expected type 'Contravariant<Upper>'.
+
+ // Inference for Contrabound(...) produces Lower <: T <: Upper.
+ // Since T is contravariant, we choose Upper as the solution.
+ var inferredContraUpper = inferContraBound(ContraBound(Lower(), (Upper x) {}));
+ lower = inferredContraUpper;
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+ // [cfe] A value of type 'Exactly<Upper>' can't be assigned to a variable of type 'Exactly<Lower>'.
+
+ // Inference for Contrabound(...) produces Lower <: T <: Middle.
+ // Since T is contravariant, we choose Middle as the solution.
+ var inferredContraMiddle = inferContraBound(ContraBound(Lower(), (Middle x) {}));
+ lower = inferredContraMiddle;
+ // ^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+ // [cfe] A value of type 'Exactly<Middle>' can't be assigned to a variable of type 'Exactly<Lower>'.
}
diff --git a/tests/language_2/variance/variance_in_inference_test.dart b/tests/language_2/variance/variance_in_inference_test.dart
index 742911d..03277fb 100644
--- a/tests/language_2/variance/variance_in_inference_test.dart
+++ b/tests/language_2/variance/variance_in_inference_test.dart
@@ -15,10 +15,16 @@
class Middle extends Upper {}
class Lower extends Middle {}
+class ContraBound<in T> {
+ ContraBound(T x, void Function(T) y) {}
+}
+
Exactly<T> inferCovContra<T>(Covariant<T> x, Contravariant<T> y) => new Exactly<T>();
Exactly<T> inferContraContra<T>(Contravariant<T> x, Contravariant<T> y) => new Exactly<T>();
+Exactly<T> inferContraBound<T>(ContraBound<T> x) => new Exactly<T>();
main() {
+ Exactly<Upper> upper;
Exactly<Middle> middle;
Exactly<Lower> lower;
@@ -57,4 +63,14 @@
// Choose Lower since it is the greatest lower bound of Middle and Lower.
var inferredLower5 = inferContraContra(Contravariant<Lower>(), Contravariant<Middle>());
lower = inferredLower5;
+
+ // Lower <: T <: Upper
+ // Choose Upper.
+ var inferredContraUpper = inferContraBound(ContraBound(Lower(), (Upper x) {}));
+ upper = inferredContraUpper;
+
+ // Lower <: T <: Middle
+ // Choose Middle.
+ var inferredContraMiddle = inferContraBound(ContraBound(Lower(), (Middle x) {}));
+ middle = inferredContraMiddle;
}
diff --git a/tests/language_2/variance/variance_in_method_error_test.dart b/tests/language_2/variance/variance_in_method_error_test.dart
index 98c8033..e7e26c4 100644
--- a/tests/language_2/variance/variance_in_method_error_test.dart
+++ b/tests/language_2/variance/variance_in_method_error_test.dart
@@ -17,40 +17,47 @@
class A<in T> {
// TODO (kallentu): Come NNBD, change `T` to `T?`
T method1() => null;
+//^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
void method2(Contra<T> x) {}
+ // ^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
Cov<T> method3() {
+//^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
return () => null;
}
void method4(Contra<Cov<T>> x) {}
+ // ^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
void method5(Cov<Contra<T>> x) {}
+ // ^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
Contra<Contra<T>> method6() => (Contra<T> x) {};
+//^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
Cov<Cov<T>> method7() {
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
return () {
return () => null;
@@ -58,133 +65,153 @@
}
Inv<T> method8() => null;
+//^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in the return type.
void method9(Inv<T> x) {}
+ // ^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
Covariant<T> method10() => null;
+//^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
void method11(Contravariant<T> x) {}
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
Invariant<T> method12() => null;
+//^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in the return type.
void method13(Invariant<T> x) {}
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
void method14(Contravariant<Covariant<T>> x) {}
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
void method15(Covariant<Contravariant<T>> x) {}
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
Contravariant<Contravariant<T>> method16() => Contravariant<Contravariant<T>>();
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
Covariant<Covariant<T>> method17() => Covariant<Covariant<T>>();
+//^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
void method18<X extends T>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
void method19<X extends Cov<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
void method20<X extends Covariant<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
void method21({Contra<T> x}) {}
+ // ^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
void method22({Contravariant<T> x}) {}
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
void method23({Covariant<T> x, Contravariant<T> y}) {}
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
void method24<X extends Contra<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
void method25<X extends Contravariant<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
}
mixin BMixin<in T> {
// TODO (kallentu): Come NNBD, change `T` to `T?`
T method1() => null;
+//^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
void method2(Contra<T> x) {}
+ // ^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
Cov<T> method3() {
+//^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
return () => null;
}
void method4(Contra<Cov<T>> x) {}
+ // ^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
void method5(Cov<Contra<T>> x) {}
+ // ^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
Contra<Contra<T>> method6() => (Contra<T> x) {};
+//^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
Cov<Cov<T>> method7() {
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
return () {
return () => null;
@@ -192,104 +219,119 @@
}
Inv<T> method8() => null;
+//^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in the return type.
void method9(Inv<T> x) {}
+ // ^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
Covariant<T> method10() => null;
+//^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
void method11(Contravariant<T> x) {}
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
Invariant<T> method12() => null;
+//^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in the return type.
void method13(Invariant<T> x) {}
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
void method14(Contravariant<Covariant<T>> x) {}
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
void method15(Covariant<Contravariant<T>> x) {}
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
Contravariant<Contravariant<T>> method16() => Contravariant<Contravariant<T>>();
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
Covariant<Covariant<T>> method17() => Covariant<Covariant<T>>();
+//^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
void method18<X extends T>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
void method19<X extends Cov<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
void method20<X extends Covariant<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
void method21({Contra<T> x}) {}
+ // ^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
void method22({Contravariant<T> x}) {}
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
void method23({Covariant<T> x, Contravariant<T> y}) {}
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
void method24<X extends Contra<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
void method25<X extends Contravariant<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position.
}
class B<in T> {
void method1(A<T> x) {}
+ // ^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
Contra<A<T>> method2() {
+//^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in the return type.
return null;
}
@@ -302,7 +344,8 @@
class D<in T> extends C<void Function(T)> {
@override
void method(void Function(T) x) {}
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position.
}
diff --git a/tests/language_2/variance/variance_in_subclass_error_test.dart b/tests/language_2/variance/variance_in_subclass_error_test.dart
index 6899685..123b3e5 100644
--- a/tests/language_2/variance/variance_in_subclass_error_test.dart
+++ b/tests/language_2/variance/variance_in_subclass_error_test.dart
@@ -21,103 +21,124 @@
class A<in T> extends LegacyCovariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'LegacyCovariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class B<in T> implements LegacyCovariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'LegacyCovariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class C<in T> with MLegacyCovariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MLegacyCovariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class D<in T> extends Covariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class E<in T> implements Covariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class F<in T> with MCovariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MCovariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class G<in T> extends Invariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'Invariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class H<in T> implements Invariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'Invariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class I<in T> with MInvariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'MInvariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class J<in T> extends Covariant<Covariant<T>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class K<in T> extends Contravariant<Contravariant<T>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Contravariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class L<in T> extends Covariant<CovFunction<T>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class M<in T> extends Covariant<ContraFunction<ContraFunction<T>>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class N<in T> extends Contravariant<CovFunction<Contravariant<T>>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Contravariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class O<in T> extends Covariant<CovFunction<Covariant<T>>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class P<in T> extends Covariant<Covariant<Covariant<T>>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class Q<in T> extends Invariant<InvFunction<T>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'Invariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class R<in T> = Covariant<T> with MContravariant<T>;
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class S<in T> = Contravariant<T> with MCovariant<T>;
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MCovariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class T<in X> = Invariant<X> with MInvariant<X>;
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'X' in an 'inout' position in supertype 'Invariant'.
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'X' in an 'inout' position in supertype 'MInvariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
diff --git a/tests/language_2/variance/variance_inout_inference_error_test.dart b/tests/language_2/variance/variance_inout_inference_error_test.dart
index 361ec92..ce4109f 100644
--- a/tests/language_2/variance/variance_inout_inference_error_test.dart
+++ b/tests/language_2/variance/variance_inout_inference_error_test.dart
@@ -23,38 +23,48 @@
main() {
// Middle <: T <: Middle and int <: T <: int are not valid constraints.
inferInvInv(Invariant<Middle>(), Invariant<int>());
- // ^
- // [analyzer] unspecified
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Object>'.
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^
+ // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'Invariant<int>' can't be assigned to the parameter type 'Invariant<Object>'.
// Middle <: T <: Middle and Upper <: T <: Upper are not valid constraints.
inferInvInv(Invariant<Middle>(), Invariant<Upper>());
- // ^
- // [analyzer] unspecified
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Upper>'.
// Middle <: T <: Middle and Lower <: T <: Lower are not valid constraints.
inferInvInv(Invariant<Middle>(), Invariant<Lower>());
- // ^
- // [analyzer] unspecified
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // ^^^^^^^^^^^^^^^^^^
+ // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'Invariant<Lower>' can't be assigned to the parameter type 'Invariant<Middle>'.
// Upper <: T
// Middle <: T <: Middle
// Upper <: T <: Middle is not a valid constraint.
inferInvCov(Invariant<Middle>(), Covariant<Upper>());
- // ^
- // [analyzer] unspecified
+//^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
// [cfe] The argument type 'Invariant<Middle>' can't be assigned to the parameter type 'Invariant<Upper>'.
// T <: Lower
// Middle <: T <: Lower
// Middle <: T <: Lower is not a valid constraint
inferInvContra(Invariant<Middle>(), Contravariant<Lower>());
- // ^
- // [analyzer] unspecified
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
+ // ^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.INVALID_CAST_NEW_EXPR
// [cfe] The constructor returns type 'Contravariant<Lower>' that isn't of expected type 'Contravariant<Middle>'.
}
diff --git a/tests/language_2/variance/variance_inout_method_test.dart b/tests/language_2/variance/variance_inout_method_test.dart
index 62b1f2e..ae46510 100644
--- a/tests/language_2/variance/variance_inout_method_test.dart
+++ b/tests/language_2/variance/variance_inout_method_test.dart
@@ -273,6 +273,10 @@
F<Object> f = new H<String>((String s) {});
Expect.throws(() => f.method(3));
+
+ // Tests reified type is the type expected for F and not G.
+ Expect.type<int Function(Object)>(f.method);
+ Expect.type<int Function(Object)>(new H<String>((String s){}).method);
}
main() {
diff --git a/tests/language_2/variance/variance_method_tearoff_test.dart b/tests/language_2/variance/variance_method_tearoff_test.dart
new file mode 100644
index 0000000..03261ac
--- /dev/null
+++ b/tests/language_2/variance/variance_method_tearoff_test.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2019, 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 reified types of torn-off methods with type parameters that have
+// explicit variance modifiers.
+
+// SharedOptions=--enable-experiment=variance
+
+import "package:expect/expect.dart";
+
+class Contravariant<in T> {
+ int method(T x) {}
+}
+
+class Invariant<inout T> {
+ T method(T x) {}
+}
+
+class LegacyCovariant<T> {
+ int method(T x) {}
+}
+
+class NoSuchMethod<inout T> implements Invariant<T> {
+ noSuchMethod(_) => 3;
+}
+
+main() {
+ Contravariant<int> contraDiff = new Contravariant<num>();
+ Expect.notType<int Function(Object)>(contraDiff.method);
+ Expect.type<int Function(num)>(contraDiff.method);
+
+ Contravariant<num> contraSame = new Contravariant<num>();
+ Expect.notType<int Function(Object)>(contraSame.method);
+ Expect.type<int Function(num)>(contraSame.method);
+
+ Invariant<num> invSame = new Invariant<num>();
+ Expect.notType<num Function(Object)>(invSame.method);
+ Expect.type<num Function(num)>(invSame.method);
+
+ LegacyCovariant<num> legacyDiff = new LegacyCovariant<int>();
+ Expect.type<int Function(Object)>(legacyDiff.method);
+ Expect.type<int Function(num)>(legacyDiff.method);
+
+ LegacyCovariant<num> legacySame = new LegacyCovariant<num>();
+ Expect.type<int Function(Object)>(legacySame.method);
+ Expect.type<int Function(num)>(legacySame.method);
+
+ NoSuchMethod<num> nsm = new NoSuchMethod<num>();
+ Expect.notType<num Function(Object)>(nsm.method);
+ Expect.type<num Function(num)>(nsm.method);
+}
diff --git a/tests/language_2/variance/variance_multi_subclass_error_test.dart b/tests/language_2/variance/variance_multi_subclass_error_test.dart
index 18e2db2..ed790c7 100644
--- a/tests/language_2/variance/variance_multi_subclass_error_test.dart
+++ b/tests/language_2/variance/variance_multi_subclass_error_test.dart
@@ -17,55 +17,68 @@
class A<in T, out U, inout V> extends Covariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class B<in T> extends MultiThree<T, T, T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'MultiThree'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class C<in T, out U, inout V> extends MultiTwo<U, T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MultiTwo'.
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'U' in an 'in' position in supertype 'MultiTwo'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class D<in T, out U, inout V> extends MultiThree<V, U, T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'inout' position in supertype 'MultiThree'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class E<in T, out U, inout V> extends MultiThree<Covariant<U>, Covariant<T>, Covariant<U>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MultiThree'.
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'U' in an 'inout' position in supertype 'MultiThree'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class F<in T, out U, inout V> extends MultiTwo<Contravariant<T>, Contravariant<U>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MultiTwo'.
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'U' in an 'in' position in supertype 'MultiTwo'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class G<in T, out U, inout V> extends MultiThree<CovFunction<U>, CovFunction<T>, CovFunction<U>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MultiThree'.
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'U' in an 'inout' position in supertype 'MultiThree'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class H<in T, out U, inout V> extends MultiTwo<ContraFunction<T>, ContraFunction<U>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'in' type variable 'T' in an 'out' position in supertype 'MultiTwo'.
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'U' in an 'in' position in supertype 'MultiTwo'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
diff --git a/tests/language_2/variance/variance_out_field_error_test.dart b/tests/language_2/variance/variance_out_field_error_test.dart
index 629cf96..2123b9d 100644
--- a/tests/language_2/variance/variance_out_field_error_test.dart
+++ b/tests/language_2/variance/variance_out_field_error_test.dart
@@ -8,30 +8,46 @@
class A<out T> {
void set a(T value) => value;
+ // ^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
final void Function(T) b = (T val) {};
// ^
- // [analyzer] unspecified
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
T c;
- //^
- // [analyzer] unspecified
- // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
}
mixin BMixin<out T> {
void set a(T value) => value;
+ // ^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
final void Function(T) b = (T val) {};
// ^
- // [analyzer] unspecified
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
T c;
- //^
- // [analyzer] unspecified
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
+}
+
+abstract class C<out T> {
+ void set a(T value) => value;
+ // ^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+ // ^
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
}
+
+class D<out T> extends C<T> {
+ var a;
+ // ^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+}
diff --git a/tests/language_2/variance/variance_out_inference_error_test.dart b/tests/language_2/variance/variance_out_inference_error_test.dart
index cc2f448..809cdfb 100644
--- a/tests/language_2/variance/variance_out_inference_error_test.dart
+++ b/tests/language_2/variance/variance_out_inference_error_test.dart
@@ -14,20 +14,47 @@
class Middle extends Upper {}
class Lower extends Middle {}
+class CovBound<out T> {
+ CovBound(T x, void Function(T) y) {}
+}
+
Exactly<T> inferCovCov<T>(Covariant<T> x, Covariant<T> y) => new Exactly<T>();
+Exactly<T> inferCovBound<T>(CovBound<T> x) => new Exactly<T>();
main() {
+ Exactly<Upper> upper;
+ Exactly<Middle> middle;
Exactly<Lower> lower;
+ // Lower <: T <: Middle.
+ // We choose Middle.
var inferredMiddle = inferCovCov(Covariant<Lower>(), Covariant<Middle>());
lower = inferredMiddle;
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^
+ // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
// [cfe] A value of type 'Exactly<Middle>' can't be assigned to a variable of type 'Exactly<Lower>'.
+ // Lower <: T <: Upper.
+ // We choose Upper.
var inferredUpper = inferCovCov(Covariant<Lower>(), Covariant<Upper>());
lower = inferredUpper;
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^
+ // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
// [cfe] A value of type 'Exactly<Upper>' can't be assigned to a variable of type 'Exactly<Lower>'.
+
+ // Inference for Covbound(...) produces Lower <: T <: Upper.
+ // Since T is covariant, we choose Lower as the solution.
+ var inferredCovLower = inferCovBound(CovBound(Lower(), (Upper x) {}));
+ upper = inferredCovLower;
+ // ^^^^^^^^^^^^^^^^
+ // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+ // [cfe] A value of type 'Exactly<Lower>' can't be assigned to a variable of type 'Exactly<Upper>'.
+
+ // Inference for Covbound(...) produces Lower <: T <: Middle.
+ // Since T is covariant, we choose Lower as the solution.
+ var inferredCovLower2 = inferCovBound(CovBound(Lower(), (Middle x) {}));
+ middle = inferredCovLower2;
+ // ^^^^^^^^^^^^^^^^^
+ // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+ // [cfe] A value of type 'Exactly<Lower>' can't be assigned to a variable of type 'Exactly<Middle>'.
}
diff --git a/tests/language_2/variance/variance_out_inference_test.dart b/tests/language_2/variance/variance_out_inference_test.dart
index 8ba2f49..14b49e1 100644
--- a/tests/language_2/variance/variance_out_inference_test.dart
+++ b/tests/language_2/variance/variance_out_inference_test.dart
@@ -14,10 +14,16 @@
class Middle extends Upper {}
class Lower extends Middle {}
+class CovBound<out T> {
+ CovBound(T x, void Function(T) y) {}
+}
+
Exactly<T> inferCovCov<T>(Covariant<T> x, Covariant<T> y) => new Exactly<T>();
+Exactly<T> inferCovBound<T>(CovBound<T> x) => new Exactly<T>();
main() {
Exactly<Upper> upper;
+ Exactly<Lower> lower;
// Upper <: T
// Upper <: T
@@ -36,4 +42,14 @@
// Choose Upper since it is the lowest upper bound of Upper and Lower.
var inferredUpper3 = inferCovCov(Covariant<Upper>(), Covariant<Lower>());
upper = inferredUpper3;
+
+ // Lower <: T <: Upper
+ // Choose Lower.
+ var inferredCovLower = inferCovBound(CovBound(Lower(), (Upper x) {}));
+ lower = inferredCovLower;
+
+ // Lower <: T <: Middle
+ // Choose Lower.
+ var inferredCovLower2 = inferCovBound(CovBound(Lower(), (Middle x) {}));
+ lower = inferredCovLower2;
}
diff --git a/tests/language_2/variance/variance_out_method_error_test.dart b/tests/language_2/variance/variance_out_method_error_test.dart
index 905763a..1705207 100644
--- a/tests/language_2/variance/variance_out_method_error_test.dart
+++ b/tests/language_2/variance/variance_out_method_error_test.dart
@@ -16,33 +16,39 @@
class A<out T> {
void method1(T x) {}
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method2(Cov<T> x) {}
+ // ^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Contra<T> method3() => (T val) {};
+//^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
void method4(Cov<Cov<T>> x) {}
+ // ^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Contra<Cov<T>> method5() => (Cov<T> method) {};
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
Cov<Contra<T>> method6() {
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
return () {
return (T x) {};
@@ -50,135 +56,156 @@
}
void method7(Contra<Contra<T>> x) {}
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Inv<T> method8() => null;
+//^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in the return type.
void method9(Inv<T> x) {}
+ // ^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
Contravariant<T> method10() => null;
+//^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
void method11(Covariant<T> x) {}
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Invariant<T> method12() => null;
+//^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in the return type.
void method13(Invariant<T> x) {}
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
void method14(Covariant<Covariant<T>> x) {}
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method15(Contravariant<Contravariant<T>> x) {}
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Contravariant<Covariant<T>> method16() => Contravariant<Covariant<T>>();
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
Covariant<Contravariant<T>> method17() => Covariant<Contravariant<T>>();
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
void method18<X extends Contra<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
void method19<X extends Contravariant<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
void method20({T x}) {}
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method21({Cov<T> x}) {}
+ // ^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method22({Covariant<T> x}) {}
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method23({Covariant<T> x, Contravariant<T> y}) {}
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method24<X extends T>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
void method25<X extends Contra<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
void method26<X extends Contravariant<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
}
mixin BMixin<out T> {
void method1(T x) {}
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method2(Cov<T> x) {}
+ // ^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Contra<T> method3() => (T val) {};
+//^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
void method4(Cov<Cov<T>> x) {}
+ // ^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Contra<Cov<T>> method5() => (Cov<T> method) {};
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
Cov<Contra<T>> method6() {
+//^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
return () {
return (T x) {};
@@ -186,114 +213,131 @@
}
void method7(Contra<Contra<T>> x) {}
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Inv<T> method8() => null;
+//^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in the return type.
void method9(Inv<T> x) {}
+ // ^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
Contravariant<T> method10() => null;
+//^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
void method11(Covariant<T> x) {}
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Invariant<T> method12() => null;
+//^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in the return type.
void method13(Invariant<T> x) {}
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
void method14(Covariant<Covariant<T>> x) {}
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method15(Contravariant<Contravariant<T>> x) {}
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Contravariant<Covariant<T>> method16() => Contravariant<Covariant<T>>();
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
Covariant<Contravariant<T>> method17() => Covariant<Contravariant<T>>();
+//^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
void method18<X extends Contra<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
void method19<X extends Contravariant<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
void method20({T x}) {}
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method21({Cov<T> x}) {}
+ // ^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method22({Covariant<T> x}) {}
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method23({Covariant<T> x, Contravariant<T> y}) {}
+ // ^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
void method24<X extends T>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
void method25<X extends Contra<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
void method26<X extends Contravariant<T>>() {}
- // ^
- // [analyzer] unspecified
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position.
}
class B<out T> {
void method1(Cov<A<T>> x) {}
+ // ^^^^^^^^^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
Contra<A<T>> method2() {
+//^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in the return type.
return null;
}
@@ -306,7 +350,8 @@
class D<out T> extends C<T> {
@override
void method(T x) {}
+ // ^^^
+ // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
// ^
- // [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position.
}
diff --git a/tests/language_2/variance/variance_out_subclass_error_test.dart b/tests/language_2/variance/variance_out_subclass_error_test.dart
index a6d783a..046395c 100644
--- a/tests/language_2/variance/variance_out_subclass_error_test.dart
+++ b/tests/language_2/variance/variance_out_subclass_error_test.dart
@@ -19,88 +19,106 @@
class A<out T> extends Contravariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Contravariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class B<out T> implements Contravariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Contravariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class C<out T> with MContravariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'MContravariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class D<out T> extends Invariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in supertype 'Invariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class E<out T> implements Invariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in supertype 'Invariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class F<out T> with MInvariant<T> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'MInvariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class G<out T> extends Covariant<Contravariant<T>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class H<out T> extends Contravariant<Covariant<T>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Contravariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class I<out T> extends Covariant<ContraFunction<T>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class J<out T> extends Covariant<ContraFunction<CovFunction<T>>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class K<out T> extends Covariant<CovFunction<ContraFunction<T>>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class L<out T> extends Covariant<ContraFunction<Covariant<T>>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class M<out T> extends Contravariant<Contravariant<Contravariant<T>>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Contravariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class N<out T> extends Covariant<InvFunction<T>> {}
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in supertype 'Covariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class O<out T> = Covariant<T> with MContravariant<T>;
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'MContravariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class P<out T> = Contravariant<T> with MCovariant<T>;
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'Contravariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
class Q<out T> = Invariant<T> with MInvariant<T>;
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'in' position in supertype 'MInvariant'.
// ^
-// [analyzer] unspecified
// [cfe] Can't use 'out' type variable 'T' in an 'inout' position in supertype 'Invariant'.
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
+// ^
+// [analyzer] COMPILE_TIME_ERROR.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE
diff --git a/tests/language_2/vm/causal_async_exception_stack2_test.dart b/tests/language_2/vm/causal_async_exception_stack2_test.dart
index 94dda4b..4efca8f 100644
--- a/tests/language_2/vm/causal_async_exception_stack2_test.dart
+++ b/tests/language_2/vm/causal_async_exception_stack2_test.dart
@@ -29,11 +29,8 @@
expect(
h.stringContainsInOrder(st.toString(), [
'foo3',
- '<asynchronous suspension>',
'foo2',
- '<asynchronous suspension>',
'foo',
- '<asynchronous suspension>',
'test1',
]),
isTrue);
@@ -47,11 +44,8 @@
expect(
h.stringContainsInOrder(st.toString(), [
'bar3',
- '<asynchronous suspension>',
'bar2',
- '<asynchronous suspension>',
'bar',
- '<asynchronous suspension>',
'test1',
]),
isTrue);
@@ -72,11 +66,8 @@
expect(
h.stringContainsInOrder(st.toString(), [
'foo3',
- '<asynchronous suspension>',
'foo2',
- '<asynchronous suspension>',
'foo',
- '<asynchronous suspension>',
'test2',
]),
isTrue);
@@ -90,11 +81,8 @@
expect(
h.stringContainsInOrder(st.toString(), [
'bar3',
- '<asynchronous suspension>',
'bar2',
- '<asynchronous suspension>',
'bar',
- '<asynchronous suspension>',
'test2',
]),
isTrue);
diff --git a/tests/language_2/vm/causal_async_exception_stack_test.dart b/tests/language_2/vm/causal_async_exception_stack_test.dart
index b4059e9..caba5d9 100644
--- a/tests/language_2/vm/causal_async_exception_stack_test.dart
+++ b/tests/language_2/vm/causal_async_exception_stack_test.dart
@@ -35,11 +35,9 @@
expect(
h.stringContainsInOrder(st.toString(), [
'thrower', '.dart:10', //
- '<asynchronous suspension>', //
'generator', '.dart:19', //
'<asynchronous suspension>', //
'foo', '.dart:23', //
- '<asynchronous suspension>', //
'main', //
]),
isTrue);
@@ -60,11 +58,8 @@
expect(
h.stringContainsInOrder(st.toString(), [
'thrower',
- '<asynchronous suspension>',
'main.<anonymous closure>.inner.deep',
- '<asynchronous suspension>',
'main.<anonymous closure>.inner',
- '<asynchronous suspension>',
'main',
'<asynchronous suspension>',
]),
@@ -78,8 +73,7 @@
expect(
h.stringContainsInOrder(st.toString(), [
'thrower', '.dart:10', //
- '<asynchronous suspension>', //
- 'main.<anonymous closure>', '.dart:76', //
+ 'main.<anonymous closure>', '.dart:71', //
]),
isTrue);
}
diff --git a/tests/language_2/vm/deep_loop_test.dart b/tests/language_2/vm/deep_loop_test.dart
new file mode 100644
index 0000000..dea7d53
--- /dev/null
+++ b/tests/language_2/vm/deep_loop_test.dart
@@ -0,0 +1,363 @@
+// Copyright (c) 2019, 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.
+
+import 'package:expect/expect.dart';
+
+// Stress tests on loop nesting depth. Make sure loop and induction
+// analysis do not break down (excessive compile-time or otherwise)
+// when analyzing a deeply nested loop with dependent bounds.
+
+@pragma("vm:never-inline")
+foo(List<int> a) {
+ for (int i0 = 100; i0 <= a.length - 101; i0++)
+ for (int i1 = i0 - 1; i1 <= i0 + 1; i1++)
+ for (int i2 = i1 - 1; i2 <= i1 + 1; i2++)
+ for (int i3 = i2 - 1; i3 <= i2 + 1; i3++)
+ for (int i4 = i3 - 1; i4 <= i3 + 1; i4++)
+ for (int i5 = i4 - 1; i5 <= i4 + 1; i5++)
+ for (int i6 = i5 - 1; i6 <= i5 + 1; i6++)
+ for (int i7 = i6 - 1; i7 <= i6 + 1; i7++)
+ for (int i8 = i7 - 1; i8 <= i7 + 1; i8++)
+ for (int i9 = i8 - 1; i9 <= i8 + 1; i9++)
+ for (int i10 = i9 - 1; i10 <= i9 + 1; i10++)
+ for (int i11 = i10 - 1; i11 <= i10 + 1; i11++)
+ for (int i12 = i11 - 1; i12 <= i11 + 1; i12++)
+ for (int i13 = i12 - 1; i13 <= i12 + 1; i13++)
+ for (int i14 = i13 - 1; i14 <= i13 + 1; i14++)
+ for (int i15 = i14 - 1; i15 <= i14 + 1; i15++)
+ for (int i16 = i15 - 1; i16 <= i15 + 1; i16++)
+ for (int i17 = i16 - 1;
+ i17 <= i16 + 1;
+ i17++)
+ for (int i18 = i17 - 1;
+ i18 <= i17 + 1;
+ i18++)
+ for (int i19 = i18 - 1;
+ i19 <= i18 + 1;
+ i19++)
+ for (int i20 = i19 - 1;
+ i20 <= i19 + 1;
+ i20++)
+ for (int i21 = i20 - 1;
+ i21 <= i20 + 1;
+ i21++)
+ for (int i22 = i21 - 1;
+ i22 <= i21 + 1;
+ i22++)
+ for (int i23 = i22 - 1;
+ i23 <= i22 + 1;
+ i23++)
+ for (int i24 = i23 - 1;
+ i24 <= i23 + 1;
+ i24++)
+ for (int i25 = i24 - 1;
+ i25 <= i24 + 1;
+ i25++)
+ for (int i26 = i25 - 1;
+ i26 <= i25 + 1;
+ i26++)
+ for (int i27 = i26 - 1;
+ i27 <= i26 + 1;
+ i27++)
+ for (int i28 =
+ i27 - 1;
+ i28 <= i27 + 1;
+ i28++)
+ for (int i29 =
+ i28 - 1;
+ i29 <= i28 + 1;
+ i29++)
+ for (int i30 =
+ i29 - 1;
+ i30 <=
+ i29 + 1;
+ i30++)
+ for (int i31 =
+ i30 - 1;
+ i31 <=
+ i30 + 1;
+ i31++)
+ for (int i32 =
+ i31 -
+ 1;
+ i32 <=
+ i31 +
+ 1;
+ i32++)
+ for (int i33 =
+ i32 -
+ 1;
+ i33 <=
+ i32 +
+ 1;
+ i33++)
+ for (int i34 = i33 -
+ 1;
+ i34 <=
+ i33 + 1;
+ i34++)
+ for (int i35 = i34 -
+ 1;
+ i35 <=
+ i34 + 1;
+ i35++)
+ for (int i36 = i35 - 1;
+ i36 <= i35 + 1;
+ i36++)
+ for (int i37 = i36 - 1;
+ i37 <= i36 + 1;
+ i37++)
+ for (int i38 = i37 - 1; i38 <= i37 + 1; i38++)
+ for (int i39 = i38 - 1; i39 <= i38 + 1; i39++)
+ for (int i40 = i39 - 1; i40 <= i39 + 1; i40++)
+ for (int i41 = i40 - 1; i41 <= i40 + 1; i41++)
+ for (int i42 = i41 - 1; i42 <= i41 + 1; i42++)
+ for (int i43 = i42 - 1; i43 <= i42 + 1; i43++)
+ for (int i44 = i43 - 1; i44 <= i43 + 1; i44++)
+ for (int i45 = i44 - 1; i45 <= i44 + 1; i45++)
+ for (int i46 = i45 - 1; i46 <= i45 + 1; i46++)
+ for (int i47 = i46 - 1; i47 <= i46 + 1; i47++)
+ for (int i48 = i47 - 1; i48 <= i47 + 1; i48++)
+ for (int i49 = i48 - 1; i49 <= i48 + 1; i49++)
+ for (int i50 = i49 - 1; i50 <= i49 + 1; i50++)
+ for (int i51 = i50 - 1; i51 <= i50 + 1; i51++)
+ for (int i52 = i51 - 1; i52 <= i51 + 1; i52++)
+ for (int i53 = i52 - 1; i53 <= i52 + 1; i53++)
+ for (int i54 = i53 - 1; i54 <= i53 + 1; i54++)
+ for (int i55 = i54 - 1; i55 <= i54 + 1; i55++)
+ for (int i56 = i55 - 1; i56 <= i55 + 1; i56++)
+ for (int i57 = i56 - 1; i57 <= i56 + 1; i57++)
+ for (int i58 = i57 - 1; i58 <= i57 + 1; i58++)
+ for (int i59 = i58 - 1; i59 <= i58 + 1; i59++)
+ for (int i60 = i59 - 1; i60 <= i59 + 1; i60++)
+ for (int i61 = i60 - 1; i61 <= i60 + 1; i61++)
+ for (int i62 = i61 - 1; i62 <= i61 + 1; i62++)
+ for (int i63 = i62 - 1; i63 <= i62 + 1; i63++)
+ for (int i64 = i63 - 1; i64 <= i63 + 1; i64++)
+ for (int i65 = i64 - 1; i65 <= i64 + 1; i65++)
+ for (int i66 = i65 - 1; i66 <= i65 + 1; i66++)
+ for (int i67 = i66 - 1; i67 <= i66 + 1; i67++)
+ for (int i68 = i67 - 1; i68 <= i67 + 1; i68++)
+ for (int i69 = i68 - 1; i69 <= i68 + 1; i69++)
+ for (int i70 = i69 - 1; i70 <= i69 + 1; i70++)
+ for (int i71 = i70 - 1; i71 <= i70 + 1; i71++)
+ for (int i72 = i71 - 1; i72 <= i71 + 1; i72++)
+ for (int i73 = i72 - 1; i73 <= i72 + 1; i73++)
+ for (int i74 = i73 - 1; i74 <= i73 + 1; i74++)
+ for (int i75 = i74 - 1; i75 <= i74 + 1; i75++)
+ for (int i76 = i75 - 1; i76 <= i75 + 1; i76++)
+ for (int i77 = i76 - 1; i77 <= i76 + 1; i77++)
+ for (int i78 = i77 - 1; i78 <= i77 + 1; i78++)
+ for (int i79 = i78 - 1; i79 <= i78 + 1; i79++)
+ for (int i80 = i79 - 1; i80 <= i79 + 1; i80++)
+ for (int i81 = i80 - 1; i81 <= i80 + 1; i81++)
+ for (int i82 = i81 - 1; i82 <= i81 + 1; i82++)
+ for (int i83 = i82 - 1; i83 <= i82 + 1; i83++)
+ for (int i84 = i83 - 1; i84 <= i83 + 1; i84++)
+ for (int i85 = i84 - 1; i85 <= i84 + 1; i85++)
+ for (int i86 = i85 - 1; i86 <= i85 + 1; i86++)
+ for (int i87 = i86 - 1; i87 <= i86 + 1; i87++)
+ for (int i88 = i87 - 1; i88 <= i87 + 1; i88++)
+ for (int i89 = i88 - 1; i89 <= i88 + 1; i89++)
+ for (int i90 = i89 - 1; i90 <= i89 + 1; i90++)
+ for (int i91 = i90 - 1; i91 <= i90 + 1; i91++)
+ for (int i92 = i91 - 1; i92 <= i91 + 1; i92++)
+ for (int i93 = i92 - 1; i93 <= i92 + 1; i93++)
+ for (int i94 = i93 - 1; i94 <= i93 + 1; i94++)
+ for (int i95 = i94 - 1; i95 <= i94 + 1; i95++)
+ for (int i96 = i95 - 1; i96 <= i95 + 1; i96++)
+ for (int i97 = i96 - 1; i97 <= i96 + 1; i97++)
+ for (int i98 = i97 - 1; i98 <= i97 + 1; i98++)
+ for (int i99 = i98 - 1; i99 <= i98 + 1; i99++)
+ for (int i100 = i99 - 1; i100 <= i99 + 1; i100++) {
+ // Range [0,a.length).
+ a[i100] += 1;
+ }
+}
+
+@pragma("vm:never-inline")
+bar(List<int> a) {
+ for (int i0 = a.length - 101; i0 >= 100; i0--)
+ for (int i1 = i0 + 1; i1 >= i0 - 1; i1--)
+ for (int i2 = i1 + 1; i2 >= i1 - 1; i2--)
+ for (int i3 = i2 + 1; i3 >= i2 - 1; i3--)
+ for (int i4 = i3 + 1; i4 >= i3 - 1; i4--)
+ for (int i5 = i4 + 1; i5 >= i4 - 1; i5--)
+ for (int i6 = i5 + 1; i6 >= i5 - 1; i6--)
+ for (int i7 = i6 + 1; i7 >= i6 - 1; i7--)
+ for (int i8 = i7 + 1; i8 >= i7 - 1; i8--)
+ for (int i9 = i8 + 1; i9 >= i8 - 1; i9--)
+ for (int i10 = i9 + 1; i10 >= i9 - 1; i10--)
+ for (int i11 = i10 + 1; i11 >= i10 - 1; i11--)
+ for (int i12 = i11 + 1; i12 >= i11 - 1; i12--)
+ for (int i13 = i12 + 1; i13 >= i12 - 1; i13--)
+ for (int i14 = i13 + 1; i14 >= i13 - 1; i14--)
+ for (int i15 = i14 + 1; i15 >= i14 - 1; i15--)
+ for (int i16 = i15 + 1; i16 >= i15 - 1; i16--)
+ for (int i17 = i16 + 1;
+ i17 >= i16 - 1;
+ i17--)
+ for (int i18 = i17 + 1;
+ i18 >= i17 - 1;
+ i18--)
+ for (int i19 = i18 + 1;
+ i19 >= i18 - 1;
+ i19--)
+ for (int i20 = i19 + 1;
+ i20 >= i19 - 1;
+ i20--)
+ for (int i21 = i20 + 1;
+ i21 >= i20 - 1;
+ i21--)
+ for (int i22 = i21 + 1;
+ i22 >= i21 - 1;
+ i22--)
+ for (int i23 = i22 + 1;
+ i23 >= i22 - 1;
+ i23--)
+ for (int i24 = i23 + 1;
+ i24 >= i23 - 1;
+ i24--)
+ for (int i25 = i24 + 1;
+ i25 >= i24 - 1;
+ i25--)
+ for (int i26 = i25 + 1;
+ i26 >= i25 - 1;
+ i26--)
+ for (int i27 = i26 + 1;
+ i27 >= i26 - 1;
+ i27--)
+ for (int i28 =
+ i27 + 1;
+ i28 >= i27 - 1;
+ i28--)
+ for (int i29 =
+ i28 + 1;
+ i29 >= i28 - 1;
+ i29--)
+ for (int i30 =
+ i29 + 1;
+ i30 >=
+ i29 - 1;
+ i30--)
+ for (int i31 =
+ i30 + 1;
+ i31 >=
+ i30 - 1;
+ i31--)
+ for (int i32 =
+ i31 +
+ 1;
+ i32 >=
+ i31 -
+ 1;
+ i32--)
+ for (int i33 =
+ i32 +
+ 1;
+ i33 >=
+ i32 -
+ 1;
+ i33--)
+ for (int i34 = i33 +
+ 1;
+ i34 >=
+ i33 - 1;
+ i34--)
+ for (int i35 = i34 +
+ 1;
+ i35 >=
+ i34 - 1;
+ i35--)
+ for (int i36 = i35 + 1;
+ i36 >= i35 - 1;
+ i36--)
+ for (int i37 = i36 + 1;
+ i37 >= i36 - 1;
+ i37--)
+ for (int i38 = i37 + 1; i38 >= i37 - 1; i38--)
+ for (int i39 = i38 + 1; i39 >= i38 - 1; i39--)
+ for (int i40 = i39 + 1; i40 >= i39 - 1; i40--)
+ for (int i41 = i40 + 1; i41 >= i40 - 1; i41--)
+ for (int i42 = i41 + 1; i42 >= i41 - 1; i42--)
+ for (int i43 = i42 + 1; i43 >= i42 - 1; i43--)
+ for (int i44 = i43 + 1; i44 >= i43 - 1; i44--)
+ for (int i45 = i44 + 1; i45 >= i44 - 1; i45--)
+ for (int i46 = i45 + 1; i46 >= i45 - 1; i46--)
+ for (int i47 = i46 + 1; i47 >= i46 - 1; i47--)
+ for (int i48 = i47 + 1; i48 >= i47 - 1; i48--)
+ for (int i49 = i48 + 1; i49 >= i48 - 1; i49--)
+ for (int i50 = i49 + 1; i50 >= i49 - 1; i50--)
+ for (int i51 = i50 + 1; i51 >= i50 - 1; i51--)
+ for (int i52 = i51 + 1; i52 >= i51 - 1; i52--)
+ for (int i53 = i52 + 1; i53 >= i52 - 1; i53--)
+ for (int i54 = i53 + 1; i54 >= i53 - 1; i54--)
+ for (int i55 = i54 + 1; i55 >= i54 - 1; i55--)
+ for (int i56 = i55 + 1; i56 >= i55 - 1; i56--)
+ for (int i57 = i56 + 1; i57 >= i56 - 1; i57--)
+ for (int i58 = i57 + 1; i58 >= i57 - 1; i58--)
+ for (int i59 = i58 + 1; i59 >= i58 - 1; i59--)
+ for (int i60 = i59 + 1; i60 >= i59 - 1; i60--)
+ for (int i61 = i60 + 1; i61 >= i60 - 1; i61--)
+ for (int i62 = i61 + 1; i62 >= i61 - 1; i62--)
+ for (int i63 = i62 + 1; i63 >= i62 - 1; i63--)
+ for (int i64 = i63 + 1; i64 >= i63 - 1; i64--)
+ for (int i65 = i64 + 1; i65 >= i64 - 1; i65--)
+ for (int i66 = i65 + 1; i66 >= i65 - 1; i66--)
+ for (int i67 = i66 + 1; i67 >= i66 - 1; i67--)
+ for (int i68 = i67 + 1; i68 >= i67 - 1; i68--)
+ for (int i69 = i68 + 1; i69 >= i68 - 1; i69--)
+ for (int i70 = i69 + 1; i70 >= i69 - 1; i70--)
+ for (int i71 = i70 + 1; i71 >= i70 - 1; i71--)
+ for (int i72 = i71 + 1; i72 >= i71 - 1; i72--)
+ for (int i73 = i72 + 1; i73 >= i72 - 1; i73--)
+ for (int i74 = i73 + 1; i74 >= i73 - 1; i74--)
+ for (int i75 = i74 + 1; i75 >= i74 - 1; i75--)
+ for (int i76 = i75 + 1; i76 >= i75 - 1; i76--)
+ for (int i77 = i76 + 1; i77 >= i76 - 1; i77--)
+ for (int i78 = i77 + 1; i78 >= i77 - 1; i78--)
+ for (int i79 = i78 + 1; i79 >= i78 - 1; i79--)
+ for (int i80 = i79 + 1; i80 >= i79 - 1; i80--)
+ for (int i81 = i80 + 1; i81 >= i80 - 1; i81--)
+ for (int i82 = i81 + 1; i82 >= i81 - 1; i82--)
+ for (int i83 = i82 + 1; i83 >= i82 - 1; i83--)
+ for (int i84 = i83 + 1; i84 >= i83 - 1; i84--)
+ for (int i85 = i84 + 1; i85 >= i84 - 1; i85--)
+ for (int i86 = i85 + 1; i86 >= i85 - 1; i86--)
+ for (int i87 = i86 + 1; i87 >= i86 - 1; i87--)
+ for (int i88 = i87 + 1; i88 >= i87 - 1; i88--)
+ for (int i89 = i88 + 1; i89 >= i88 - 1; i89--)
+ for (int i90 = i89 + 1; i90 >= i89 - 1; i90--)
+ for (int i91 = i90 + 1; i91 >= i90 - 1; i91--)
+ for (int i92 = i91 + 1; i92 >= i91 - 1; i92--)
+ for (int i93 = i92 + 1; i93 >= i92 - 1; i93--)
+ for (int i94 = i93 + 1; i94 >= i93 - 1; i94--)
+ for (int i95 = i94 + 1; i95 >= i94 - 1; i95--)
+ for (int i96 = i95 + 1; i96 >= i95 - 1; i96--)
+ for (int i97 = i96 + 1; i97 >= i96 - 1; i97--)
+ for (int i98 = i97 + 1; i98 >= i97 - 1; i98--)
+ for (int i99 = i98 + 1; i99 >= i98 - 1; i99--)
+ for (int i100 = i99 + 1; i100 >= i99 - 1; i100--) {
+ // Range [0,a.length).
+ a[i100] += 1;
+ }
+}
+
+main() {
+ // To avoid executing the deep loops completely, we pass in a list
+ // with null values, so that each first iteration throws an exception.
+ List<int> a = new List<int>(300);
+ int tryCallingPlusOnNull = 0;
+ try {
+ foo(a);
+ } on NoSuchMethodError catch (e) {
+ ++tryCallingPlusOnNull;
+ }
+ try {
+ bar(a);
+ } on NoSuchMethodError catch (e) {
+ ++tryCallingPlusOnNull;
+ }
+ Expect.equals(2, tryCallingPlusOnNull);
+}
diff --git a/tests/language_2/vm/regression_39071.dart b/tests/language_2/vm/regression_39071_test.dart
similarity index 100%
rename from tests/language_2/vm/regression_39071.dart
rename to tests/language_2/vm/regression_39071_test.dart
diff --git a/tests/language_2/vm/regression_39193_test.dart b/tests/language_2/vm/regression_39193_test.dart
new file mode 100644
index 0000000..bf48765
--- /dev/null
+++ b/tests/language_2/vm/regression_39193_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, 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.
+
+// VMOptions=--optimization_counter_threshold=1
+
+// Found by DartFuzzing: would assert during OSR:
+// https://github.com/dart-lang/sdk/issues/39193
+
+Map<int, Set<int>> var75 = {};
+
+main() {
+ try {} catch (e, st) {} finally {
+ print('before');
+ var75[42] = (false
+ ? const {}
+ : {for (int loc1 = 0; loc1 < 1; loc1++) (-9223372034707292161 >> 165)});
+ print('after');
+ }
+}
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
new file mode 100644
index 0000000..0dd8e28
--- /dev/null
+++ b/tests/lib/analyzer/analyze_library.status
@@ -0,0 +1,6 @@
+# Copyright (c) 2012, 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.
+
+[ $compiler == dart2analyzer ]
+*: Skip
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
new file mode 100644
index 0000000..a592e6a
--- /dev/null
+++ b/tests/lib/lib.status
@@ -0,0 +1,125 @@
+# Copyright (c) 2017, 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.
+html/cross_frame_test: Skip # Issue 32039, test reloads itself (not by design - investigate)
+wasm/*: Skip # dart:wasm is currently behind a Dart SDK build flag.
+
+[ $arch == simarm64 ]
+convert/utf85_test: Skip # Pass, Slow Issue 20111.
+
+[ $mode == product ]
+developer/timeline_test: Skip # Not supported
+isolate/issue_24243_parent_isolate_test: Skip # Requires checked mode
+
+[ $runtime == ff ]
+convert/streamed_conversion_utf8_decode_test: Slow # Issue 12029
+mirrors/mirrors_reader_test: Slow # Issue 16589
+
+[ $runtime == ie11 ]
+html/request_animation_frame_test: Skip # Times out. Issue 22167
+html/transition_event_test: Skip # Times out. Issue 22167
+
+[ $runtime == safari ]
+html/indexeddb_1_test/functional: Skip # Times out. Issue 21433
+html/indexeddb_3_test: Skip # Times out 1 out of 10.
+html/worker_api_test: Skip # Issue 13221
+
+[ $system == windows ]
+html/xhr_test/xhr: Skip # Times out. Issue 21527
+
+[ $csp ]
+isolate/deferred_in_isolate2_test: Skip # Issue 16898. Deferred loading does not work from an isolate in CSP-mode
+
+[ $runtime == chrome && $system == linux ]
+mirrors/native_class_test: Slow
+
+[ $runtime == chrome && $system == macos ]
+convert/streamed_conversion_utf8_encode_test: SkipSlow # Times out. Issue 22050
+html/canvasrenderingcontext2d_test/drawImage_video_element: Skip # Times out. Please triage this failure.
+html/canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Skip # Times out. Please triage this failure.
+html/request_animation_frame_test: Skip # Times out. Issue 22167
+html/transition_event_test: Skip # Times out. Issue 22167
+
+[ $runtime != dart_precompiled && ($runtime != vm || $compiler != dartk && $compiler != none) ]
+isolate/vm_rehash_test: SkipByDesign
+
+[ $arch == simarm || $arch == simarmv6 ]
+convert/utf85_test: Skip # Pass, Slow Issue 12644.
+
+[ $arch != x64 || $compiler == dartkb || $runtime != vm ]
+isolate/int32_length_overflow_test: SkipSlow
+
+[ $compiler != none || $runtime != vm ]
+isolate/package_config_test: SkipByDesign # Uses Isolate.packageConfig
+isolate/package_resolve_test: SkipByDesign # Uses Isolate.resolvePackageUri
+isolate/package_root_test: SkipByDesign # Uses Isolate.packageRoot
+isolate/scenarios/*: SkipByDesign # Use automatic package resolution, spawnFunction and .dart URIs.
+isolate/spawn_uri_fail_test: SkipByDesign # Uses dart:io.
+
+[ $mode == product || $runtime != vm ]
+isolate/checked_test: Skip # Unsupported.
+
+[ $runtime == chrome || $runtime == ff ]
+async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
+async/stream_timeout_test: SkipSlow # Times out. Issue 22050
+
+[ $runtime == dart_precompiled || $runtime == vm ]
+isolate/isolate_stress_test: Skip # Issue 12588: Uses dart:html. This should be able to pass when we have wrapper-less tests.
+
+# It makes no sense to run any test that uses spawnURI under the simulator
+# as that would involve running CFE (the front end) in simulator mode
+# to compile the URI file specified in spawnURI code.
+# These Isolate tests that use spawnURI are hence skipped on purpose.
+[ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64) ]
+isolate/count_test: Skip # Isolate.spawnUri
+isolate/cross_isolate_message_test: Skip # Isolate.spawnUri
+isolate/deferred_in_isolate2_test: Skip # Isolate.spawnUri
+isolate/deferred_in_isolate_test: Skip # Isolate.spawnUri
+isolate/error_at_spawnuri_test: Skip # Isolate.spawnUri
+isolate/error_exit_at_spawnuri_test: Skip # Isolate.spawnUri
+isolate/exit_at_spawnuri_test: Skip # Isolate.spawnUri
+isolate/illegal_msg_function_test: Skip # Isolate.spawnUri
+isolate/illegal_msg_mirror_test: Skip # Isolate.spawnUri
+isolate/isolate_complex_messages_test: Skip # Isolate.spawnUri
+isolate/issue_21398_parent_isolate1_test: Skip # Isolate.spawnUri
+isolate/issue_21398_parent_isolate_test: Skip # Isolate.spawnUri
+isolate/issue_24243_parent_isolate_test: Skip # Isolate.spawnUri
+isolate/issue_6610_test: Skip # Isolate.spawnUri
+isolate/mandel_isolate_test: Skip # Isolate.spawnUri
+isolate/message2_test: Skip # Isolate.spawnUri
+isolate/message_test: Skip # Isolate.spawnUri
+isolate/mint_maker_test: Skip # Isolate.spawnUri
+isolate/nested_spawn2_test: Skip # Isolate.spawnUri
+isolate/nested_spawn_test: Skip # Isolate.spawnUri
+isolate/raw_port_test: Skip # Isolate.spawnUri
+isolate/request_reply_test: Skip # Isolate.spawnUri
+isolate/spawn_function_custom_class_test: Skip # Isolate.spawnUri
+isolate/spawn_function_test: Skip # Isolate.spawnUri
+isolate/spawn_uri_exported_main_test: Skip # Isolate.spawnUri
+isolate/spawn_uri_missing_from_isolate_test: Skip # Isolate.spawnUri
+isolate/spawn_uri_missing_test: Skip # Isolate.spawnUri
+isolate/spawn_uri_multi_test: Skip # Isolate.spawnUri
+isolate/spawn_uri_nested_vm_test: Skip # Isolate.spawnUri
+isolate/spawn_uri_test: Skip # Isolate.spawnUri
+isolate/spawn_uri_vm_test: Skip # Isolate.spawnUri
+isolate/stacktrace_message_test: Skip # Isolate.spawnUri
+isolate/static_function_test: Skip # Isolate.spawnUri
+isolate/unresolved_ports_test: Skip # Isolate.spawnUri
+
+[ $hot_reload || $hot_reload_rollback ]
+convert/chunked_conversion_utf88_test: SkipSlow
+convert/utf85_test: SkipSlow
+isolate/deferred_in_isolate2_test: Crash # Requires deferred libraries
+isolate/deferred_in_isolate_test: Crash # Requires deferred libraries
+isolate/issue_21398_parent_isolate2_test: Crash # Requires deferred libraries
+isolate/spawn_uri_nested_vm_test: Crash # Issue 28192
+mirrors/closurization_equivalence_test: SkipByDesign # Method equality
+mirrors/deferred_constraints_constants_test: Crash # Requires deferred libraries
+mirrors/deferred_mirrors_metadata_test: Crash # Deferred loading
+mirrors/deferred_mirrors_metatarget_test: Crash # Deferred loading
+mirrors/deferred_mirrors_update_test: Crash # Deferred loading
+mirrors/library_enumeration_deferred_loading_test: Crash # Deferred loading
+mirrors/library_import_deferred_loading_test: Crash # Deferred loading
+mirrors/library_imports_deferred_test: Crash # Deferred loading
+mirrors/load_library_test: Crash # Deferred loading
+mirrors/typedef_deferred_library_test: Crash # Deferred loading
diff --git a/tests/lib/lib_analyzer.status b/tests/lib/lib_analyzer.status
new file mode 100644
index 0000000..113c571
--- /dev/null
+++ b/tests/lib/lib_analyzer.status
@@ -0,0 +1,6 @@
+# Copyright (c) 2017, 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.
+
+[ $compiler == dart2analyzer ]
+html/js_function_getter_trust_types_test: Skip # dart2js specific flags.
diff --git a/tests/lib/lib_app_jit.status b/tests/lib/lib_app_jit.status
new file mode 100644
index 0000000..cb39a57
--- /dev/null
+++ b/tests/lib/lib_app_jit.status
@@ -0,0 +1,6 @@
+# Copyright (c) 2017, 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.
+
+[ $compiler == app_jitk ]
+mirrors/*: Skip # Issue 27929: Triage
diff --git a/tests/lib/lib_dart2js.status b/tests/lib/lib_dart2js.status
new file mode 100644
index 0000000..cc91517
--- /dev/null
+++ b/tests/lib/lib_dart2js.status
@@ -0,0 +1,98 @@
+# Copyright (c) 2017, 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.
+
+[ $compiler == dart2js ]
+convert/chunked_conversion_utf88_test: Slow
+convert/utf85_test: Slow
+developer/timeline_test: Skip # Not supported
+html/async_test: SkipByDesign
+html/custom/document_register_basic_test: Slow
+html/custom/document_register_type_extensions_test/construction: Slow
+html/custom/document_register_type_extensions_test/registration: Slow
+html/custom/entered_left_view_test/shadow_dom: Slow
+html/custom/js_custom_test: Skip # mirrors not supported, delete this test.
+html/custom/mirrors_2_test: Skip # mirrors not supported, delete this test.
+html/custom/mirrors_test: Skip # mirrors not supported, delete this test.
+html/custom_elements_test: Slow # Issue 26789
+html/isolates_test: SkipByDesign
+html/mirrors_js_typed_interop_test: Skip # mirrors not supported, delete this test.
+html/worker_api_test: SkipByDesign
+html/wrapping_collections_test: SkipByDesign # Testing an issue that is only relevant to Dartium
+html/xhr_test: Slow
+isolate/*: SkipByDesign # No support for dart:isolate in dart4web (http://dartbug.com/30538)
+mirrors/*: SkipByDesign # Mirrors not supported on web in Dart 2.0.
+profiler/metrics_num_test: Skip # Because of an int / double type test.
+wasm/*: SkipByDesign # dart:wasm not currently supported on web.
+
+[ $compiler != dart2js ]
+async/dart2js_uncaught_error_test: Skip # JS-integration only test
+
+[ $compiler == dart2js && $runtime == chrome ]
+async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
+convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Times out. Issue 22050
+convert/streamed_conversion_json_utf8_encode_test: SkipSlow # Times out. Issue 22050
+convert/streamed_conversion_utf8_decode_test: SkipSlow # Times out. Issue 22050
+
+[ $compiler == dart2js && $runtime == chromeOnAndroid ]
+html/crypto_test/functional: Slow # TODO(dart2js-team): Please triage this failure.
+html/input_element_datetime_test: Slow # TODO(dart2js-team): Please triage this failure.
+
+[ $compiler == dart2js && $runtime == d8 ]
+html/event_callback_test: Skip # Browser test
+
+[ $compiler == dart2js && $runtime == ff ]
+async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
+convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Times out. Issue 22050
+convert/streamed_conversion_json_utf8_encode_test: SkipSlow # Times out. Issue 22050
+convert/streamed_conversion_utf8_decode_test: SkipSlow # Times out. Issue 22050
+convert/utf85_test: Slow
+html/callback_list_test: SkipByDesign # FileSystem not supported in FireFox.
+html/custom/attribute_changed_callback_test: Skip # Times out
+html/custom/created_callback_test: Skip # Times out
+html/custom/document_register_basic_test: Skip # Times out, or unittest times out
+html/dart_object_local_storage_test: Skip # sessionStorage NS_ERROR_DOM_NOT_SUPPORTED_ERR
+html/file_sample_test: Skip # FileSystem not supported on FireFox.
+html/fileapi_supported_test: Skip # FileSystem not supported on FireFox.
+html/fileapi_supported_throws_test: Skip # FileSystem not supported on FireFox.
+html/history_test/history: Skip # Issue 22050
+html/request_animation_frame_test: Skip # Async test hangs.
+
+[ $compiler == dart2js && $runtime == safari ]
+html/callback_list_test: SkipByDesign # FileSystem not supported in Safari.
+html/file_sample_test: Skip # FileSystem not supported on Safari.
+html/fileapi_supported_throws_test: Skip # FileSystem not supported on Safari
+html/interactive_media_test: SkipSlow
+
+[ $compiler == dart2js && $system == linux ]
+html/interactive_geolocation_test: Skip # Requires allowing geo location.
+
+[ $compiler == dart2js && $checked ]
+convert/utf85_test: Slow # Issue 12029.
+html/js_function_getter_trust_types_test: Skip # --trust-type-annotations incompatible with --checked
+
+[ $compiler == dart2js && $csp && ($runtime == chrome || $runtime == chromeOnAndroid || $runtime == ff || $runtime == safari) ]
+html/event_customevent_test: SkipByDesign
+html/js_array_test: SkipByDesign
+html/js_dart_to_string_test: SkipByDesign
+html/js_function_getter_test: SkipByDesign
+html/js_function_getter_trust_types_test: SkipByDesign
+html/js_interop_1_test: SkipByDesign
+html/js_typed_interop_bind_this_test: SkipByDesign
+html/js_typed_interop_callable_object_test: SkipByDesign
+html/js_typed_interop_default_arg_test: SkipByDesign
+html/js_typed_interop_test: SkipByDesign
+html/js_typed_interop_type1_test: SkipByDesign
+html/js_typed_interop_type3_test: SkipByDesign
+html/js_typed_interop_type_test: SkipByDesign
+html/js_typed_interop_window_property_test: SkipByDesign
+html/js_util_test: SkipByDesign
+html/mirrors_js_typed_interop_test: SkipByDesign
+html/postmessage_structured_test: SkipByDesign
+
+[ $compiler == dart2js && ($runtime == chrome || $runtime == ff) ]
+async/slow_consumer2_test: SkipSlow # Times out. Issue 22050
+convert/streamed_conversion_json_utf8_decode_test: SkipSlow # Times out. Issue 22050
+convert/streamed_conversion_json_utf8_encode_test: SkipSlow # Times out. Issue 22050
+convert/streamed_conversion_utf8_decode_test: SkipSlow # Times out. Issue 22050
+
diff --git a/tests/lib/lib_dartdevc.status b/tests/lib/lib_dartdevc.status
new file mode 100644
index 0000000..b3c2a53
--- /dev/null
+++ b/tests/lib/lib_dartdevc.status
@@ -0,0 +1,49 @@
+# Copyright (c) 2017, 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.
+
+[ $compiler == dartdevc ]
+html/xhr_test: Slow
+
+[ $runtime == chrome && ($compiler == dartdevc || $compiler == dartdevk) ]
+html/js_dispatch_property_test: Skip # Timeout Issue 31030
+
+[ $system == linux && ($compiler == dartdevc || $compiler == dartdevk) ]
+html/interactive_geolocation_test: Skip # Requires allowing geo location.
+
+[ $system == macos && ($compiler == dartdevc || $compiler == dartdevk) ]
+html/interactive_media_test: Skip # Requires interactive camera, microphone permissions.
+
+[ $system == windows && ($compiler == dartdevc || $compiler == dartdevk) ]
+html/xhr_test: Skip # Times out. Issue 21527
+
+[ $compiler == dartdevc || $compiler == dartdevk ]
+convert/chunked_conversion_utf88_test: Slow
+convert/json_utf8_chunk_test: Slow
+convert/streamed_conversion_utf8_decode_test: Slow # Issue 29922
+convert/utf85_test: Slow
+html/callback_list_test: Skip # Test requires user interaction to accept permissions.
+html/custom/attribute_changed_callback_test: Skip # Issue 31577
+html/custom/constructor_calls_created_synchronously_test: Skip # Issue 31577
+html/custom/created_callback_test: Skip # Issue 31577
+html/custom/document_register_basic_test: Skip # Issue 31577
+html/custom/document_register_template_test: Skip # Issue 31577
+html/custom/document_register_type_extensions_test/construction: Skip # Issue 31577
+html/custom/document_register_type_extensions_test/constructors: Skip # Issue 31577
+html/custom/document_register_type_extensions_test/createElement with type extension: Skip # Issue 31577
+html/custom/document_register_type_extensions_test/functional: Skip # Issue 31577
+html/custom/document_register_type_extensions_test/namespaces: Skip # Issue 31577
+html/custom/document_register_type_extensions_test/parsing: Skip # Issue 31577
+html/custom/document_register_type_extensions_test/registration: Skip # Issue 31577
+html/custom/document_register_type_extensions_test/single-parameter createElement: Skip # Issue 31577
+html/custom/element_upgrade_test: Skip # Issue 31577
+html/custom/entered_left_view_test: Skip # Issue 31577
+html/custom/mirrors_2_test: Skip # Issue 31577
+html/custom_element_method_clash_test: Skip # Issue 29922
+html/custom_element_name_clash_test: Skip # Issue 29922
+html/custom_elements_23127_test: Skip # Issue 29922
+html/custom_elements_test: Skip # Issue 29922
+html/notification_permission_test: Skip # Issue 32002
+isolate/*: SkipByDesign # No support for dart:isolate in dart4web (http://dartbug.com/30538)
+mirrors/*: SkipByDesign # Mirrors not supported on web in Dart 2.0.
+profiler/metrics_num_test: Skip # Because of an int / double type test.
diff --git a/tests/lib/lib_kernel.status b/tests/lib/lib_kernel.status
new file mode 100644
index 0000000..1c24f7b
--- /dev/null
+++ b/tests/lib/lib_kernel.status
@@ -0,0 +1,76 @@
+# Copyright (c) 2017, 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.
+# Sections in this file should contain "$compiler == dartk" or
+# "$compiler == dartkp".
+
+isolate/ping_pause_test: Skip # Issue https://dartbug.com/37787
+
+[ $compiler == dartkb ]
+isolate/isolate_complex_messages_test: Crash # runtime/vm/object.cc: 17395: error: expected: type_arguments.IsNull() || type_arguments.IsCanonical()
+
+[ $compiler == fasta ]
+html/*: Skip # TODO(ahe): Make dart:html available.
+js/*: Skip # TODO(ahe): Make dart:js available.
+
+[ $arch == x64 && $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+mirrors/invocation_fuzz_test: Skip # Because it times out, issue 29439.
+
+[ $arch == x64 && ($hot_reload || $hot_reload_rollback) ]
+convert/base64_test/01: Crash # http://dartbug.com/35948
+
+[ $builder_tag == optimization_counter_threshold && ($compiler == dartk || $compiler == dartkb) ]
+mirrors/invocation_fuzz_test/emptyarray: Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
+mirrors/invocation_fuzz_test/false: Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
+mirrors/invocation_fuzz_test/none: Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
+mirrors/invocation_fuzz_test/smi: Crash # Crashes on opt counter builder (#31838)
+mirrors/invocation_fuzz_test/string: Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
+
+[ $compiler == app_jitk && ($mode == product || $mode == release) ]
+isolate/spawn_uri_nested_vm_test: Skip # Timeout, Issue 33385
+
+[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
+isolate/static_function_test: Skip # Flaky (https://github.com/dart-lang/sdk/issues/30063).
+
+# ===== dartkp + dart_precompiled status lines =====
+[ $compiler == dartkp && $runtime == dart_precompiled ]
+html/*: SkipByDesign # dart:html not supported on VM.
+isolate/deferred_in_isolate2_test: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/deferred_in_isolate_test: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/issue_21398_parent_isolate2_test/01: Skip # Times out. Deferred loading kernel issue 28335.
+mirrors/*: SkipByDesign # Mirrors are not supported in AOT mode.
+
+[ $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+mirrors/other_declarations_location_test: Crash # Issue 33325 (assertion error, TypeParameter not having position).
+
+[ $mode == debug && $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
+isolate/message3_test/constList_identical: Skip # Timeout
+
+# ===== dartk + vm status lines =====
+[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+html/*: SkipByDesign # dart:html not supported on VM.
+isolate/deferred_in_isolate2_test: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/deferred_in_isolate_test: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/issue_21398_parent_isolate2_test/01: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/static_function_test: Skip # Times out. Issue 31855. CompileTimeError. Issue 31402
+mirrors/invocation_fuzz_test: Crash
+mirrors/metadata_allowed_values_test/16: Skip # Flaky, crashes.
+mirrors/mirrors_used*: SkipByDesign # Invalid tests. MirrorsUsed does not have a specification, and dart:mirrors is not required to hide declarations that are not covered by any MirrorsUsed annotation.
+mirrors/native_class_test: SkipByDesign # Imports dart:html
+
+[ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
+isolate/illegal_msg_function_test: Skip # Timeout
+isolate/pause_test: Skip # Timeout
+
+[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
+isolate/message4_test: Crash # Timeout and sporadic crash (issue 33824)
+mirrors/dynamic_load_test: Skip # Reload has an effect similar to deleting the dynamically loaded library
+mirrors/immutable_collections_test: Pass, Slow
+mirrors/mirrors_reader_test: Pass, Slow
+
+[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkb || $compiler == dartkp ]
+html/*: SkipByDesign
+js/*: SkipByDesign
+
+[ $hot_reload || $hot_reload_rollback ]
+isolate/issue_6610_test: Skip # Sources are looked up on every reload request.
diff --git a/tests/lib/lib_precompiled.status b/tests/lib/lib_precompiled.status
new file mode 100644
index 0000000..5f9922d
--- /dev/null
+++ b/tests/lib/lib_precompiled.status
@@ -0,0 +1,9 @@
+# Copyright (c) 2017, 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.
+
+[ $compiler == none ]
+async/future_or_strong_test: RuntimeError
+isolate/compile_time_error_test/01: Skip # Issue 12587
+isolate/ping_test: Skip # Resolve test issues
+mirrors/symbol_validation_test: RuntimeError # Issue 13596
diff --git a/tests/lib/lib_vm.status b/tests/lib/lib_vm.status
new file mode 100644
index 0000000..aba92ff
--- /dev/null
+++ b/tests/lib/lib_vm.status
@@ -0,0 +1,86 @@
+# Copyright (c) 2017, 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.
+
+[ $runtime != vm ]
+isolate/native_wrapper_message_test: Skip # A VM specific test.
+
+[ $arch == arm64 && $runtime == vm ]
+mirrors/immutable_collections_test: Pass, Slow # http://dartbug.com/33057
+
+[ $arch == ia32 && $mode == debug && $runtime == vm && $system == windows ]
+convert/streamed_conversion_json_utf8_decode_test: Skip # Verification OOM.
+
+[ $arch != ia32 && $arch != simarm && $arch != simarmv6 && $arch != x64 && $mode == debug && $runtime == vm ]
+convert/streamed_conversion_json_utf8_decode_test: Skip # Verification not yet implemented.
+
+[ $arch == simarm64 && $runtime == vm ]
+convert/utf85_test: Skip # Pass, Slow Issue 20111.
+
+[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm ]
+async/future_or_only_in_async_test/00: MissingCompileTimeError
+convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Infrequent timeouts.
+html/*: SkipByDesign # dart:html not supported on VM.
+js/datetime_roundtrip_test: CompileTimeError
+js/null_test: CompileTimeError
+js/prototype_access_test: CompileTimeError
+mirrors/deferred_type_test: CompileTimeError
+mirrors/generic_bounded_by_type_parameter_test/02: MissingCompileTimeError
+mirrors/generic_bounded_test/01: MissingCompileTimeError
+mirrors/generic_bounded_test/02: MissingCompileTimeError
+mirrors/generic_interface_test/01: MissingCompileTimeError
+mirrors/generics_test/01: MissingCompileTimeError
+mirrors/initializing_formals_test/01: Fail # initializing formals are implicitly final as of Dart 1.21
+mirrors/metadata_nested_constructor_call_test/none: CompileTimeError
+mirrors/mirrors_used*: SkipByDesign # Invalid tests. MirrorsUsed does not have a specification, and dart:mirrors is not required to hide declarations that are not covered by any MirrorsUsed annotation.
+mirrors/native_class_test: SkipByDesign # Imports dart:html
+mirrors/redirecting_factory_different_type_test/01: MissingCompileTimeError
+mirrors/redirecting_factory_test/01: RuntimeError
+mirrors/redirecting_factory_test/none: RuntimeError
+
+[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm && !$checked ]
+mirrors/inference_and_no_such_method_test: RuntimeError
+
+[ $runtime == vm && $system == fuchsia ]
+async/first_regression_test: RuntimeError
+async/future_timeout_test: RuntimeError
+async/schedule_microtask2_test: RuntimeError
+async/schedule_microtask3_test: RuntimeError
+async/schedule_microtask5_test: RuntimeError
+async/stream_controller_async_test: RuntimeError
+async/stream_first_where_test: RuntimeError
+async/stream_iterator_test: RuntimeError
+async/stream_join_test: RuntimeError
+async/stream_last_where_test: RuntimeError
+async/stream_periodic2_test: RuntimeError
+async/stream_periodic3_test: RuntimeError
+async/stream_periodic4_test: RuntimeError
+async/stream_periodic5_test: RuntimeError
+async/stream_periodic6_test: RuntimeError
+async/stream_periodic_test: RuntimeError
+async/stream_single_test: RuntimeError
+async/stream_single_to_multi_subscriber_test: RuntimeError
+async/stream_state_nonzero_timer_test: RuntimeError
+async/stream_state_test: RuntimeError
+async/stream_subscription_as_future_test: RuntimeError
+async/stream_subscription_cancel_test: RuntimeError
+async/stream_transform_test: RuntimeError
+async/stream_transformation_broadcast_test: RuntimeError
+async/timer_cancel1_test: RuntimeError
+async/timer_cancel2_test: RuntimeError
+async/timer_cancel_test: RuntimeError
+async/timer_isActive_test: RuntimeError
+async/timer_repeat_test: RuntimeError
+async/timer_test: RuntimeError
+convert/json_lib_test: RuntimeError
+math/point_test: RuntimeError
+math/rectangle_test: RuntimeError
+mirrors/invocation_fuzz_test: Crash
+mirrors/library_uri_io_test: RuntimeError
+mirrors/library_uri_package_test: RuntimeError
+
+[ $runtime == vm && ($arch == simarm || $arch == simarmv6) ]
+convert/utf85_test: Skip # Pass, Slow Issue 12644.
+
+[ $arch == simarmv6 || $arch == simarm && $runtime == vm ]
+convert/chunked_conversion_utf88_test: Skip # Pass, Slow Issue 12644.
diff --git a/tests/lib/math/call_cmath_box_failure_path_test.dart b/tests/lib/math/call_cmath_box_failure_path_test.dart
new file mode 100644
index 0000000..bf63443
--- /dev/null
+++ b/tests/lib/math/call_cmath_box_failure_path_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2016, 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.
+
+// VMOptions=--optimization-counter-threshold=-1 --new_gen_semi_max_size=2
+
+// TODO(rnystrom): This looks like a VM-specific test. Move out of
+// tests/language and into somewhere more appropriate.
+
+import 'dart:math';
+
+main() {
+ // 2MB / 16 bytes = 125000 allocations
+
+ for (var i = 0; i < 500000; i++) {
+ sin(i);
+ }
+
+ for (var i = 0; i < 500000; i++) {
+ cos(i);
+ }
+
+ for (var i = 0; i < 500000; i++) {
+ i.toDouble().truncateToDouble();
+ }
+}
diff --git a/tests/lib/math/coin_test.dart b/tests/lib/math/coin_test.dart
new file mode 100644
index 0000000..58b4d16
--- /dev/null
+++ b/tests/lib/math/coin_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2012, 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.
+
+// Test that a coin toss with Random.nextBool() is fair.
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+main() {
+ var seed = new Random().nextInt(1 << 16);
+ print("coin_test seed: $seed");
+ var rnd = new Random(seed);
+ var heads = 0;
+ var tails = 0;
+ for (var i = 0; i < 10000; i++) {
+ if (rnd.nextBool()) {
+ heads++;
+ } else {
+ tails++;
+ }
+ }
+ print("Heads: $heads\n"
+ "Tails: $tails\n"
+ "Ratio: ${heads / tails}\n");
+ Expect.approxEquals(1.0, heads / tails, 0.1);
+
+ heads = 0;
+ tails = 0;
+ for (var i = 0; i < 10000; i++) {
+ rnd = new Random(i);
+ if (rnd.nextBool()) {
+ heads++;
+ } else {
+ tails++;
+ }
+ }
+ print("Heads: $heads\n"
+ "Tails: $tails\n"
+ "Ratio: ${heads / tails}\n");
+ Expect.approxEquals(1.0, heads / tails, 0.1);
+
+ // A sequence of newly allocated Random number generators should have fair
+ // initial tosses.
+ heads = 0;
+ tails = 0;
+ for (var i = 0; i < 10000; i++) {
+ rnd = new Random();
+ if (rnd.nextBool()) {
+ heads++;
+ } else {
+ tails++;
+ }
+ }
+ print("Heads: $heads\n"
+ "Tails: $tails\n"
+ "Ratio: ${heads / tails}\n");
+ Expect.approxEquals(1.0, heads / tails, 0.1);
+}
diff --git a/tests/lib/math/double_pow_test.dart b/tests/lib/math/double_pow_test.dart
new file mode 100644
index 0000000..c3e7969
--- /dev/null
+++ b/tests/lib/math/double_pow_test.dart
@@ -0,0 +1,174 @@
+// Copyright (c) 2011, 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.
+// VMOptions=--optimization-counter-threshold=5 --no-background-compilation
+
+library math_test;
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+void checkVeryClose(double a, num b) {
+ // We find a ulp (unit in the last place) by shifting the original number
+ // to the right. This only works if we are not too close to infinity or if
+ // we work with denormals.
+ // We special case for 0.0, but not for infinity.
+ if (a == 0.0) {
+ final minimalDouble = 4.9406564584124654e-324;
+ Expect.equals(true, b.abs() <= minimalDouble);
+ return;
+ }
+ if (b == 0.0) {
+ // No need to look if they are close. Otherwise the check for 'a' above
+ // would have triggered.
+ Expect.equals(a, b);
+ }
+ final double shiftRightBy52 = 2.220446049250313080847263336181640625e-16;
+ final double shiftedA = (a * shiftRightBy52).abs();
+ // Compared to 'a', 'shiftedA' is now ~1-2 ulp.
+
+ final double limitLow = a - shiftedA;
+ final double limitHigh = a + shiftedA;
+ Expect.equals(false, a == limitLow);
+ Expect.equals(false, a == limitHigh);
+ Expect.equals(true, limitLow <= b);
+ Expect.equals(true, b <= limitHigh);
+}
+
+const NaN = double.nan;
+const Infinity = double.infinity;
+
+var samples = [
+ NaN,
+ -Infinity,
+ -3.0, // Odd integer
+ -2.0, // Even integer
+ -1.5, // Non-integer, magnitude > 1
+ -1.0, // Unit
+ -0.5, // Non-integer, magnitude < 1.
+ -0.0,
+ 0.5, // Non-integer, magnitude < 1.
+ 1.0, // Unit
+ 1.5, // Non-integer, magnitude > 1
+ 2.0, // Even integer
+ 3.0, // Odd integer
+ Infinity
+];
+
+test() {
+ // Tests of pow(x, y):
+ for (var d in samples) {
+ // if `y` is zero (0.0 or -0.0), the result is always 1.0.
+ Expect.identical(1.0, pow(d, 0.0), "$d");
+ Expect.identical(1.0, pow(d, -0.0), "$d");
+ }
+ for (var d in samples) {
+ // if `x` is 1.0, the result is always 1.0.
+ Expect.identical(1.0, pow(1.0, d), "$d");
+ }
+ for (var d in samples) {
+ // otherwise, if either `x` or `y` is NaN then the result is NaN.
+ if (d != 0.0) Expect.isTrue(pow(NaN, d).isNaN, "$d");
+ if (d != 1.0) Expect.isTrue(pow(d, NaN).isNaN, "$d");
+ }
+
+ for (var d in samples) {
+ // if `x` is a finite and strictly negative and `y` is a finite non-integer,
+ // the result is NaN.
+ if (d < 0 && !d.isInfinite) {
+ Expect.isTrue(pow(d, 0.5).isNaN, "$d");
+ Expect.isTrue(pow(d, -0.5).isNaN, "$d");
+ Expect.isTrue(pow(d, 1.5).isNaN, "$d");
+ Expect.isTrue(pow(d, -1.5).isNaN, "$d");
+ }
+ }
+
+ for (var d in samples) {
+ if (d < 0) {
+ // if `x` is Infinity and `y` is strictly negative, the result is 0.0.
+ Expect.identical(0.0, pow(Infinity, d), "$d");
+ }
+ if (d > 0) {
+ // if `x` is Infinity and `y` is strictly positive, the result is Infinity.
+ Expect.identical(Infinity, pow(Infinity, d), "$d");
+ }
+ }
+
+ for (var d in samples) {
+ if (d < 0) {
+ // if `x` is 0.0 and `y` is strictly negative, the result is Infinity.
+ Expect.identical(Infinity, pow(0.0, d), "$d");
+ }
+ if (d > 0) {
+ // if `x` is 0.0 and `y` is strictly positive, the result is 0.0.
+ Expect.identical(0.0, pow(0.0, d), "$d");
+ }
+ }
+
+ for (var d in samples) {
+ if (!d.isInfinite && !d.isNaN) {
+ var dint = d.toInt();
+ if (d == dint && dint.isOdd) {
+ // if `x` is -Infinity or -0.0 and `y` is an odd integer, then the
+ // result is`-pow(-x ,y)`.
+ Expect.identical(-pow(Infinity, d), pow(-Infinity, d));
+ Expect.identical(-pow(0.0, d), pow(-0.0, d));
+ continue;
+ }
+ }
+ // if `x` is -Infinity or -0.0 and `y` is not an odd integer, then the
+ // result is the same as `pow(-x , y)`.
+ if (d.isNaN) {
+ Expect.isTrue(pow(Infinity, d).isNaN);
+ Expect.isTrue(pow(-Infinity, d).isNaN);
+ Expect.isTrue(pow(0.0, d).isNaN);
+ Expect.isTrue(pow(-0.0, d).isNaN);
+ continue;
+ }
+ Expect.identical(pow(Infinity, d), pow(-Infinity, d));
+ Expect.identical(pow(0.0, d), pow(-0.0, d));
+ }
+
+ for (var d in samples) {
+ if (d.abs() < 1) {
+ // if `y` is Infinity and the absolute value of `x` is less than 1, the
+ // result is 0.0.
+ Expect.identical(0.0, pow(d, Infinity));
+ } else if (d.abs() > 1) {
+ // if `y` is Infinity and the absolute value of `x` is greater than 1,
+ // the result is Infinity.
+ Expect.identical(Infinity, pow(d, Infinity));
+ } else if (d == -1) {
+ // if `y` is Infinity and `x` is -1, the result is 1.0.
+ Expect.identical(1.0, pow(d, Infinity));
+ }
+ // if `y` is -Infinity, the result is `1/pow(x, Infinity)`.
+ if (d.isNaN) {
+ Expect.isTrue((1 / pow(d, Infinity)).isNaN);
+ Expect.isTrue(pow(d, -Infinity).isNaN);
+ } else {
+ Expect.identical(1 / pow(d, Infinity), pow(d, -Infinity));
+ }
+ }
+
+ // Some non-exceptional values.
+ checkVeryClose(16.0, pow(4.0, 2.0));
+ checkVeryClose(sqrt2, pow(2.0, 0.5));
+ checkVeryClose(sqrt1_2, pow(0.5, 0.5));
+ // Denormal result.
+ Expect.identical(5e-324, pow(2.0, -1074.0));
+ // Overflow.
+ Expect.identical(Infinity, pow(10.0, 309.0));
+ // Underflow.
+ Expect.identical(0.0, pow(10.0, -325.0));
+
+ // Conversion to double.
+
+ // The second argument is an odd integer as int, but not when converted
+ // to double.
+ Expect.identical(Infinity, pow(-0.0, -9223372036854775807));
+}
+
+main() {
+ for (int i = 0; i < 10; i++) test();
+}
diff --git a/tests/lib/math/implement_rectangle_test.dart b/tests/lib/math/implement_rectangle_test.dart
new file mode 100644
index 0000000..3a31ed8
--- /dev/null
+++ b/tests/lib/math/implement_rectangle_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2016, 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.
+
+import 'dart:math' hide Rectangle;
+import 'dart:math' as math show Point, Rectangle, MutableRectangle;
+import 'package:expect/expect.dart' show Expect;
+
+void main() {
+ verifyRectable(new Rectangle(1, 2, 3, 4));
+}
+
+void verifyRectable(math.Rectangle rect) {
+ Expect.equals(1.0, rect.left.toDouble());
+ Expect.equals(2.0, rect.top.toDouble());
+ Expect.equals(4.0, rect.right.toDouble());
+ Expect.equals(6.0, rect.bottom.toDouble());
+}
+
+class Rectangle<T extends num> implements math.MutableRectangle<T> {
+ T left;
+ T top;
+ T width;
+ T height;
+
+ Rectangle(this.left, this.top, this.width, this.height);
+
+ T get right => left + width;
+
+ T get bottom => top + height;
+
+ Point<T> get topLeft => new Point<T>(left, top);
+
+ Point<T> get topRight => new Point<T>(right, top);
+
+ Point<T> get bottomLeft => new Point<T>(left, bottom);
+
+ Point<T> get bottomRight => new Point<T>(right, bottom);
+
+ //---------------------------------------------------------------------------
+
+ bool contains(num px, num py) {
+ return left <= px && top <= py && right > px && bottom > py;
+ }
+
+ bool containsPoint(math.Point<num> p) {
+ return contains(p.x, p.y);
+ }
+
+ bool intersects(math.Rectangle<num> r) {
+ return left < r.right && right > r.left && top < r.bottom && bottom > r.top;
+ }
+
+ /// Returns a new rectangle which completely contains `this` and [other].
+
+ Rectangle<T> boundingBox(math.Rectangle<T> other) {
+ T rLeft = min(left, other.left);
+ T rTop = min(top, other.top);
+ T rRight = max(right, other.right);
+ T rBottom = max(bottom, other.bottom);
+ return new Rectangle<T>(rLeft, rTop, rRight - rLeft, rBottom - rTop);
+ }
+
+ /// Tests whether `this` entirely contains [another].
+
+ bool containsRectangle(math.Rectangle<num> r) {
+ return left <= r.left &&
+ top <= r.top &&
+ right >= r.right &&
+ bottom >= r.bottom;
+ }
+
+ Rectangle<T> intersection(math.Rectangle<T> rect) {
+ T rLeft = max(left, rect.left);
+ T rTop = max(top, rect.top);
+ T rRight = min(right, rect.right);
+ T rBottom = min(bottom, rect.bottom);
+ return new Rectangle<T>(rLeft, rTop, rRight - rLeft, rBottom - rTop);
+ }
+}
diff --git a/tests/lib/math/low_test.dart b/tests/lib/math/low_test.dart
new file mode 100644
index 0000000..f7e9060
--- /dev/null
+++ b/tests/lib/math/low_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2012, 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.
+
+// Test that the default PRNG does uniformly distribute values when not using
+// a power of 2.
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+void main() {
+ var n = (2 * 0x100000000) ~/ 3;
+ var n2 = n ~/ 2;
+
+ var iterations = 200000;
+
+ var seed = new Random().nextInt(1 << 16);
+ print("low_test seed: $seed");
+ var prng = new Random(seed);
+
+ var low = 0;
+ for (var i = 0; i < iterations; i++) {
+ if (prng.nextInt(n) < n2) {
+ low++;
+ }
+ }
+
+ var diff = (low - (iterations ~/ 2)).abs();
+ print("$low, $diff");
+ Expect.isTrue(diff < (iterations ~/ 20));
+}
diff --git a/tests/lib/math/math2_test.dart b/tests/lib/math/math2_test.dart
new file mode 100644
index 0000000..6802723
--- /dev/null
+++ b/tests/lib/math/math2_test.dart
@@ -0,0 +1,265 @@
+// Copyright (c) 2012, 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.
+
+// We temporarily test both the new math library and the old Math
+// class. This can easily be simplified once we get rid of the Math
+// class entirely.
+library math_test;
+
+import "package:expect/expect.dart";
+import 'dart:math' as math;
+
+class MathLibraryTest {
+ static void testConstants() {
+ // Source for mathematical constants is Wolfram Alpha.
+ Expect.equals(
+ 2.7182818284590452353602874713526624977572470936999595749669, math.e);
+ Expect.equals(2.3025850929940456840179914546843642076011014886287729760333,
+ math.ln10);
+ Expect.equals(
+ 0.6931471805599453094172321214581765680755001343602552541206, math.ln2);
+ Expect.equals(1.4426950408889634073599246810018921374266459541529859341354,
+ math.log2e);
+ Expect.equals(0.4342944819032518276511289189166050822943970058036665661144,
+ math.log10e);
+ Expect.equals(
+ 3.1415926535897932384626433832795028841971693993751058209749, math.pi);
+ Expect.equals(0.7071067811865475244008443621048490392848359376884740365883,
+ math.sqrt1_2);
+ Expect.equals(1.4142135623730950488016887242096980785696718753769480731766,
+ math.sqrt2);
+ }
+
+ static checkClose(double a, double b, EPSILON) {
+ Expect.equals(true, a - EPSILON <= b);
+ Expect.equals(true, b <= a + EPSILON);
+ }
+
+ static void testSin() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, math.sin(0.0), EPSILON);
+ checkClose(0.0, math.sin(math.pi), EPSILON);
+ checkClose(0.0, math.sin(2.0 * math.pi), EPSILON);
+ checkClose(1.0, math.sin(math.pi / 2.0), EPSILON);
+ checkClose(-1.0, math.sin(math.pi * (3.0 / 2.0)), EPSILON);
+ }
+
+ static void testCos() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(1.0, math.cos(0.0), EPSILON);
+ checkClose(-1.0, math.cos(math.pi), EPSILON);
+ checkClose(1.0, math.cos(2.0 * math.pi), EPSILON);
+ checkClose(0.0, math.cos(math.pi / 2.0), EPSILON);
+ checkClose(0.0, math.cos(math.pi * (3.0 / 2.0)), EPSILON);
+ }
+
+ static void testTan() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, math.tan(0.0), EPSILON);
+ checkClose(0.0, math.tan(math.pi), EPSILON);
+ checkClose(0.0, math.tan(2.0 * math.pi), EPSILON);
+ checkClose(1.0, math.tan(math.pi / 4.0), EPSILON);
+ }
+
+ static void testAsin() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, math.asin(0.0), EPSILON);
+ checkClose(math.pi / 2.0, math.asin(1.0), EPSILON);
+ checkClose(-math.pi / 2.0, math.asin(-1.0), EPSILON);
+ }
+
+ static void testAcos() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, math.acos(1.0), EPSILON);
+ checkClose(math.pi, math.acos(-1.0), EPSILON);
+ checkClose(math.pi / 2.0, math.acos(0.0), EPSILON);
+ }
+
+ static void testAtan() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, math.atan(0.0), EPSILON);
+ checkClose(math.pi / 4.0, math.atan(1.0), EPSILON);
+ checkClose(-math.pi / 4.0, math.atan(-1.0), EPSILON);
+ }
+
+ static void testAtan2() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, math.atan2(0.0, 5.0), EPSILON);
+ checkClose(math.pi / 4.0, math.atan2(2.0, 2.0), EPSILON);
+ checkClose(3 * math.pi / 4.0, math.atan2(0.5, -0.5), EPSILON);
+ checkClose(-3 * math.pi / 4.0, math.atan2(-2.5, -2.5), EPSILON);
+ }
+
+ static checkVeryClose(double a, num b) {
+ // We find a ulp (unit in the last place) by shifting the original number
+ // to the right. This only works if we are not too close to infinity or if
+ // we work with denormals.
+ // We special case or 0.0, but not for infinity.
+ if (a == 0.0) {
+ final minimalDouble = 4.9406564584124654e-324;
+ Expect.equals(true, b.abs() <= minimalDouble);
+ return;
+ }
+ if (b == 0.0) {
+ // No need to look if they are close. Otherwise the check for 'a' above
+ // whould have triggered.
+ Expect.equals(a, b);
+ }
+ final double shiftRightBy52 = 2.220446049250313080847263336181640625e-16;
+ final double shiftedA = (a * shiftRightBy52).abs();
+ // Compared to 'a', 'shiftedA' is now ~1-2 ulp.
+
+ final double limitLow = a - shiftedA;
+ final double limitHigh = a + shiftedA;
+ Expect.equals(false, a == limitLow);
+ Expect.equals(false, a == limitHigh);
+ Expect.equals(true, limitLow <= b);
+ Expect.equals(true, b <= limitHigh);
+ }
+
+ static void testSqrt() {
+ checkVeryClose(2.0, math.sqrt(4.0));
+ checkVeryClose(math.sqrt2, math.sqrt(2.0));
+ checkVeryClose(math.sqrt1_2, math.sqrt(0.5));
+ checkVeryClose(1e50, math.sqrt(1e100));
+ checkVeryClose(1.1111111061110855443054405046358901279277111935183977e56,
+ math.sqrt(12345678901234e99));
+ }
+
+ static void testExp() {
+ checkVeryClose(math.e, math.exp(1.0));
+ final EPSILON = 1e-15;
+ checkClose(10.0, math.exp(math.ln10), EPSILON);
+ checkClose(2.0, math.exp(math.ln2), EPSILON);
+ }
+
+ static void testLog() {
+ // Even though E is imprecise, it is good enough to get really close to 1.
+ // We still provide an epsilon.
+ checkClose(1.0, math.log(math.e), 1e-16);
+ checkVeryClose(math.ln10, math.log(10.0));
+ checkVeryClose(math.ln2, math.log(2.0));
+ }
+
+ static void testPow() {
+ checkVeryClose(16.0, math.pow(4.0, 2.0));
+ checkVeryClose(math.sqrt2, math.pow(2.0, 0.5));
+ checkVeryClose(math.sqrt1_2, math.pow(0.5, 0.5));
+ }
+
+ static bool parseIntThrowsFormatException(str) {
+ try {
+ int.parse(str);
+ return false;
+ } on FormatException catch (e) {
+ return true;
+ }
+ }
+
+ static void testParseInt() {
+ Expect.equals(499, int.parse("499"));
+ Expect.equals(499, int.parse("+499"));
+ Expect.equals(-499, int.parse("-499"));
+ Expect.equals(499, int.parse(" 499 "));
+ Expect.equals(499, int.parse(" +499 "));
+ Expect.equals(-499, int.parse(" -499 "));
+ Expect.equals(0, int.parse("0"));
+ Expect.equals(0, int.parse("+0"));
+ Expect.equals(0, int.parse("-0"));
+ Expect.equals(0, int.parse(" 0 "));
+ Expect.equals(0, int.parse(" +0 "));
+ Expect.equals(0, int.parse(" -0 "));
+ Expect.equals(0x1234567890, int.parse("0x1234567890"));
+ Expect.equals(-0x1234567890, int.parse("-0x1234567890"));
+ Expect.equals(0x1234567890, int.parse(" 0x1234567890 "));
+ Expect.equals(-0x1234567890, int.parse(" -0x1234567890 "));
+ Expect.equals(256, int.parse("0x100"));
+ Expect.equals(-256, int.parse("-0x100"));
+ Expect.equals(256, int.parse(" 0x100 "));
+ Expect.equals(-256, int.parse(" -0x100 "));
+ Expect.equals(0xabcdef, int.parse("0xabcdef"));
+ Expect.equals(0xABCDEF, int.parse("0xABCDEF"));
+ Expect.equals(0xabcdef, int.parse("0xabCDEf"));
+ Expect.equals(-0xabcdef, int.parse("-0xabcdef"));
+ Expect.equals(-0xABCDEF, int.parse("-0xABCDEF"));
+ Expect.equals(0xabcdef, int.parse(" 0xabcdef "));
+ Expect.equals(0xABCDEF, int.parse(" 0xABCDEF "));
+ Expect.equals(-0xabcdef, int.parse(" -0xabcdef "));
+ Expect.equals(-0xABCDEF, int.parse(" -0xABCDEF "));
+ Expect.equals(0xabcdef, int.parse("0x00000abcdef"));
+ Expect.equals(0xABCDEF, int.parse("0x00000ABCDEF"));
+ Expect.equals(-0xabcdef, int.parse("-0x00000abcdef"));
+ Expect.equals(-0xABCDEF, int.parse("-0x00000ABCDEF"));
+ Expect.equals(0xabcdef, int.parse(" 0x00000abcdef "));
+ Expect.equals(0xABCDEF, int.parse(" 0x00000ABCDEF "));
+ Expect.equals(-0xabcdef, int.parse(" -0x00000abcdef "));
+ Expect.equals(-0xABCDEF, int.parse(" -0x00000ABCDEF "));
+ Expect.equals(10, int.parse("010"));
+ Expect.equals(-10, int.parse("-010"));
+ Expect.equals(10, int.parse(" 010 "));
+ Expect.equals(-10, int.parse(" -010 "));
+ Expect.equals(9, int.parse("09"));
+ Expect.equals(9, int.parse(" 09 "));
+ Expect.equals(-9, int.parse("-09"));
+ Expect.equals(0x1234567890, int.parse("+0x1234567890"));
+ Expect.equals(0x1234567890, int.parse(" +0x1234567890 "));
+ Expect.equals(0x100, int.parse("+0x100"));
+ Expect.equals(0x100, int.parse(" +0x100 "));
+
+ Expect.equals(true, parseIntThrowsFormatException("1b"));
+ Expect.equals(true, parseIntThrowsFormatException(" 1b "));
+ Expect.equals(true, parseIntThrowsFormatException(" 1 b "));
+ Expect.equals(true, parseIntThrowsFormatException("1e2"));
+ Expect.equals(true, parseIntThrowsFormatException(" 1e2 "));
+ Expect.equals(true, parseIntThrowsFormatException("00x12"));
+ Expect.equals(true, parseIntThrowsFormatException(" 00x12 "));
+ Expect.equals(true, parseIntThrowsFormatException("-1b"));
+ Expect.equals(true, parseIntThrowsFormatException(" -1b "));
+ Expect.equals(true, parseIntThrowsFormatException(" -1 b "));
+ Expect.equals(true, parseIntThrowsFormatException("-1e2"));
+ Expect.equals(true, parseIntThrowsFormatException(" -1e2 "));
+ Expect.equals(true, parseIntThrowsFormatException("-00x12"));
+ Expect.equals(true, parseIntThrowsFormatException(" -00x12 "));
+ Expect.equals(true, parseIntThrowsFormatException(" -00x12 "));
+ Expect.equals(true, parseIntThrowsFormatException("0x0x12"));
+ Expect.equals(true, parseIntThrowsFormatException("0.1"));
+ Expect.equals(true, parseIntThrowsFormatException("0x3.1"));
+ Expect.equals(true, parseIntThrowsFormatException("5."));
+ Expect.equals(true, parseIntThrowsFormatException("+-5"));
+ Expect.equals(true, parseIntThrowsFormatException("-+5"));
+ Expect.equals(true, parseIntThrowsFormatException("--5"));
+ Expect.equals(true, parseIntThrowsFormatException("++5"));
+ Expect.equals(true, parseIntThrowsFormatException("+ 5"));
+ Expect.equals(true, parseIntThrowsFormatException("- 5"));
+ Expect.equals(true, parseIntThrowsFormatException(""));
+ Expect.equals(true, parseIntThrowsFormatException(" "));
+ }
+
+ static testMain() {
+ testConstants();
+ testSin();
+ testCos();
+ testTan();
+ testAsin();
+ testAcos();
+ testAtan();
+ testAtan2();
+ testSqrt();
+ testLog();
+ testExp();
+ testPow();
+ testParseInt();
+ }
+}
+
+main() {
+ MathLibraryTest.testMain();
+}
diff --git a/tests/lib/math/math_parse_double_test.dart b/tests/lib/math/math_parse_double_test.dart
new file mode 100644
index 0000000..4aedf50
--- /dev/null
+++ b/tests/lib/math/math_parse_double_test.dart
@@ -0,0 +1,170 @@
+// Copyright (c) 2012, 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.
+
+// We temporarily test both the new math library and the old Math
+// class. This can easily be simplified once we get rid of the Math
+// class entirely.
+library math_parse_double_test;
+
+import "package:expect/expect.dart";
+
+void parseDoubleThrowsFormatException(str) {
+ Expect.throwsFormatException(() => double.parse(str));
+}
+
+void runTest(double expected, String input) {
+ Expect.equals(expected, double.parse(input));
+ Expect.equals(expected, double.parse(" $input "));
+ Expect.equals(expected, double.parse(" $input"));
+ Expect.equals(expected, double.parse("$input "));
+ Expect.equals(expected, double.parse("+$input"));
+ Expect.equals(expected, double.parse(" +$input "));
+ Expect.equals(expected, double.parse("+$input "));
+ Expect.equals(expected, double.parse("\xA0 $input\xA0 "));
+ Expect.equals(expected, double.parse(" \xA0$input"));
+ Expect.equals(expected, double.parse("$input \xA0"));
+ Expect.equals(expected, double.parse("\xA0 +$input\xA0 "));
+ Expect.equals(expected, double.parse("+$input\xA0 "));
+ Expect.equals(expected, double.parse("\u205F $input\u205F "));
+ Expect.equals(expected, double.parse("$input \u2006"));
+ Expect.equals(expected, double.parse("\u1680 +$input\u1680 "));
+ Expect.equals(-expected, double.parse("-$input"));
+ Expect.equals(-expected, double.parse(" -$input "));
+ Expect.equals(-expected, double.parse("-$input "));
+ Expect.equals(-expected, double.parse("\xA0 -$input\xA0 "));
+ Expect.equals(-expected, double.parse("-$input\xA0 "));
+ Expect.equals(-expected, double.parse("\u1680 -$input\u1680 "));
+}
+
+final TESTS = [
+ [499.0, "499"],
+ [499.0, "499."],
+ [499.0, "499.0"],
+ [0.0, "0"],
+ [0.0, ".0"],
+ [0.0, "0."],
+ [0.1, "0.1"],
+ [0.1, ".1"],
+ [10.0, "010"],
+ [1.5, "1.5"],
+ [1.5, "001.5"],
+ [1.5, "1.500"],
+ [1234567.89, "1234567.89"],
+ [1234567e89, "1234567e89"],
+ [1234567.89e2, "1234567.89e2"],
+ [1234567.89e2, "1234567.89e+2"],
+ [1234567.89e-2, "1234567.89e-2"],
+ [5.0, "5"],
+ [123456700.0, "1234567.e2"],
+ [123456700.0, "1234567.e+2"],
+ [double.infinity, "Infinity"],
+ [5e-324, "5e-324"], // min-pos.
+ // Same, without exponential.
+ [
+ 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625,
+ "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004940656458412465441765687928682213723650598026143247644255856825006755072702087518652998363616359923797965646954457177309266567103559397963987747960107818781263007131903114045278458171678489821036887186360569987307230500063874091535649843873124733972731696151400317153853980741262385655911710266585566867681870395603106249319452715914924553293054565444011274801297099995419319894090804165633245247571478690147267801593552386115501348035264934720193790268107107491703332226844753335720832431936092382893458368060106011506169809753078342277318329247904982524730776375927247874656084778203734469699533647017972677717585125660551199131504891101451037862738167250955837389733598993664809941164205702637090279242767544565229087538682506419718265533447265625"
+ ],
+ [0.0, "2e-324"], // underflow 0.0
+ [0.9999999999999999, "0.9999999999999999"], // max below 1
+ [1.0, "1.00000000000000005"], // 1.0
+ [1.0000000000000002, "1.0000000000000002"], // min above 1
+ [2147483647.0, "2147483647"], // max int32
+ [2147483647.0000002, "2147483647.0000002"], // min not int32
+ [2147483648.0, "2147483648"], // min int not int32
+ [4295967295.0, "4295967295"], // max uint32
+ [4295967295.000001, "4295967295.000001"], // min not uint-32
+ [4295967296.0, "4295967296"], // min int not-uint32
+ [1.7976931348623157e+308, "1.7976931348623157e+308"], // Max finite
+ [1.7976931348623157e+308, "1.7976931348623158e+308"], // Max finite
+ [double.infinity, "1.7976931348623159e+308"], // Infinity
+ [.049999999999999994, ".049999999999999994"], // not 0.5
+ [.05, ".04999999999999999935"],
+ [4503599627370498.0, "4503599627370497.5"],
+ [1.2345678901234568e+39, "1234567890123456898981341324213421342134"],
+ [9.87291183742987e+24, "9872911837429871193379121"],
+ [1e21, "1e+21"],
+];
+
+void main() {
+ for (var test in TESTS) {
+ runTest(test[0] as double, test[1] as String);
+ }
+
+ Expect.equals(true, double.parse("-0").isNegative);
+ Expect.equals(true, double.parse(" -0 ").isNegative);
+ Expect.equals(true, double.parse("\xA0 -0 \xA0").isNegative);
+ Expect.isTrue(double.parse("NaN").isNaN);
+ Expect.isTrue(double.parse("-NaN").isNaN);
+ Expect.isTrue(double.parse("+NaN").isNaN);
+ Expect.isTrue(double.parse("NaN ").isNaN);
+ Expect.isTrue(double.parse("-NaN ").isNaN);
+ Expect.isTrue(double.parse("+NaN ").isNaN);
+ Expect.isTrue(double.parse(" NaN ").isNaN);
+ Expect.isTrue(double.parse(" -NaN ").isNaN);
+ Expect.isTrue(double.parse(" +NaN ").isNaN);
+ Expect.isTrue(double.parse(" NaN").isNaN);
+ Expect.isTrue(double.parse(" -NaN").isNaN);
+ Expect.isTrue(double.parse(" +NaN").isNaN);
+ Expect.isTrue(double.parse("NaN\xA0").isNaN);
+ Expect.isTrue(double.parse("-NaN\xA0").isNaN);
+ Expect.isTrue(double.parse("+NaN\xA0").isNaN);
+ Expect.isTrue(double.parse(" \xA0NaN\xA0").isNaN);
+ Expect.isTrue(double.parse(" \xA0-NaN\xA0").isNaN);
+ Expect.isTrue(double.parse(" \xA0+NaN\xA0").isNaN);
+ Expect.isTrue(double.parse(" \xA0NaN").isNaN);
+ Expect.isTrue(double.parse(" \xA0-NaN").isNaN);
+ Expect.isTrue(double.parse(" \xA0+NaN").isNaN);
+
+ parseDoubleThrowsFormatException("1b");
+ parseDoubleThrowsFormatException(" 1b ");
+ parseDoubleThrowsFormatException(" 1 b ");
+ parseDoubleThrowsFormatException(" e3 ");
+ parseDoubleThrowsFormatException(" .e3 ");
+ parseDoubleThrowsFormatException("00x12");
+ parseDoubleThrowsFormatException(" 00x12 ");
+ parseDoubleThrowsFormatException("-1b");
+ parseDoubleThrowsFormatException(" -1b ");
+ parseDoubleThrowsFormatException(" -1 b ");
+ parseDoubleThrowsFormatException("-00x12");
+ parseDoubleThrowsFormatException(" -00x12 ");
+ parseDoubleThrowsFormatException(" -00x12 ");
+ parseDoubleThrowsFormatException("0x0x12");
+ parseDoubleThrowsFormatException("+ 1.5");
+ parseDoubleThrowsFormatException("- 1.5");
+ parseDoubleThrowsFormatException("");
+ parseDoubleThrowsFormatException(" ");
+ parseDoubleThrowsFormatException("+0x1234567890");
+ parseDoubleThrowsFormatException(" +0x1234567890 ");
+ parseDoubleThrowsFormatException(" +0x100 ");
+ parseDoubleThrowsFormatException("+0x100");
+ parseDoubleThrowsFormatException("0x1234567890");
+ parseDoubleThrowsFormatException("-0x1234567890");
+ parseDoubleThrowsFormatException(" 0x1234567890 ");
+ parseDoubleThrowsFormatException(" -0x1234567890 ");
+ parseDoubleThrowsFormatException("0x100");
+ parseDoubleThrowsFormatException("-0x100");
+ parseDoubleThrowsFormatException(" 0x100 ");
+ parseDoubleThrowsFormatException(" -0x100 ");
+ parseDoubleThrowsFormatException("0xabcdef");
+ parseDoubleThrowsFormatException("0xABCDEF");
+ parseDoubleThrowsFormatException("0xabCDEf");
+ parseDoubleThrowsFormatException("-0xabcdef");
+ parseDoubleThrowsFormatException("-0xABCDEF");
+ parseDoubleThrowsFormatException(" 0xabcdef ");
+ parseDoubleThrowsFormatException(" 0xABCDEF ");
+ parseDoubleThrowsFormatException(" -0xabcdef ");
+ parseDoubleThrowsFormatException(" -0xABCDEF ");
+ parseDoubleThrowsFormatException("0x00000abcdef");
+ parseDoubleThrowsFormatException("0x00000ABCDEF");
+ parseDoubleThrowsFormatException("-0x00000abcdef");
+ parseDoubleThrowsFormatException("-0x00000ABCDEF");
+ parseDoubleThrowsFormatException(" 0x00000abcdef ");
+ parseDoubleThrowsFormatException(" 0x00000ABCDEF ");
+ parseDoubleThrowsFormatException(" -0x00000abcdef ");
+ parseDoubleThrowsFormatException(" -0x00000ABCDEF ");
+ parseDoubleThrowsFormatException(" -INFINITY ");
+ parseDoubleThrowsFormatException(" NAN ");
+ parseDoubleThrowsFormatException(" inf ");
+ parseDoubleThrowsFormatException(" nan ");
+}
diff --git a/tests/lib/math/math_test.dart b/tests/lib/math/math_test.dart
new file mode 100644
index 0000000..ca32951
--- /dev/null
+++ b/tests/lib/math/math_test.dart
@@ -0,0 +1,254 @@
+// Copyright (c) 2011, 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.
+
+library math_test;
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+class MathTest {
+ static void testConstants() {
+ // Source for mathematical constants is Wolfram Alpha.
+ Expect.equals(
+ 2.7182818284590452353602874713526624977572470936999595749669, e);
+ Expect.equals(
+ 2.3025850929940456840179914546843642076011014886287729760333, ln10);
+ Expect.equals(
+ 0.6931471805599453094172321214581765680755001343602552541206, ln2);
+ Expect.equals(
+ 1.4426950408889634073599246810018921374266459541529859341354, log2e);
+ Expect.equals(
+ 0.4342944819032518276511289189166050822943970058036665661144, log10e);
+ Expect.equals(
+ 3.1415926535897932384626433832795028841971693993751058209749, pi);
+ Expect.equals(
+ 0.7071067811865475244008443621048490392848359376884740365883, sqrt1_2);
+ Expect.equals(
+ 1.4142135623730950488016887242096980785696718753769480731766, sqrt2);
+ }
+
+ static checkClose(double a, double b, EPSILON) {
+ Expect.equals(true, a - EPSILON <= b);
+ Expect.equals(true, b <= a + EPSILON);
+ }
+
+ static void testSin() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, sin(0.0), EPSILON);
+ checkClose(0.0, sin(pi), EPSILON);
+ checkClose(0.0, sin(2.0 * pi), EPSILON);
+ checkClose(1.0, sin(pi / 2.0), EPSILON);
+ checkClose(-1.0, sin(pi * (3.0 / 2.0)), EPSILON);
+ }
+
+ static void testCos() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(1.0, cos(0.0), EPSILON);
+ checkClose(-1.0, cos(pi), EPSILON);
+ checkClose(1.0, cos(2.0 * pi), EPSILON);
+ checkClose(0.0, cos(pi / 2.0), EPSILON);
+ checkClose(0.0, cos(pi * (3.0 / 2.0)), EPSILON);
+ }
+
+ static void testTan() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, tan(0.0), EPSILON);
+ checkClose(0.0, tan(pi), EPSILON);
+ checkClose(0.0, tan(2.0 * pi), EPSILON);
+ checkClose(1.0, tan(pi / 4.0), EPSILON);
+ }
+
+ static void testAsin() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, asin(0.0), EPSILON);
+ checkClose(pi / 2.0, asin(1.0), EPSILON);
+ checkClose(-pi / 2.0, asin(-1.0), EPSILON);
+ }
+
+ static void testAcos() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, acos(1.0), EPSILON);
+ checkClose(pi, acos(-1.0), EPSILON);
+ checkClose(pi / 2.0, acos(0.0), EPSILON);
+ }
+
+ static void testAtan() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, atan(0.0), EPSILON);
+ checkClose(pi / 4.0, atan(1.0), EPSILON);
+ checkClose(-pi / 4.0, atan(-1.0), EPSILON);
+ }
+
+ static void testAtan2() {
+ // Given the imprecision of pi we can't expect better results than this.
+ final double EPSILON = 1e-15;
+ checkClose(0.0, atan2(0.0, 5.0), EPSILON);
+ checkClose(pi / 4.0, atan2(2.0, 2.0), EPSILON);
+ checkClose(3 * pi / 4.0, atan2(0.5, -0.5), EPSILON);
+ checkClose(-3 * pi / 4.0, atan2(-2.5, -2.5), EPSILON);
+ }
+
+ static checkVeryClose(double a, double b) {
+ // We find a ulp (unit in the last place) by shifting the original number
+ // to the right. This only works if we are not too close to infinity or if
+ // we work with denormals.
+ // We special case or 0.0, but not for infinity.
+ if (a == 0.0) {
+ final minimalDouble = 4.9406564584124654e-324;
+ Expect.equals(true, b.abs() <= minimalDouble);
+ return;
+ }
+ if (b == 0.0) {
+ // No need to look if they are close. Otherwise the check for 'a' above
+ // whould have triggered.
+ Expect.equals(a, b);
+ }
+ final double shiftRightBy52 = 2.220446049250313080847263336181640625e-16;
+ final double shiftedA = (a * shiftRightBy52).abs();
+ // Compared to 'a', 'shiftedA' is now ~1-2 ulp.
+
+ final double limitLow = a - shiftedA;
+ final double limitHigh = a + shiftedA;
+ Expect.equals(false, a == limitLow);
+ Expect.equals(false, a == limitHigh);
+ Expect.equals(true, limitLow <= b);
+ Expect.equals(true, b <= limitHigh);
+ }
+
+ static void testSqrt() {
+ checkVeryClose(2.0, sqrt(4.0));
+ checkVeryClose(sqrt2, sqrt(2.0));
+ checkVeryClose(sqrt1_2, sqrt(0.5));
+ checkVeryClose(1e50, sqrt(1e100));
+ checkVeryClose(1.1111111061110855443054405046358901279277111935183977e56,
+ sqrt(12345678901234e99));
+ }
+
+ static void testExp() {
+ checkVeryClose(e, exp(1.0));
+ final EPSILON = 1e-15;
+ checkClose(10.0, exp(ln10), EPSILON);
+ checkClose(2.0, exp(ln2), EPSILON);
+ }
+
+ static void testLog() {
+ // Even though E is imprecise, it is good enough to get really close to 1.
+ // We still provide an epsilon.
+ checkClose(1.0, log(e), 1e-16);
+ checkVeryClose(ln10, log(10.0));
+ checkVeryClose(ln2, log(2.0));
+ }
+
+ static bool parseIntThrowsFormatException(str) {
+ try {
+ int.parse(str);
+ return false;
+ } on FormatException catch (e) {
+ return true;
+ }
+ }
+
+ static void testParseInt() {
+ Expect.equals(499, int.parse("499"));
+ Expect.equals(499, int.parse("+499"));
+ Expect.equals(-499, int.parse("-499"));
+ Expect.equals(499, int.parse(" 499 "));
+ Expect.equals(499, int.parse(" +499 "));
+ Expect.equals(-499, int.parse(" -499 "));
+ Expect.equals(0, int.parse("0"));
+ Expect.equals(0, int.parse("+0"));
+ Expect.equals(0, int.parse("-0"));
+ Expect.equals(0, int.parse(" 0 "));
+ Expect.equals(0, int.parse(" +0 "));
+ Expect.equals(0, int.parse(" -0 "));
+ Expect.equals(0x1234567890, int.parse("0x1234567890"));
+ Expect.equals(-0x1234567890, int.parse("-0x1234567890"));
+ Expect.equals(0x1234567890, int.parse(" 0x1234567890 "));
+ Expect.equals(-0x1234567890, int.parse(" -0x1234567890 "));
+ Expect.equals(256, int.parse("0x100"));
+ Expect.equals(-256, int.parse("-0x100"));
+ Expect.equals(256, int.parse(" 0x100 "));
+ Expect.equals(-256, int.parse(" -0x100 "));
+ Expect.equals(0xabcdef, int.parse("0xabcdef"));
+ Expect.equals(0xABCDEF, int.parse("0xABCDEF"));
+ Expect.equals(0xabcdef, int.parse("0xabCDEf"));
+ Expect.equals(-0xabcdef, int.parse("-0xabcdef"));
+ Expect.equals(-0xABCDEF, int.parse("-0xABCDEF"));
+ Expect.equals(0xabcdef, int.parse(" 0xabcdef "));
+ Expect.equals(0xABCDEF, int.parse(" 0xABCDEF "));
+ Expect.equals(-0xabcdef, int.parse(" -0xabcdef "));
+ Expect.equals(-0xABCDEF, int.parse(" -0xABCDEF "));
+ Expect.equals(0xabcdef, int.parse("0x00000abcdef"));
+ Expect.equals(0xABCDEF, int.parse("0x00000ABCDEF"));
+ Expect.equals(-0xabcdef, int.parse("-0x00000abcdef"));
+ Expect.equals(-0xABCDEF, int.parse("-0x00000ABCDEF"));
+ Expect.equals(0xabcdef, int.parse(" 0x00000abcdef "));
+ Expect.equals(0xABCDEF, int.parse(" 0x00000ABCDEF "));
+ Expect.equals(-0xabcdef, int.parse(" -0x00000abcdef "));
+ Expect.equals(-0xABCDEF, int.parse(" -0x00000ABCDEF "));
+ Expect.equals(10, int.parse("010"));
+ Expect.equals(-10, int.parse("-010"));
+ Expect.equals(10, int.parse(" 010 "));
+ Expect.equals(-10, int.parse(" -010 "));
+ Expect.equals(9, int.parse("09"));
+ Expect.equals(9, int.parse(" 09 "));
+ Expect.equals(-9, int.parse("-09"));
+ Expect.equals(0x1234567890, int.parse("+0x1234567890"));
+ Expect.equals(0x1234567890, int.parse(" +0x1234567890 "));
+ Expect.equals(0x100, int.parse("+0x100"));
+ Expect.equals(0x100, int.parse(" +0x100 "));
+ Expect.equals(true, parseIntThrowsFormatException("1b"));
+ Expect.equals(true, parseIntThrowsFormatException(" 1b "));
+ Expect.equals(true, parseIntThrowsFormatException(" 1 b "));
+ Expect.equals(true, parseIntThrowsFormatException("1e2"));
+ Expect.equals(true, parseIntThrowsFormatException(" 1e2 "));
+ Expect.equals(true, parseIntThrowsFormatException("00x12"));
+ Expect.equals(true, parseIntThrowsFormatException(" 00x12 "));
+ Expect.equals(true, parseIntThrowsFormatException("-1b"));
+ Expect.equals(true, parseIntThrowsFormatException(" -1b "));
+ Expect.equals(true, parseIntThrowsFormatException(" -1 b "));
+ Expect.equals(true, parseIntThrowsFormatException("-1e2"));
+ Expect.equals(true, parseIntThrowsFormatException(" -1e2 "));
+ Expect.equals(true, parseIntThrowsFormatException("-00x12"));
+ Expect.equals(true, parseIntThrowsFormatException(" -00x12 "));
+ Expect.equals(true, parseIntThrowsFormatException(" -00x12 "));
+ Expect.equals(true, parseIntThrowsFormatException("0x0x12"));
+ Expect.equals(true, parseIntThrowsFormatException("0.1"));
+ Expect.equals(true, parseIntThrowsFormatException("0x3.1"));
+ Expect.equals(true, parseIntThrowsFormatException("5."));
+ Expect.equals(true, parseIntThrowsFormatException("+-5"));
+ Expect.equals(true, parseIntThrowsFormatException("-+5"));
+ Expect.equals(true, parseIntThrowsFormatException("--5"));
+ Expect.equals(true, parseIntThrowsFormatException("++5"));
+ Expect.equals(true, parseIntThrowsFormatException("+ 5"));
+ Expect.equals(true, parseIntThrowsFormatException("- 5"));
+ Expect.equals(true, parseIntThrowsFormatException(""));
+ Expect.equals(true, parseIntThrowsFormatException(" "));
+ }
+
+ static testMain() {
+ testConstants();
+ testSin();
+ testCos();
+ testTan();
+ testAsin();
+ testAcos();
+ testAtan();
+ testAtan2();
+ testSqrt();
+ testLog();
+ testExp();
+ testParseInt();
+ }
+}
+
+main() {
+ MathTest.testMain();
+}
diff --git a/tests/lib/math/min_max_test.dart b/tests/lib/math/min_max_test.dart
new file mode 100644
index 0000000..4fb4317
--- /dev/null
+++ b/tests/lib/math/min_max_test.dart
@@ -0,0 +1,563 @@
+// Copyright (c) 2012, 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.
+// Dart test for testing Math.min and Math.max.
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+library min_max_test;
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+var inf = double.infinity;
+var nan = double.nan;
+
+// A class that might work if [min] and [max] worked for non-numbers.
+class Wrap implements Comparable<dynamic> {
+ final num value;
+ Wrap(this.value);
+ int compareTo(dynamic other) => value.compareTo(other.value);
+ bool operator <(Wrap other) => compareTo(other) < 0;
+ bool operator <=(Wrap other) => compareTo(other) <= 0;
+ bool operator >(Wrap other) => compareTo(other) > 0;
+ bool operator >=(Wrap other) => compareTo(other) >= 0;
+ bool operator ==(other) => other is Wrap && compareTo(other) == 0;
+ String toString() => 'Wrap($value)';
+ int get hashCode => value.hashCode;
+}
+
+var wrap1 = new Wrap(1);
+var wrap2 = new Wrap(2);
+
+testMin() {
+ testMin1();
+ testMin2();
+ testMin3();
+}
+
+testMin1() {
+ Expect.equals(0, min(0, 2));
+ Expect.equals(0, min(2, 0));
+
+ Expect.equals(-10, min(-10, -9));
+ Expect.equals(-10, min(-10, 9));
+ Expect.equals(-10, min(-10, 0));
+ Expect.equals(-10, min(-9, -10));
+ Expect.equals(-10, min(9, -10));
+ Expect.equals(-10, min(0, -10));
+
+ Expect.equals(0.5, min(0.5, 2.5));
+ Expect.equals(0.5, min(2.5, 0.5));
+
+ Expect.equals(-10.5, min(-10.5, -9.5));
+ Expect.equals(-10.5, min(-10.5, 9.5));
+ Expect.equals(-10.5, min(-10.5, 0.5));
+ Expect.equals(-10.5, min(-9.5, -10.5));
+ Expect.equals(-10.5, min(9.5, -10.5));
+ Expect.equals(-10.5, min(0.5, -10.5));
+ // Test matrix:
+ // NaN, -infinity, -499.0, -499, -0.0, 0.0, 0, 499.0, 499, +infinity.
+
+ Expect.isTrue(min(nan, nan).isNaN);
+ Expect.isTrue(min(nan, -inf).isNaN);
+ Expect.isTrue(min(nan, -499.0).isNaN);
+ Expect.isTrue(min(nan, -499).isNaN);
+ Expect.isTrue(min(nan, -0.0).isNaN);
+ Expect.isTrue(min(nan, 0.0).isNaN);
+ Expect.isTrue(min(nan, 499.0).isNaN);
+ Expect.isTrue(min(nan, 499).isNaN);
+ Expect.isTrue(min(nan, inf).isNaN);
+
+ Expect.equals(-inf, min(-inf, -inf));
+ Expect.equals(-inf, min(-inf, -499.0));
+ Expect.equals(-inf, min(-inf, -499));
+ Expect.equals(-inf, min(-inf, -0.0));
+ Expect.equals(-inf, min(-inf, 0.0));
+ Expect.equals(-inf, min(-inf, 0));
+ Expect.equals(-inf, min(-inf, 499));
+ Expect.equals(-inf, min(-inf, 499.0));
+ Expect.equals(-inf, min(-inf, inf));
+ Expect.isTrue(min(-inf, nan).isNaN);
+
+ Expect.equals(-inf, min(-499.0, -inf));
+ Expect.equals(-499.0, min(-499.0, -499.0));
+ Expect.equals(-499.0, min(-499.0, -499));
+ Expect.equals(-499.0, min(-499.0, -0.0));
+ Expect.equals(-499.0, min(-499.0, 0.0));
+ Expect.equals(-499.0, min(-499.0, 0));
+ Expect.equals(-499.0, min(-499.0, 499.0));
+ Expect.equals(-499.0, min(-499.0, 499));
+ Expect.equals(-499.0, min(-499.0, inf));
+ Expect.isTrue(min(-499.0, nan).isNaN);
+
+ Expect.isTrue(min(-499.0, -499.0) is double);
+ Expect.isTrue(min(-499.0, -499) is double);
+ Expect.isTrue(min(-499.0, -0.0) is double);
+ Expect.isTrue(min(-499.0, 0.0) is double);
+ Expect.isTrue(min(-499.0, 0) is double);
+ Expect.isTrue(min(-499.0, 499.0) is double);
+ Expect.isTrue(min(-499.0, 499) is double);
+ Expect.isTrue(min(-499.0, inf) is double);
+
+ Expect.equals(-inf, min(-499, -inf));
+ Expect.equals(-499, min(-499, -499.0));
+ Expect.equals(-499, min(-499, -499));
+ Expect.equals(-499, min(-499, -0.0));
+ Expect.equals(-499, min(-499, 0.0));
+ Expect.equals(-499, min(-499, 0));
+ Expect.equals(-499, min(-499, 499.0));
+ Expect.equals(-499, min(-499, 499));
+ Expect.equals(-499, min(-499, inf));
+ Expect.isTrue(min(-499, nan).isNaN);
+
+ Expect.isTrue(min(-499, -499.0) is int);
+ Expect.isTrue(min(-499, -499) is int);
+ Expect.isTrue(min(-499, -0.0) is int);
+ Expect.isTrue(min(-499, 0.0) is int);
+ Expect.isTrue(min(-499, 0) is int);
+ Expect.isTrue(min(-499, 499.0) is int);
+ Expect.isTrue(min(-499, 499) is int);
+ Expect.isTrue(min(-499, inf) is int);
+
+ Expect.equals(-inf, min(-0.0, -inf));
+ Expect.equals(-499.0, min(-0.0, -499.0));
+ Expect.equals(-499, min(-0.0, -499));
+ Expect.equals(-0.0, min(-0.0, -0.0));
+ Expect.equals(-0.0, min(-0.0, 0.0));
+ Expect.equals(-0.0, min(-0.0, 0));
+ Expect.equals(-0.0, min(-0.0, 499.0));
+ Expect.equals(-0.0, min(-0.0, 499));
+ Expect.equals(-0.0, min(-0.0, inf));
+ Expect.isTrue(min(-0.0, nan).isNaN);
+}
+
+testMin2() {
+ Expect.isTrue(min(-0.0, -499.0) is double);
+ Expect.isTrue(min(-0.0, -499) is int);
+ Expect.isTrue(min(-0.0, -0.0) is double);
+ Expect.isTrue(min(-0.0, 0.0) is double);
+ Expect.isTrue(min(-0.0, 0) is double);
+ Expect.isTrue(min(-0.0, 499.0) is double);
+ Expect.isTrue(min(-0.0, 499) is double);
+ Expect.isTrue(min(-0.0, inf) is double);
+
+ Expect.isTrue(min(-0.0, -499.0).isNegative);
+ Expect.isTrue(min(-0.0, -499).isNegative);
+ Expect.isTrue(min(-0.0, -0.0).isNegative);
+ Expect.isTrue(min(-0.0, 0.0).isNegative);
+ Expect.isTrue(min(-0.0, 0).isNegative);
+ Expect.isTrue(min(-0.0, 499.0).isNegative);
+ Expect.isTrue(min(-0.0, 499).isNegative);
+ Expect.isTrue(min(-0.0, inf).isNegative);
+
+ Expect.equals(-inf, min(0.0, -inf));
+ Expect.equals(-499.0, min(0.0, -499.0));
+ Expect.equals(-499, min(0.0, -499));
+ Expect.equals(-0.0, min(0.0, -0.0));
+ Expect.equals(0.0, min(0.0, 0.0));
+ Expect.equals(0.0, min(0.0, 0));
+ Expect.equals(0.0, min(0.0, 499.0));
+ Expect.equals(0.0, min(0.0, 499));
+ Expect.equals(0.0, min(0.0, inf));
+ Expect.isTrue(min(0.0, nan).isNaN);
+
+ Expect.isTrue(min(0.0, -499.0) is double);
+ Expect.isTrue(min(0.0, -499) is int);
+ Expect.isTrue(min(0.0, -0.0) is double);
+ Expect.isTrue(min(0.0, 0.0) is double);
+ Expect.isTrue(min(0.0, 0) is double);
+ Expect.isTrue(min(0.0, 499.0) is double);
+ Expect.isTrue(min(0.0, 499) is double);
+ Expect.isTrue(min(0.0, inf) is double);
+
+ Expect.isTrue(min(0.0, -499.0).isNegative);
+ Expect.isTrue(min(0.0, -499).isNegative);
+ Expect.isTrue(min(0.0, -0.0).isNegative);
+ Expect.isFalse(min(0.0, 0.0).isNegative);
+ Expect.isFalse(min(0.0, 0).isNegative);
+ Expect.isFalse(min(0.0, 499.0).isNegative);
+ Expect.isFalse(min(0.0, 499).isNegative);
+ Expect.isFalse(min(0.0, inf).isNegative);
+
+ Expect.equals(-inf, min(0, -inf));
+ Expect.equals(-499.0, min(0, -499.0));
+ Expect.equals(-499, min(0, -499));
+ Expect.equals(-0.0, min(0, -0.0));
+ Expect.equals(0, min(0, 0.0));
+ Expect.equals(0, min(0, 0));
+ Expect.equals(0, min(0, 499.0));
+ Expect.equals(0, min(0, 499));
+ Expect.equals(0, min(0, inf));
+ Expect.isTrue(min(0, nan).isNaN);
+
+ Expect.isTrue(min(0, -499.0) is double);
+ Expect.isTrue(min(0, -499) is int);
+ Expect.isTrue(min(0, -0.0) is double);
+ Expect.isTrue(min(0, 0.0) is int);
+ Expect.isTrue(min(0, 0) is int);
+ Expect.isTrue(min(0, 499.0) is int);
+ Expect.isTrue(min(0, 499) is int);
+ Expect.isTrue(min(0, inf) is int);
+ Expect.isTrue(min(0, -499.0).isNegative);
+ Expect.isTrue(min(0, -499).isNegative);
+ Expect.isTrue(min(0, -0.0).isNegative);
+ Expect.isFalse(min(0, 0.0).isNegative);
+ Expect.isFalse(min(0, 0).isNegative);
+ Expect.isFalse(min(0, 499.0).isNegative);
+ Expect.isFalse(min(0, 499).isNegative);
+ Expect.isFalse(min(0, inf).isNegative);
+}
+
+testMin3() {
+ Expect.equals(-inf, min(499.0, -inf));
+ Expect.equals(-499.0, min(499.0, -499.0));
+ Expect.equals(-499, min(499.0, -499));
+ Expect.equals(-0.0, min(499.0, -0.0));
+ Expect.equals(0.0, min(499.0, 0.0));
+ Expect.equals(0, min(499.0, 0));
+ Expect.equals(499.0, min(499.0, 499.0));
+ Expect.equals(499.0, min(499.0, 499));
+ Expect.equals(499.0, min(499.0, inf));
+ Expect.isTrue(min(499.0, nan).isNaN);
+
+ Expect.isTrue(min(499.0, -499.0) is double);
+ Expect.isTrue(min(499.0, -499) is int);
+ Expect.isTrue(min(499.0, -0.0) is double);
+ Expect.isTrue(min(499.0, 0.0) is double);
+ Expect.isTrue(min(499.0, 0) is int);
+ Expect.isTrue(min(499.0, 499) is double);
+ Expect.isTrue(min(499.0, 499.0) is double);
+ Expect.isTrue(min(499.0, inf) is double);
+
+ Expect.isTrue(min(499.0, -499.0).isNegative);
+ Expect.isTrue(min(499.0, -499).isNegative);
+ Expect.isTrue(min(499.0, -0.0).isNegative);
+ Expect.isFalse(min(499.0, 0.0).isNegative);
+ Expect.isFalse(min(499.0, 0).isNegative);
+ Expect.isFalse(min(499.0, 499).isNegative);
+ Expect.isFalse(min(499.0, 499.0).isNegative);
+ Expect.isFalse(min(499.0, inf).isNegative);
+
+ Expect.equals(-inf, min(499, -inf));
+ Expect.equals(-499.0, min(499, -499.0));
+ Expect.equals(-499, min(499, -499));
+ Expect.equals(-0.0, min(499, -0.0));
+ Expect.equals(0.0, min(499, 0.0));
+ Expect.equals(0, min(499, 0));
+ Expect.equals(499, min(499, 499.0));
+ Expect.equals(499, min(499, 499));
+ Expect.equals(499, min(499, inf));
+ Expect.isTrue(min(499, nan).isNaN);
+
+ Expect.isTrue(min(499, -499.0) is double);
+ Expect.isTrue(min(499, -499) is int);
+ Expect.isTrue(min(499, -0.0) is double);
+ Expect.isTrue(min(499, 0.0) is double);
+ Expect.isTrue(min(499, 0) is int);
+ Expect.isTrue(min(499, 499.0) is int);
+ Expect.isTrue(min(499, 499) is int);
+ Expect.isTrue(min(499, inf) is int);
+
+ Expect.isTrue(min(499, -499.0).isNegative);
+ Expect.isTrue(min(499, -499).isNegative);
+ Expect.isTrue(min(499, -0.0).isNegative);
+ Expect.isFalse(min(499, 0.0).isNegative);
+ Expect.isFalse(min(499, 0).isNegative);
+ Expect.isFalse(min(499, 499.0).isNegative);
+ Expect.isFalse(min(499, 499).isNegative);
+ Expect.isFalse(min(499, inf).isNegative);
+
+ Expect.equals(-inf, min(inf, -inf));
+ Expect.equals(-499.0, min(inf, -499.0));
+ Expect.equals(-499, min(inf, -499));
+ Expect.equals(-0.0, min(inf, -0.0));
+ Expect.equals(0.0, min(inf, 0.0));
+ Expect.equals(0, min(inf, 0));
+ Expect.equals(499.0, min(inf, 499.0));
+ Expect.equals(499, min(inf, 499));
+ Expect.equals(inf, min(inf, inf));
+ Expect.isTrue(min(inf, nan).isNaN);
+
+ Expect.isTrue(min(inf, -499.0) is double);
+ Expect.isTrue(min(inf, -499) is int);
+ Expect.isTrue(min(inf, -0.0) is double);
+ Expect.isTrue(min(inf, 0.0) is double);
+ Expect.isTrue(min(inf, 0) is int);
+ Expect.isTrue(min(inf, 499) is int);
+ Expect.isTrue(min(inf, 499.0) is double);
+ Expect.isTrue(min(inf, inf) is double);
+
+ Expect.isTrue(min(inf, -499.0).isNegative);
+ Expect.isTrue(min(inf, -499).isNegative);
+ Expect.isTrue(min(inf, -0.0).isNegative);
+ Expect.isFalse(min(inf, 0.0).isNegative);
+ Expect.isFalse(min(inf, 0).isNegative);
+ Expect.isFalse(min(inf, 499).isNegative);
+ Expect.isFalse(min(inf, 499.0).isNegative);
+ Expect.isFalse(min(inf, inf).isNegative);
+}
+
+testMax() {
+ testMax1();
+ testMax2();
+ testMax3();
+}
+
+testMax1() {
+ Expect.equals(2, max(0, 2));
+ Expect.equals(2, max(2, 0));
+
+ Expect.equals(-9, max(-10, -9));
+ Expect.equals(9, max(-10, 9));
+ Expect.equals(0, max(-10, 0));
+ Expect.equals(-9, max(-9, -10));
+ Expect.equals(9, max(9, -10));
+ Expect.equals(0, max(0, -10));
+
+ Expect.equals(2.5, max(0.5, 2.5));
+ Expect.equals(2.5, max(2.5, 0.5));
+
+ Expect.equals(-9.5, max(-10.5, -9.5));
+ Expect.equals(9.5, max(-10.5, 9.5));
+ Expect.equals(0.5, max(-10.5, 0.5));
+ Expect.equals(-9.5, max(-9.5, -10.5));
+ Expect.equals(9.5, max(9.5, -10.5));
+ Expect.equals(0.5, max(0.5, -10.5));
+
+ // Test matrix:
+ // NaN, infinity, 499.0, 499, 0.0, 0, -0.0, -499.0, -499, -infinity.
+
+ Expect.isTrue(max(nan, nan).isNaN);
+ Expect.isTrue(max(nan, -inf).isNaN);
+ Expect.isTrue(max(nan, -499.0).isNaN);
+ Expect.isTrue(max(nan, -499).isNaN);
+ Expect.isTrue(max(nan, -0.0).isNaN);
+ Expect.isTrue(max(nan, 0.0).isNaN);
+ Expect.isTrue(max(nan, 499.0).isNaN);
+ Expect.isTrue(max(nan, 499).isNaN);
+ Expect.isTrue(max(nan, inf).isNaN);
+
+ Expect.equals(inf, max(inf, inf));
+ Expect.equals(inf, max(inf, 499.0));
+ Expect.equals(inf, max(inf, 499));
+ Expect.equals(inf, max(inf, 0.0));
+ Expect.equals(inf, max(inf, 0));
+ Expect.equals(inf, max(inf, -0.0));
+ Expect.equals(inf, max(inf, -499));
+ Expect.equals(inf, max(inf, -499.0));
+ Expect.equals(inf, max(inf, -inf));
+ Expect.isTrue(max(inf, nan).isNaN);
+
+ Expect.equals(inf, max(499.0, inf));
+ Expect.equals(499.0, max(499.0, 499.0));
+ Expect.equals(499.0, max(499.0, 499));
+ Expect.equals(499.0, max(499.0, 0.0));
+ Expect.equals(499.0, max(499.0, 0));
+ Expect.equals(499.0, max(499.0, -0.0));
+ Expect.equals(499.0, max(499.0, -499));
+ Expect.equals(499.0, max(499.0, -499.0));
+ Expect.equals(499.0, max(499.0, -inf));
+ Expect.isTrue(max(499.0, nan).isNaN);
+
+ Expect.isTrue(max(499.0, 499.0) is double);
+ Expect.isTrue(max(499.0, 499) is double);
+ Expect.isTrue(max(499.0, 0.0) is double);
+ Expect.isTrue(max(499.0, 0) is double);
+ Expect.isTrue(max(499.0, -0.0) is double);
+ Expect.isTrue(max(499.0, -499) is double);
+ Expect.isTrue(max(499.0, -499.0) is double);
+ Expect.isTrue(max(499.0, -inf) is double);
+
+ Expect.equals(inf, max(499, inf));
+ Expect.equals(499, max(499, 499.0));
+ Expect.equals(499, max(499, 499));
+ Expect.equals(499, max(499, 0.0));
+ Expect.equals(499, max(499, 0));
+ Expect.equals(499, max(499, -0.0));
+ Expect.equals(499, max(499, -499));
+ Expect.equals(499, max(499, -499.0));
+ Expect.equals(499, max(499, -inf));
+ Expect.isTrue(max(499, nan).isNaN);
+
+ Expect.isTrue(max(499, 499.0) is int);
+ Expect.isTrue(max(499, 499) is int);
+ Expect.isTrue(max(499, 0.0) is int);
+ Expect.isTrue(max(499, 0) is int);
+ Expect.isTrue(max(499, -0.0) is int);
+ Expect.isTrue(max(499, -499) is int);
+ Expect.isTrue(max(499, -499.0) is int);
+ Expect.isTrue(max(499, -inf) is int);
+
+ Expect.equals(inf, max(0.0, inf));
+ Expect.equals(499.0, max(0.0, 499.0));
+ Expect.equals(499, max(0.0, 499));
+ Expect.equals(0.0, max(0.0, 0.0));
+ Expect.equals(0.0, max(0.0, 0));
+ Expect.equals(0.0, max(0.0, -0.0));
+ Expect.equals(0.0, max(0.0, -499));
+ Expect.equals(0.0, max(0.0, -499.0));
+ Expect.equals(0.0, max(0.0, -inf));
+ Expect.isTrue(max(0.0, nan).isNaN);
+
+ Expect.isTrue(max(0.0, 499.0) is double);
+ Expect.isTrue(max(0.0, 499) is int);
+ Expect.isTrue(max(0.0, 0.0) is double);
+ Expect.isTrue(max(0.0, 0) is double);
+ Expect.isTrue(max(0.0, -0.0) is double);
+ Expect.isTrue(max(0.0, -499) is double);
+ Expect.isTrue(max(0.0, -499.0) is double);
+ Expect.isTrue(max(0.0, -inf) is double);
+}
+
+testMax2() {
+ Expect.isFalse(max(0.0, 0.0).isNegative);
+ Expect.isFalse(max(0.0, 0).isNegative);
+ Expect.isFalse(max(0.0, -0.0).isNegative);
+ Expect.isFalse(max(0.0, -499).isNegative);
+ Expect.isFalse(max(0.0, -499.0).isNegative);
+ Expect.isFalse(max(0.0, -inf).isNegative);
+
+ Expect.equals(inf, max(0, inf));
+ Expect.equals(499.0, max(0, 499.0));
+ Expect.equals(499, max(0, 499));
+ Expect.equals(0, max(0, 0.0));
+ Expect.equals(0, max(0, 0));
+ Expect.equals(0, max(0, -0.0));
+ Expect.equals(0, max(0, -499));
+ Expect.equals(0, max(0, -499.0));
+ Expect.equals(0, max(0, -inf));
+ Expect.isTrue(max(0, nan).isNaN);
+
+ Expect.isTrue(max(0, 499.0) is double);
+ Expect.isTrue(max(0, 499) is int);
+ Expect.isTrue(max(0, 0.0) is int);
+ Expect.isTrue(max(0, 0) is int);
+ Expect.isTrue(max(0, -0.0) is int);
+ Expect.isTrue(max(0, -499) is int);
+ Expect.isTrue(max(0, -499.0) is int);
+ Expect.isTrue(max(0, -inf) is int);
+
+ Expect.isFalse(max(0, 0.0).isNegative);
+ Expect.isFalse(max(0, 0).isNegative);
+ Expect.isFalse(max(0, -0.0).isNegative);
+ Expect.isFalse(max(0, -499).isNegative);
+ Expect.isFalse(max(0, -499.0).isNegative);
+ Expect.isFalse(max(0, -inf).isNegative);
+
+ Expect.equals(inf, max(-0.0, inf));
+ Expect.equals(499.0, max(-0.0, 499.0));
+ Expect.equals(499, max(-0.0, 499));
+ Expect.equals(0.0, max(-0.0, 0.0));
+ Expect.equals(0.0, max(-0.0, 0));
+ Expect.equals(-0.0, max(-0.0, -0.0));
+ Expect.equals(-0.0, max(-0.0, -499));
+ Expect.equals(-0.0, max(-0.0, -499.0));
+ Expect.equals(-0.0, max(-0.0, -inf));
+ Expect.isTrue(max(-0.0, nan).isNaN);
+
+ Expect.isTrue(max(-0.0, 499.0) is double);
+ Expect.isTrue(max(-0.0, 499) is int);
+ Expect.isTrue(max(-0.0, 0.0) is double);
+ Expect.isTrue(max(-0.0, 0) is int);
+ Expect.isTrue(max(-0.0, -0.0) is double);
+ Expect.isTrue(max(-0.0, -499) is double);
+ Expect.isTrue(max(-0.0, -499.0) is double);
+ Expect.isTrue(max(-0.0, -inf) is double);
+}
+
+testMax3() {
+ Expect.isFalse(max(-0.0, 0.0).isNegative);
+ Expect.isFalse(max(-0.0, 0).isNegative);
+ Expect.isTrue(max(-0.0, -0.0).isNegative);
+ Expect.isTrue(max(-0.0, -499).isNegative);
+ Expect.isTrue(max(-0.0, -499.0).isNegative);
+ Expect.isTrue(max(-0.0, -inf).isNegative);
+
+ Expect.equals(inf, max(-499, inf));
+ Expect.equals(499.0, max(-499, 499.0));
+ Expect.equals(499, max(-499, 499));
+ Expect.equals(0.0, max(-499, 0.0));
+ Expect.equals(0.0, max(-499, 0));
+ Expect.equals(-0.0, max(-499, -0.0));
+ Expect.equals(-499, max(-499, -499));
+ Expect.equals(-499, max(-499, -499.0));
+ Expect.equals(-499, max(-499, -inf));
+ Expect.isTrue(max(-499, nan).isNaN);
+
+ Expect.isTrue(max(-499, 499.0) is double);
+ Expect.isTrue(max(-499, 499) is int);
+ Expect.isTrue(max(-499, 0.0) is double);
+ Expect.isTrue(max(-499, 0) is int);
+ Expect.isTrue(max(-499, -0.0) is double);
+ Expect.isTrue(max(-499, -499) is int);
+ Expect.isTrue(max(-499, -499.0) is int);
+ Expect.isTrue(max(-499, -inf) is int);
+
+ Expect.isFalse(max(-499, 0.0).isNegative);
+ Expect.isFalse(max(-499, 0).isNegative);
+ Expect.isTrue(max(-499, -0.0).isNegative);
+ Expect.isTrue(max(-499, -499).isNegative);
+ Expect.isTrue(max(-499, -499.0).isNegative);
+ Expect.isTrue(max(-499, -inf).isNegative);
+
+ Expect.equals(inf, max(-499.0, inf));
+ Expect.equals(499.0, max(-499.0, 499.0));
+ Expect.equals(499, max(-499.0, 499));
+ Expect.equals(0.0, max(-499.0, 0.0));
+ Expect.equals(0.0, max(-499.0, 0));
+ Expect.equals(-0.0, max(-499.0, -0.0));
+ Expect.equals(-499.0, max(-499.0, -499));
+ Expect.equals(-499.0, max(-499.0, -499.0));
+ Expect.equals(-499.0, max(-499.0, -inf));
+ Expect.isTrue(max(-499.0, nan).isNaN);
+
+ Expect.isTrue(max(-499.0, 499.0) is double);
+ Expect.isTrue(max(-499.0, 499) is int);
+ Expect.isTrue(max(-499.0, 0.0) is double);
+ Expect.isTrue(max(-499.0, 0) is int);
+ Expect.isTrue(max(-499.0, -0.0) is double);
+ Expect.isTrue(max(-499.0, -499) is double);
+ Expect.isTrue(max(-499.0, -499.0) is double);
+ Expect.isTrue(max(-499.0, -inf) is double);
+
+ Expect.isFalse(max(-499.0, 0.0).isNegative);
+ Expect.isFalse(max(-499.0, 0).isNegative);
+ Expect.isTrue(max(-499.0, -0.0).isNegative);
+ Expect.isTrue(max(-499.0, -499).isNegative);
+ Expect.isTrue(max(-499.0, -499.0).isNegative);
+ Expect.isTrue(max(-499.0, -inf).isNegative);
+
+ Expect.equals(inf, max(-inf, inf));
+ Expect.equals(499.0, max(-inf, 499.0));
+ Expect.equals(499, max(-inf, 499));
+ Expect.equals(0.0, max(-inf, 0.0));
+ Expect.equals(0.0, max(-inf, 0));
+ Expect.equals(-0.0, max(-inf, -0.0));
+ Expect.equals(-499, max(-inf, -499));
+ Expect.equals(-499.0, max(-inf, -499.0));
+ Expect.equals(-inf, max(-inf, -inf));
+ Expect.isTrue(max(-inf, nan).isNaN);
+
+ Expect.isTrue(max(-inf, 499.0) is double);
+ Expect.isTrue(max(-inf, 499) is int);
+ Expect.isTrue(max(-inf, 0.0) is double);
+ Expect.isTrue(max(-inf, 0) is int);
+ Expect.isTrue(max(-inf, -0.0) is double);
+ Expect.isTrue(max(-inf, -499) is int);
+ Expect.isTrue(max(-inf, -499.0) is double);
+ Expect.isTrue(max(-inf, -inf) is double);
+
+ Expect.isFalse(max(-inf, 0.0).isNegative);
+ Expect.isFalse(max(-inf, 0).isNegative);
+ Expect.isTrue(max(-inf, -0.0).isNegative);
+ Expect.isTrue(max(-inf, -499).isNegative);
+ Expect.isTrue(max(-inf, -499.0).isNegative);
+ Expect.isTrue(max(-inf, -inf).isNegative);
+}
+
+main() {
+ testMin();
+ testMin();
+ testMax();
+ testMax();
+}
diff --git a/tests/lib/math/pi_test.dart b/tests/lib/math/pi_test.dart
new file mode 100644
index 0000000..b867132
--- /dev/null
+++ b/tests/lib/math/pi_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2012, 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.
+
+// Test that the default PRNG does converge towards Pi when doing a Monte Carlo
+// simulation.
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+var known_bad_seeds = const [50051, 55597, 59208];
+
+void main([args]) {
+ // Select a seed either from the argument passed in or
+ // otherwise a random seed.
+ var seed = -1;
+ if ((args != null) && (args.length > 0)) {
+ seed = int.parse(args[0]);
+ } else {
+ var seed_prng = new Random();
+ while (seed == -1) {
+ seed = seed_prng.nextInt(1 << 16);
+ if (known_bad_seeds.contains(seed)) {
+ // Reset seed and try again.
+ seed = -1;
+ }
+ }
+ }
+
+ // Setup the PRNG for the Monte Carlo simulation.
+ print("pi_test seed: $seed");
+ var prng = new Random(seed);
+
+ var outside = 0;
+ var inside = 0;
+ for (var i = 0; i < 600000; i++) {
+ var x = prng.nextDouble();
+ var y = prng.nextDouble();
+ if ((x * x) + (y * y) < 1.0) {
+ inside++;
+ } else {
+ outside++;
+ }
+ }
+ // Mmmmh, Pie!
+ var pie = 4.0 * (inside / (inside + outside));
+ print("$pie");
+ Expect.isTrue(((pi - 0.009) < pie) && (pie < (pi + 0.009)));
+}
diff --git a/tests/lib/math/point_test.dart b/tests/lib/math/point_test.dart
new file mode 100644
index 0000000..7e6979a
--- /dev/null
+++ b/tests/lib/math/point_test.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2013, 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.
+
+import 'dart:math';
+import 'package:expect/expect.dart';
+
+main() {
+ // constructor
+ {
+ var point = new Point(0, 0);
+ Expect.equals(0, point.x);
+ Expect.equals(0, point.y);
+ Expect.equals('Point(0, 0)', '$point');
+ }
+
+ // constructor X
+ {
+ var point = new Point<int>(10, 0);
+ Expect.equals(10, point.x);
+ Expect.equals(0, point.y);
+ Expect.equals('Point(10, 0)', '$point');
+ }
+
+ // constructor X Y
+ {
+ var point = new Point<int>(10, 20);
+ Expect.equals(10, point.x);
+ Expect.equals(20, point.y);
+ Expect.equals('Point(10, 20)', '$point');
+ }
+
+ // constructor X Y double
+ {
+ var point = new Point<double>(10.5, 20.897);
+ Expect.equals(10.5, point.x);
+ Expect.equals(20.897, point.y);
+ Expect.equals('Point(10.5, 20.897)', '$point');
+ }
+
+ // constructor X Y NaN
+ {
+ var point = new Point(double.nan, 1000);
+ Expect.isTrue(point.x.isNaN);
+ Expect.equals(1000, point.y);
+ Expect.equals('Point(NaN, 1000)', '$point');
+ }
+
+ // squaredDistanceTo
+ {
+ var a = new Point(7, 11);
+ var b = new Point(3, -1);
+ Expect.equals(160, a.squaredDistanceTo(b));
+ Expect.equals(160, b.squaredDistanceTo(a));
+ }
+
+ // distanceTo
+ {
+ var a = new Point(-2, -3);
+ var b = new Point(2, 0);
+ Expect.equals(5, a.distanceTo(b));
+ Expect.equals(5, b.distanceTo(a));
+ }
+
+ // subtract
+ {
+ var a = new Point(5, 10);
+ var b = new Point(2, 50);
+ Expect.equals(new Point(3, -40), a - b);
+ }
+
+ // add
+ {
+ var a = new Point(5, 10);
+ var b = new Point(2, 50);
+ Expect.equals(new Point(7, 60), a + b);
+ }
+
+ // hashCode
+ {
+ var a = new Point(0, 1);
+ var b = new Point(0, 1);
+ Expect.equals(b.hashCode, a.hashCode);
+
+ var c = new Point(1, 0);
+ Expect.isFalse(a.hashCode == c.hashCode);
+ }
+
+ // magnitude
+ {
+ var a = new Point(5, 10);
+ var b = new Point(0, 0);
+ Expect.equals(a.distanceTo(b), a.magnitude);
+ Expect.equals(0, b.magnitude);
+
+ var c = new Point(-5, -10);
+ Expect.equals(a.distanceTo(b), c.magnitude);
+ }
+}
diff --git a/tests/lib/math/random_big_test.dart b/tests/lib/math/random_big_test.dart
new file mode 100644
index 0000000..41a5651
--- /dev/null
+++ b/tests/lib/math/random_big_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2014, 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.
+
+// Test that Random can deal with a seed outside 64-bit range.
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+main() {
+ var results = [];
+ for (var i = 60; i < 64; i++) {
+ var rng = new Random(1 << i);
+ var val = rng.nextInt(100000);
+ print("$i: $val");
+ Expect.isFalse(results.contains(val));
+ results.add(val);
+ }
+}
diff --git a/tests/lib/math/random_secure_test.dart b/tests/lib/math/random_secure_test.dart
new file mode 100644
index 0000000..a28a215
--- /dev/null
+++ b/tests/lib/math/random_secure_test.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2015, 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.
+
+// Test that the secure random generator does not systematically generates
+// duplicates. Note that this test is flaky by definition, since duplicates
+// can occur. They should be extremely rare, though.
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+main() {
+ var results;
+ var rng0;
+ var rng1;
+ var checkInt = (max) {
+ var intVal0 = rng0.nextInt(max);
+ var intVal1 = rng1.nextInt(max);
+ if (max > (1 << 28)) {
+ Expect.isFalse(results.contains(intVal0));
+ results.add(intVal0);
+ Expect.isFalse(results.contains(intVal1));
+ results.add(intVal1);
+ }
+ };
+ results = [];
+ rng0 = new Random.secure();
+ for (var i = 0; i <= 32; i++) {
+ rng1 = new Random.secure();
+ checkInt(pow(2, 32));
+ checkInt(pow(2, 32 - i));
+ checkInt(1000000000);
+ }
+ var checkDouble = () {
+ var doubleVal0 = rng0.nextDouble();
+ var doubleVal1 = rng1.nextDouble();
+ Expect.isFalse(results.contains(doubleVal0));
+ results.add(doubleVal0);
+ Expect.isFalse(results.contains(doubleVal1));
+ results.add(doubleVal1);
+ };
+ results = [];
+ rng0 = new Random.secure();
+ for (var i = 0; i < 32; i++) {
+ rng1 = new Random.secure();
+ checkDouble();
+ }
+ var cnt0 = 0;
+ var cnt1 = 0;
+ rng0 = new Random.secure();
+ for (var i = 0; i < 32; i++) {
+ rng1 = new Random.secure();
+ cnt0 += rng0.nextBool() ? 1 : 0;
+ cnt1 += rng1.nextBool() ? 1 : 0;
+ }
+ Expect.isTrue((cnt0 > 0) && (cnt0 < 32));
+ Expect.isTrue((cnt1 > 0) && (cnt1 < 32));
+}
diff --git a/tests/lib/math/random_secure_unsupported_test.dart b/tests/lib/math/random_secure_unsupported_test.dart
new file mode 100644
index 0000000..7e8744c
--- /dev/null
+++ b/tests/lib/math/random_secure_unsupported_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, 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.
+
+// Test that `Random.secure()` throws `UnsupportedError` each time it fails.
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+main() {
+ var result1 = getRandom();
+ var result2 = getRandom();
+
+ Expect.isNotNull(result1);
+ Expect.isNotNull(result2); // This fired for http://dartbug.com/36206
+
+ Expect.equals(result1 is Random, result2 is Random);
+ Expect.equals(result1 is UnsupportedError, result2 is UnsupportedError);
+}
+
+dynamic getRandom() {
+ try {
+ return Random.secure();
+ } catch (e) {
+ return e;
+ }
+}
diff --git a/tests/lib/math/random_test.dart b/tests/lib/math/random_test.dart
new file mode 100644
index 0000000..9e66365
--- /dev/null
+++ b/tests/lib/math/random_test.dart
@@ -0,0 +1,239 @@
+// Copyright (c) 2013, 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.
+
+// Test that rnd.nextInt with a seed generates the same sequence each time.
+
+// Library tag to allow Dartium to run the test.
+library random_test;
+
+import "package:expect/expect.dart";
+import 'dart:math';
+
+main() {
+ checkSequence();
+ checkSeed();
+}
+
+void checkSequence() {
+ // Check the sequence of numbers generated by the random generator for a seed
+ // doesn't change unintendedly, and it agrees between implementations.
+ var rnd = new Random(20130307);
+ // Make sure we do not break the random number generation.
+ // If the random algorithm changes, make sure both the VM and dart2js
+ // generate the same new sequence.
+ var i = 1;
+ Expect.equals(0, rnd.nextInt(i *= 2));
+ Expect.equals(3, rnd.nextInt(i *= 2));
+ Expect.equals(7, rnd.nextInt(i *= 2));
+ Expect.equals(5, rnd.nextInt(i *= 2));
+ Expect.equals(29, rnd.nextInt(i *= 2));
+ Expect.equals(17, rnd.nextInt(i *= 2));
+ Expect.equals(104, rnd.nextInt(i *= 2));
+ Expect.equals(199, rnd.nextInt(i *= 2));
+ Expect.equals(408, rnd.nextInt(i *= 2));
+ Expect.equals(362, rnd.nextInt(i *= 2));
+ Expect.equals(995, rnd.nextInt(i *= 2));
+ Expect.equals(2561, rnd.nextInt(i *= 2));
+ Expect.equals(2548, rnd.nextInt(i *= 2));
+ Expect.equals(9553, rnd.nextInt(i *= 2));
+ Expect.equals(2628, rnd.nextInt(i *= 2));
+ Expect.equals(42376, rnd.nextInt(i *= 2));
+ Expect.equals(101848, rnd.nextInt(i *= 2));
+ Expect.equals(85153, rnd.nextInt(i *= 2));
+ Expect.equals(495595, rnd.nextInt(i *= 2));
+ Expect.equals(647122, rnd.nextInt(i *= 2));
+ Expect.equals(793546, rnd.nextInt(i *= 2));
+ Expect.equals(1073343, rnd.nextInt(i *= 2));
+ Expect.equals(4479969, rnd.nextInt(i *= 2));
+ Expect.equals(9680425, rnd.nextInt(i *= 2));
+ Expect.equals(28460171, rnd.nextInt(i *= 2));
+ Expect.equals(49481738, rnd.nextInt(i *= 2));
+ Expect.equals(9878974, rnd.nextInt(i *= 2));
+ Expect.equals(132552472, rnd.nextInt(i *= 2));
+ Expect.equals(210267283, rnd.nextInt(i *= 2));
+ Expect.equals(125422442, rnd.nextInt(i *= 2));
+ Expect.equals(226275094, rnd.nextInt(i *= 2));
+ Expect.equals(1639629168, rnd.nextInt(i *= 2));
+ Expect.equals(0x100000000, i);
+ // If max is too large expect an ArgumentError.
+ Expect.throwsArgumentError(() => rnd.nextInt(i + 1));
+
+ rnd = new Random(6790);
+ Expect.approxEquals(0.1202733131, rnd.nextDouble());
+ Expect.approxEquals(0.5554054805, rnd.nextDouble());
+ Expect.approxEquals(0.0385160727, rnd.nextDouble());
+ Expect.approxEquals(0.2836345217, rnd.nextDouble());
+}
+
+void checkSeed() {
+ // Check that various seeds generate the expected first values.
+ // 53 significant bits, so the number is representable in JS.
+ var rawSeed = 0x19a32c640e1d71;
+ var expectations = [
+ 26007,
+ 43006,
+ 46458,
+ 18610,
+ 16413,
+ 50455,
+ 2164,
+ 47399,
+ 8859,
+ 9732,
+ 20367,
+ 33935,
+ 54549,
+ 54913,
+ 4819,
+ 24198,
+ 49353,
+ 22277,
+ 51852,
+ 35959,
+ 45347,
+ 12100,
+ 10136,
+ 22372,
+ 15293,
+ 20066,
+ 1351,
+ 49030,
+ 64845,
+ 12793,
+ 50916,
+ 55784,
+ 43170,
+ 27653,
+ 34696,
+ 1492,
+ 50255,
+ 9597,
+ 45929,
+ 2874,
+ 27629,
+ 53084,
+ 36064,
+ 42140,
+ 32016,
+ 41751,
+ 13967,
+ 20516,
+ 578,
+ 16773,
+ 53064,
+ 14814,
+ 22737,
+ 48846,
+ 45147,
+ 10205,
+ 56584,
+ 63711,
+ 44128,
+ 21099,
+ 47966,
+ 35471,
+ 39576,
+ 1141,
+ 45716,
+ 54940,
+ 57406,
+ 15437,
+ 31721,
+ 35044,
+ 28136,
+ 39797,
+ 50801,
+ 22184,
+ 58686
+ ];
+ var negative_seed_expectations = [
+ 12170,
+ 42844,
+ 39228,
+ 64032,
+ 29046,
+ 57572,
+ 8453,
+ 52224,
+ 27060,
+ 28454,
+ 20510,
+ 28804,
+ 59221,
+ 53422,
+ 11047,
+ 50864,
+ 33997,
+ 19611,
+ 1250,
+ 65088,
+ 19690,
+ 11396,
+ 20,
+ 48867,
+ 44862,
+ 47129,
+ 58724,
+ 13325,
+ 50005,
+ 33320,
+ 16523,
+ 4740,
+ 63721,
+ 63272,
+ 30545,
+ 51403,
+ 35845,
+ 3943,
+ 31850,
+ 23148,
+ 26307,
+ 1724,
+ 29281,
+ 39988,
+ 43653,
+ 48012,
+ 43810,
+ 16755,
+ 13105,
+ 25325,
+ 32648,
+ 19958,
+ 38838,
+ 8322,
+ 3421,
+ 28624,
+ 17269,
+ 45385,
+ 50680,
+ 1696,
+ 26088,
+ 2787,
+ 48566,
+ 34357,
+ 27731,
+ 51764,
+ 8455,
+ 16498,
+ 59721,
+ 59568,
+ 46333,
+ 7935,
+ 51459,
+ 36766,
+ 50711
+ ];
+ for (var i = 0, m = 1; i < 75; i++) {
+ if (rawSeed * m < 0) {
+ // Overflow.
+ break;
+ }
+ Expect.equals(expectations[i], new Random(rawSeed * m).nextInt(65536));
+ Expect.equals(
+ negative_seed_expectations[i], new Random(rawSeed * -m).nextInt(65536));
+ m *= 2;
+ }
+ // And test zero seed too.
+ Expect.equals(21391, new Random(0).nextInt(65536));
+}
diff --git a/tests/lib/math/rectangle_test.dart b/tests/lib/math/rectangle_test.dart
new file mode 100644
index 0000000..f6b5ed2
--- /dev/null
+++ b/tests/lib/math/rectangle_test.dart
@@ -0,0 +1,288 @@
+// Copyright (c) 2013, 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.
+
+import 'dart:math';
+import 'package:expect/expect.dart';
+
+main() {
+ testConstruction();
+ testIntersection();
+ testIntersects();
+ testBoundingBox();
+ testContainsRectangle();
+ testContainsPoint();
+ testHashCode();
+ testEdgeCases();
+ testEquality();
+ testNegativeLengths();
+ testNaNLeft();
+ testNaNTop();
+ testNaNWidth();
+ testNaNHeight();
+}
+
+Rectangle? createRectangle(List<num>? a) {
+ return a != null ? new Rectangle(a[0], a[1], a[2] - a[0], a[3] - a[1]) : null;
+}
+
+testConstruction() {
+ var r0 = new Rectangle(10, 20, 30, 40);
+ Expect.equals('Rectangle (10, 20) 30 x 40', r0.toString());
+ Expect.equals(40, r0.right);
+ Expect.equals(60, r0.bottom);
+
+ var r1 = new Rectangle.fromPoints(r0.topLeft, r0.bottomRight);
+ Expect.equals(r0, r1);
+
+ var r2 = new Rectangle.fromPoints(r0.bottomRight, r0.topLeft);
+ Expect.equals(r0, r2);
+}
+
+testIntersection() {
+ var tests = <List<List<num>?>>[
+ [
+ [10, 10, 20, 20],
+ [15, 15, 25, 25],
+ [15, 15, 20, 20]
+ ],
+ [
+ [10, 10, 20, 20],
+ [20, 0, 30, 10],
+ [20, 10, 20, 10]
+ ],
+ [
+ [0, 0, 1, 1],
+ [10, 11, 12, 13],
+ null
+ ],
+ [
+ [11, 12, 98, 99],
+ [22, 23, 34, 35],
+ [22, 23, 34, 35]
+ ]
+ ];
+
+ for (var test in tests) {
+ var r0 = createRectangle(test[0]);
+ var r1 = createRectangle(test[1]);
+ var expected = createRectangle(test[2]);
+
+ Expect.equals(expected, r0.intersection(r1));
+ Expect.equals(expected, r1.intersection(r0));
+ }
+}
+
+testIntersects() {
+ var r0 = new Rectangle(10, 10, 20, 20);
+ var r1 = new Rectangle(15, 15, 25, 25);
+ var r2 = new Rectangle(0, 0, 1, 1);
+
+ Expect.isTrue(r0.intersects(r1));
+ Expect.isTrue(r1.intersects(r0));
+
+ Expect.isFalse(r0.intersects(r2));
+ Expect.isFalse(r2.intersects(r0));
+}
+
+testBoundingBox() {
+ var tests = [
+ [
+ [10, 10, 20, 20],
+ [15, 15, 25, 25],
+ [10, 10, 25, 25]
+ ],
+ [
+ [10, 10, 20, 20],
+ [20, 0, 30, 10],
+ [10, 0, 30, 20]
+ ],
+ [
+ [0, 0, 1, 1],
+ [10, 11, 12, 13],
+ [0, 0, 12, 13]
+ ],
+ [
+ [11, 12, 98, 99],
+ [22, 23, 34, 35],
+ [11, 12, 98, 99]
+ ]
+ ];
+
+ for (var test in tests) {
+ var r0 = createRectangle(test[0]);
+ var r1 = createRectangle(test[1]);
+ var expected = createRectangle(test[2]);
+
+ Expect.equals(expected, r0.boundingBox(r1));
+ Expect.equals(expected, r1.boundingBox(r0));
+ }
+}
+
+testContainsRectangle() {
+ var r = new Rectangle(-10, 0, 20, 10);
+ Expect.isTrue(r.containsRectangle(r));
+
+ Expect.isFalse(r.containsRectangle(
+ new Rectangle(double.nan, double.nan, double.nan, double.nan)));
+
+ var r2 = new Rectangle(0, 2, 5, 5);
+ Expect.isTrue(r.containsRectangle(r2));
+ Expect.isFalse(r2.containsRectangle(r));
+
+ r2 = new Rectangle(-11, 2, 5, 5);
+ Expect.isFalse(r.containsRectangle(r2));
+ r2 = new Rectangle(0, 2, 15, 5);
+ Expect.isFalse(r.containsRectangle(r2));
+ r2 = new Rectangle(0, 2, 5, 10);
+ Expect.isFalse(r.containsRectangle(r2));
+ r2 = new Rectangle(0, 0, 5, 10);
+ Expect.isTrue(r.containsRectangle(r2));
+}
+
+testContainsPoint() {
+ var r = new Rectangle(20, 40, 60, 80);
+
+ // Test middle.
+ Expect.isTrue(r.containsPoint(new Point(50, 80)));
+
+ // Test edges.
+ Expect.isTrue(r.containsPoint(new Point(20, 40)));
+ Expect.isTrue(r.containsPoint(new Point(50, 40)));
+ Expect.isTrue(r.containsPoint(new Point(80, 40)));
+ Expect.isTrue(r.containsPoint(new Point(80, 80)));
+ Expect.isTrue(r.containsPoint(new Point(80, 120)));
+ Expect.isTrue(r.containsPoint(new Point(50, 120)));
+ Expect.isTrue(r.containsPoint(new Point(20, 120)));
+ Expect.isTrue(r.containsPoint(new Point(20, 80)));
+
+ // Test outside.
+ Expect.isFalse(r.containsPoint(new Point(0, 0)));
+ Expect.isFalse(r.containsPoint(new Point(50, 0)));
+ Expect.isFalse(r.containsPoint(new Point(100, 0)));
+ Expect.isFalse(r.containsPoint(new Point(100, 80)));
+ Expect.isFalse(r.containsPoint(new Point(100, 160)));
+ Expect.isFalse(r.containsPoint(new Point(50, 160)));
+ Expect.isFalse(r.containsPoint(new Point(0, 160)));
+ Expect.isFalse(r.containsPoint(new Point(0, 80)));
+}
+
+testHashCode() {
+ var a = new Rectangle(0, 1, 2, 3);
+ var b = new Rectangle(0, 1, 2, 3);
+ Expect.equals(b.hashCode, a.hashCode);
+
+ var c = new Rectangle(1, 0, 2, 3);
+ Expect.isFalse(a.hashCode == c.hashCode);
+}
+
+testEdgeCases() {
+ edgeTest(double a, double l) {
+ var r = new Rectangle(a, a, l, l);
+ Expect.equals(r, r.boundingBox(r));
+ Expect.equals(r, r.intersection(r));
+ }
+
+ var bignum1 = 0x20000000000000 + 0.0;
+ var bignum2 = 0x20000000000002 + 0.0;
+ var bignum3 = 0x20000000000004 + 0.0;
+ edgeTest(1.0, bignum1);
+ edgeTest(1.0, bignum2);
+ edgeTest(1.0, bignum3);
+ edgeTest(bignum1, 1.0);
+ edgeTest(bignum2, 1.0);
+ edgeTest(bignum3, 1.0);
+}
+
+testEquality() {
+ var bignum = 0x80000000000008 + 0.0;
+ var r1 = new Rectangle(bignum, bignum, 1.0, 1.0);
+ var r2 = new Rectangle(bignum, bignum, 2.0, 2.0);
+ Expect.equals(r2, r1);
+ Expect.equals(r2.hashCode, r1.hashCode);
+ Expect.equals(r2.right, r1.right);
+ Expect.equals(r2.bottom, r1.bottom);
+ Expect.equals(1.0, r1.width);
+ Expect.equals(2.0, r2.width);
+}
+
+testNegativeLengths() {
+ // Constructor allows negative lengths, but clamps them to zero.
+ Expect.equals(new Rectangle(4, 4, 0, 0), new Rectangle(4, 4, -2, -2));
+ Expect.equals(new Rectangle(4, 4, 0, 0), new MutableRectangle(4, 4, -2, -2));
+
+ // Setters clamp negative lengths to zero.
+ var mutable = new MutableRectangle(0, 0, 1, 1);
+ mutable.width = -1;
+ mutable.height = -1;
+ Expect.equals(new Rectangle(0, 0, 0, 0), mutable);
+
+ // Test that doubles are clamped to double zero.
+ var rectangle = new Rectangle(1.5, 1.5, -2.5, -2.5);
+ Expect.isTrue(identical(rectangle.width, 0.0));
+ Expect.isTrue(identical(rectangle.height, 0.0));
+}
+
+testNaNLeft() {
+ var rectangles = [
+ const Rectangle(double.nan, 1, 2, 3),
+ new MutableRectangle(double.nan, 1, 2, 3),
+ new Rectangle.fromPoints(new Point(double.nan, 1), new Point(2, 4)),
+ new MutableRectangle.fromPoints(new Point(double.nan, 1), new Point(2, 4)),
+ ];
+ for (var r in rectangles) {
+ Expect.isFalse(r.containsPoint(new Point(0, 1)));
+ Expect.isFalse(r.containsRectangle(new Rectangle(0, 1, 2, 3)));
+ Expect.isFalse(r.intersects(new Rectangle(0, 1, 2, 3)));
+ Expect.isTrue(r.left.isNaN);
+ Expect.isTrue(r.right.isNaN);
+ }
+}
+
+testNaNTop() {
+ var rectangles = [
+ const Rectangle(0, double.nan, 2, 3),
+ new MutableRectangle(0, double.nan, 2, 3),
+ new Rectangle.fromPoints(new Point(0, double.nan), new Point(2, 4)),
+ new MutableRectangle.fromPoints(new Point(0, double.nan), new Point(2, 4)),
+ ];
+ for (var r in rectangles) {
+ Expect.isFalse(r.containsPoint(new Point(0, 1)));
+ Expect.isFalse(r.containsRectangle(new Rectangle(0, 1, 2, 3)));
+ Expect.isFalse(r.intersects(new Rectangle(0, 1, 2, 3)));
+ Expect.isTrue(r.top.isNaN);
+ Expect.isTrue(r.bottom.isNaN);
+ }
+}
+
+testNaNWidth() {
+ var rectangles = [
+ const Rectangle(0, 1, double.nan, 3),
+ new MutableRectangle(0, 1, double.nan, 3),
+ new Rectangle.fromPoints(new Point(0, 1), new Point(double.nan, 4)),
+ new MutableRectangle.fromPoints(new Point(0, 1), new Point(double.nan, 4)),
+ ];
+ for (var r in rectangles) {
+ Expect.isFalse(r.containsPoint(new Point(0, 1)));
+ Expect.isFalse(r.containsRectangle(new Rectangle(0, 1, 2, 3)));
+ Expect.isFalse(r.intersects(new Rectangle(0, 1, 2, 3)));
+ Expect.isTrue(r.right.isNaN);
+ Expect.isTrue(r.width.isNaN);
+ }
+}
+
+testNaNHeight() {
+ var rectangles = [
+ const Rectangle(0, 1, 2, double.nan),
+ new MutableRectangle(0, 1, 2, double.nan),
+ new Rectangle.fromPoints(new Point(0, 1), new Point(2, double.nan)),
+ new MutableRectangle.fromPoints(new Point(0, 1), new Point(2, double.nan)),
+ ];
+ for (var r in rectangles) {
+ Expect.isFalse(r.containsPoint(new Point(0, 1)));
+ Expect.isFalse(r.containsRectangle(new Rectangle(0, 1, 2, 3)));
+ Expect.isFalse(r.intersects(new Rectangle(0, 1, 2, 3)));
+ Expect.isTrue(r.bottom.isNaN);
+ Expect.isTrue(r.height.isNaN);
+ }
+}
diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status
index aba92ff..864f1a9 100644
--- a/tests/lib_2/lib_2_vm.status
+++ b/tests/lib_2/lib_2_vm.status
@@ -8,15 +8,6 @@
[ $arch == arm64 && $runtime == vm ]
mirrors/immutable_collections_test: Pass, Slow # http://dartbug.com/33057
-[ $arch == ia32 && $mode == debug && $runtime == vm && $system == windows ]
-convert/streamed_conversion_json_utf8_decode_test: Skip # Verification OOM.
-
-[ $arch != ia32 && $arch != simarm && $arch != simarmv6 && $arch != x64 && $mode == debug && $runtime == vm ]
-convert/streamed_conversion_json_utf8_decode_test: Skip # Verification not yet implemented.
-
-[ $arch == simarm64 && $runtime == vm ]
-convert/utf85_test: Skip # Pass, Slow Issue 20111.
-
[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm ]
async/future_or_only_in_async_test/00: MissingCompileTimeError
convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Infrequent timeouts.
@@ -79,8 +70,7 @@
mirrors/library_uri_io_test: RuntimeError
mirrors/library_uri_package_test: RuntimeError
-[ $runtime == vm && ($arch == simarm || $arch == simarmv6) ]
-convert/utf85_test: Skip # Pass, Slow Issue 12644.
-
-[ $arch == simarmv6 || $arch == simarm && $runtime == vm ]
-convert/chunked_conversion_utf88_test: Skip # Pass, Slow Issue 12644.
+[ $arch == simarm || $arch == simarm64 || $hot_reload || $hot_reload_rollback ]
+convert/chunked_conversion_utf88_test: SkipSlow
+convert/streamed_conversion_json_utf8_decode_test: SkipSlow
+convert/utf85_test: SkipSlow
diff --git a/tests/standalone/array_bounds_check_generalization_test.dart b/tests/standalone/array_bounds_check_generalization_test.dart
new file mode 100644
index 0000000..96b5946
--- /dev/null
+++ b/tests/standalone/array_bounds_check_generalization_test.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2012, 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.
+//
+// We are using --complete-timeline below to ensure that we get timeline events
+// generated during all phases of compilation and deoptimization.
+// VMOptions=--optimization_counter_threshold=10 --no-use-osr --complete-timeline --no-background_compilation
+
+import "package:expect/expect.dart";
+
+test1(a, start, step, N) {
+ var e;
+ for (var i = 0; i < N; i++) {
+ e = a[start + i * step];
+ }
+ return e;
+}
+
+test2(a, b) {
+ var e;
+ for (var i = 0, j = 0, k = 0; i < a.length; i++, j++, k++) {
+ e = b[k] = a[j];
+ }
+ return e;
+}
+
+test3(a, b) {
+ var e;
+ for (var i = 0, j = 1, k = 0; i < a.length - 1; i++, j++, k++) {
+ e = b[k] = a[j - 1];
+ }
+ return e;
+}
+
+test4(a, b) {
+ var e;
+ if (a.length < 2) {
+ return null;
+ }
+
+ for (var i = 0, j = 1, k = 0; i < a.length - 1; i++, j++, k++) {
+ e = b[k] = a[j - 1];
+ }
+ return e;
+}
+
+test5(a, b, k0) {
+ var e;
+ if (a.length < 2) {
+ return null;
+ }
+
+ if (k0 > 1) {
+ return null;
+ }
+
+ for (var i = 0, j = 1, k = 0; i < a.length - 1; i++, j++, k++) {
+ e = b[k - k0] = a[j - 1];
+ }
+ return e;
+}
+
+test6(List<int> a, int M, int N) {
+ var e = 0;
+ for (var i = 0; i < N; i++) {
+ for (var j = 0; j < M; j++) {
+ e += a[i * M + j];
+ }
+ }
+ return e;
+}
+
+main() {
+ var a = const [0, 1, 2, 3, 4, 5, 6, 7];
+ var b = new List(a.length);
+ for (var i = 0; i < 10000; i++) {
+ Expect.equals(a.last, test1(a, 0, 1, a.length));
+ Expect.equals(a.last, test2(a, b));
+ Expect.equals(a[a.length - 2], test3(a, b));
+ Expect.equals(a[a.length - 2], test4(a, b));
+ Expect.equals(a[a.length - 2], test5(a, b, 0));
+ Expect.equals(6, test6(a, 2, 2));
+ }
+
+ test1(a, 0, 2, a.length ~/ 2);
+ Expect.throws(() => test1(a, 1, 1, a.length));
+ Expect.throws(() => test2(a, new List(a.length - 1)));
+ Expect.throws(() => test6(a, 4, 3));
+}
diff --git a/tests/standalone/assert_assignable_canon_test.dart b/tests/standalone/assert_assignable_canon_test.dart
new file mode 100644
index 0000000..f32f5c8
--- /dev/null
+++ b/tests/standalone/assert_assignable_canon_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2016, 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.
+//
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+
+abstract class A<T extends A<T>> {
+ @pragma('vm:prefer-inline')
+ f(x) => new R<T>(x);
+}
+
+class B extends A<B> {}
+
+class R<T> {
+ @pragma('vm:prefer-inline')
+ R(T field);
+}
+
+class C extends B {}
+
+class D extends C {}
+
+// f will be inlined and T=B will be forwarded to AssertAssignable in the
+// R. However B will be wrapped in the TypeRef which breaks runtime TypeCheck
+// function (Instance::IsInstanceOf does not work for TypeRefs).
+@pragma('vm:never-inline')
+f(o) => new B().f(o);
+
+main() {
+ final o = new D();
+ for (var i = 0; i < 10; i++) {
+ f(o);
+ }
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
new file mode 100644
index 0000000..2518819
--- /dev/null
+++ b/tests/standalone/standalone.status
@@ -0,0 +1,100 @@
+# Copyright (c) 2017, 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.
+# WARNING:
+# Tests using the multitest feature where failure is expected should *also* be
+# listed in tests/lib/analyzer/analyze_tests.status without the "standalone"
+# prefix.
+io/http_linklocal_ipv6_test: SkipByDesign # This needs manual test.
+io/non_utf8_directory_test: Skip # Issue 33519. Temp files causing bots to go purple.
+io/non_utf8_file_test: Skip # Issue 33519. Temp files causing bots to go purple.
+io/non_utf8_link_test: Skip # Issue 33519. Temp files causing bots to go purple.
+packages_file_test: Skip # Issue 26715
+packages_file_test/none: Skip # contains no tests.
+
+[ $builder_tag == asan ]
+io/process_detached_test: Slow
+
+[ $builder_tag == no_ipv6 ]
+io/http_ipv6_test: SkipByDesign
+io/http_loopback_test: SkipByDesign
+io/http_proxy_advanced_test: SkipByDesign
+io/socket_bind_test: SkipByDesign
+io/socket_info_ipv6_test: SkipByDesign
+io/socket_ipv6_test: SkipByDesign
+io/socket_source_address_test: SkipByDesign
+
+[ $compiler == dart2analyzer ]
+deferred_transitive_import_error_test: Skip
+
+[ $compiler == dartkp ]
+causal_async_stack_test: Skip # Flaky.
+
+[ $mode == product ]
+dart_developer_env_test: SkipByDesign
+io/stdio_implicit_close_test: Skip # SkipByDesign
+no_profiler_test: SkipByDesign
+no_support_coverage_test: SkipByDesign
+no_support_debugger_test: SkipByDesign
+no_support_disassembler_test: SkipByDesign
+no_support_il_printer_test: SkipByDesign
+no_support_service_test: SkipByDesign
+no_support_timeline_test: SkipByDesign
+verbose_gc_to_bmu_test: SkipByDesign # No verbose_gc in product mode
+
+[ $runtime == dart_precompiled ]
+http_launch_test: Skip
+io/addlatexhash_test: Skip
+io/wait_for_event_isolate_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_microtask_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_nested_microtask_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_nested_timer_microtask_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_nested_timer_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_nested_waits_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_timer_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_zone_caught_error_test: SkipByDesign # Uses mirrors.
+io/wait_for_event_zone_test: SkipByDesign # Uses mirrors.
+io/wait_for_test: SkipByDesign # Uses mirrors.
+verbose_gc_to_bmu_test: Skip # Attempts to spawn dart using Platform.executable
+
+[ $builder_tag == swarming && $system == macos ]
+io/*: Skip # Issue 30618
+
+[ $compiler == none && $runtime == vm && $system == fuchsia ]
+*: Skip # Not yet triaged.
+
+[ $compiler != none && $runtime != dart_precompiled && $runtime != vm ]
+env_test: Skip # This is testing a vm command line parsing scenario.
+
+[ $mode == product && $runtime == dart_precompiled ]
+dwarf_stack_trace_test: SkipByDesign # Due to instruction canonicalization we can end up having the wrong names in stack traces.
+
+[ $runtime == vm && $system == linux ]
+io/http_basic_test: Slow # Issue 28046, These tests might be slow on an opt counter threshold bot. They also time out on the bot occasionally => flaky test issue 28046
+io/http_launch_test: Slow # Issue 28046, These tests might be slow on an opt counter threshold bot. They also time out on the bot occasionally => flaky test issue 28046
+
+[ $system == macos && ($runtime == dart_precompiled || $runtime == vm) ]
+io/raw_secure_server_socket_test: Crash
+io/raw_server_socket_cancel_test: Skip # Issue 28182 # This test sometimes hangs on Mac.
+io/secure_server_client_certificate_test: Skip # Re-enable once the bots have been updated. Issue #26057
+io/socket_many_connections_test: Skip # This test fails with "Too many open files" on the Mac OS buildbot. This is expected as MacOS by default runs with a very low number of allowed open files ('ulimit -n' says something like 256).
+
+[ $arch == arm || $arch == arm64 || $runtime != vm || $system == android ]
+fragmentation_test: SkipSlow
+fragmentation_typed_data_test: SkipSlow
+
+[ $compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk ]
+*: SkipByDesign
+
+[ $mode == product || $runtime == dart_precompiled ]
+no_assert_test: SkipByDesign
+
+[ $runtime == dart_precompiled || $runtime == vm ]
+deferred_transitive_import_error_test: Skip
+
+[ $hot_reload || $hot_reload_rollback ]
+io/addlatexhash_test: Crash # Issue 31252
+io/many_directory_operations_test: SkipSlow
+io/many_file_operations_test: SkipSlow
+package/*: SkipByDesign # Launches VMs in interesting ways.
+typed_data_isolate_test: SkipSlow
diff --git a/tests/standalone/standalone_analyzer.status b/tests/standalone/standalone_analyzer.status
new file mode 100644
index 0000000..170e2de
--- /dev/null
+++ b/tests/standalone/standalone_analyzer.status
@@ -0,0 +1,6 @@
+# Copyright (c) 2017, 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.
+
+[ $compiler == dart2analyzer ]
+deferred_transitive_import_error_test: Skip # Contains intentional errors.
diff --git a/tests/standalone/standalone_kernel.status b/tests/standalone/standalone_kernel.status
new file mode 100644
index 0000000..b967e9f
--- /dev/null
+++ b/tests/standalone/standalone_kernel.status
@@ -0,0 +1,111 @@
+# Copyright (c) 2017, 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.
+# Sections in this file should contain "$compiler == dartk" or
+# "$compiler == dartkp".
+
+fragmentation_test: Pass, Slow # GC heavy
+fragmentation_typed_data_test: Pass, Slow # GC heavy
+io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
+
+[ $compiler == dartkb ]
+no_lazy_dispatchers_test: SkipByDesign # KBC interpreter doesn't support --no_lazy_dispatchers
+
+[ $system == android ]
+entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
+
+[ $arch == ia32 && $builder_tag == optimization_counter_threshold ]
+io/file_lock_test: SkipSlow # Timeout
+
+[ $arch == simarm64 && ($compiler == dartk || $compiler == dartkb) ]
+io/http_bind_test: Slow
+
+[ $builder_tag == optimization_counter_threshold && ($compiler == dartk || $compiler == dartkb) ]
+map_insert_remove_oom_test: Skip # Heap limit too low.
+
+[ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
+io/raw_socket_test: Crash
+io/socket_exception_test: Crash
+io/socket_finalizer_test: Crash
+io/socket_info_ipv4_test: Crash
+io/socket_info_ipv6_test: Crash
+io/socket_port_test: Crash
+
+[ $compiler == dartkp && $runtime == dart_precompiled ]
+io/compile_all_test: Skip # We do not support --compile-all for precompilation
+io/http_client_connect_test: Skip # Flaky.
+io/http_content_length_test: Skip # Flaky.
+io/http_proxy_advanced_test: Skip # Flaky
+io/http_proxy_test: Skip # Flaky.
+io/http_response_deadline_test: Skip # Flaky.
+io/http_reuse_server_port_test: Skip # Flaky.
+io/http_server_close_response_after_error_test: Skip # Flaky.
+io/http_shutdown_test: Skip # Flaky.
+io/https_client_certificate_test: Crash
+io/platform_test: Crash
+io/raw_datagram_socket_test: Skip # Flaky.
+io/raw_secure_server_closing_test: Skip # Flaky
+io/raw_socket_test: Crash
+io/secure_multiple_client_server_test: Skip # Flaky.
+io/secure_server_closing_test: Skip # Flaky.
+io/secure_server_socket_test: Skip # Flaky.
+io/secure_socket_renegotiate_test: Crash
+io/socket_many_connections_test: Skip # Flaky
+io/web_socket_error_test: Skip # Flaky
+io/web_socket_ping_test: Skip # Flaky.
+io/web_socket_test: Skip # Flaky.
+map_insert_remove_oom_test: Skip # Heap limit too low.
+no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
+
+[ $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+io/file_lock_test: Slow
+io/raw_socket_test: Crash
+io/socket_exception_test: Crash
+io/socket_finalizer_test: Crash
+io/socket_info_ipv4_test: Crash
+io/socket_info_ipv6_test: Crash
+io/socket_port_test: Crash
+
+[ $mode == debug && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
+io/web_socket_ping_test: Crash
+
+[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
+
+[ $system == windows && ($compiler == dartk || $compiler == dartkb) ]
+io/dart_std_io_pipe_test: Slow
+io/secure_builtin_roots_test: Skip # Issues 32137 and 32138.
+io/wait_for_event_isolate_test: Skip # Issues 32137 and 32138.
+map_insert_remove_oom_test: Skip # Heap limit too low.
+
+[ $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
+io/http_no_reason_phrase_test: Crash
+io/http_outgoing_size_test: Crash
+
+[ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
+io/directory_chdir_test: Skip # Timeout
+io/echo_server_stream_test: Slow
+
+# Enabling of dartk for sim{arm,arm64} revealed these test failures, which
+# are to be triaged. Isolate tests are skipped on purpose due to the usage of
+# batch mode.
+[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
+io/file_blocking_lock_test: Crash # Please triage.
+io/file_lock_test: Slow
+map_insert_remove_oom_test: Skip # Heap limit too low.
+
+[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
+io/addlatexhash_test: Skip # Timeout
+io/http_advanced_test: Skip # Timeout
+io/http_auth_digest_test: Crash
+io/http_auth_test: Skip # Timeout
+io/http_proxy_advanced_test: Skip # Timeout
+io/http_read_test: Skip # Timeout
+io/pipe_server_test: Skip # Timeout
+io/socket_close_test: Skip # Timeout
+io/socket_many_connections_test: Skip # Timeout
+io/web_socket_compression_test: Skip # Timeout
+io/web_socket_test: Skip # Timeout
+
+[ $compiler != dartk && $compiler != dartkb && $compiler != dartkp || $compiler == dartkp && $system == windows ]
+entrypoints_verification_test: SkipByDesign # Requires VM to run. Cannot run in precompiled Windows because the DLL is linked against dart.exe instead of dart_precompiled_runtime.exe.
diff --git a/tests/standalone/standalone_precompiled.status b/tests/standalone/standalone_precompiled.status
new file mode 100644
index 0000000..672a30e
--- /dev/null
+++ b/tests/standalone/standalone_precompiled.status
@@ -0,0 +1,68 @@
+# Copyright (c) 2017, 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.
+
+[ $builder_tag == obfuscated ]
+dwarf_stack_trace_test: Pass, RuntimeError # Issue 35563
+
+[ $runtime == dart_precompiled ]
+http_launch_test: Skip
+io/addlatexhash_test: Skip
+io/dart_std_io_pipe_test: Skip
+io/directory_list_sync_test: Timeout, Skip # Expects to find the test directory relative to the script.
+io/file_blocking_lock_test: Skip
+io/file_lock_test: Skip
+io/file_read_special_device_test: Skip
+io/http_client_stays_alive_test: Skip
+io/http_response_deadline_test: Skip
+io/http_server_close_response_after_error_test: Skip
+io/https_unauthorized_test: Skip
+io/named_pipe_script_test: Skip
+io/namespace_test: Skip # Issue 33168
+io/platform_resolved_executable_test: Skip
+io/platform_test: RuntimeError # Expects to be running from 'dart' instead of 'dart_precompiled_runtime'
+io/print_sync_test: Skip
+io/process_check_arguments_test: Skip
+io/process_detached_test: Skip
+io/process_environment_test: Skip
+io/process_inherit_stdio_test: Skip
+io/process_non_ascii_test: Skip
+io/process_run_output_test: Skip
+io/process_set_exit_code_test: Skip
+io/process_shell_test: Skip
+io/process_stderr_test: Skip
+io/process_stdin_transform_unsubscribe_test: Skip
+io/process_stdout_test: Skip
+io/process_sync_test: Skip
+io/raw_datagram_socket_test: Skip
+io/regress_7191_test: Skip
+io/regress_7679_test: Skip
+io/secure_unauthorized_test: Skip
+io/signals_test: Skip
+io/stdin_sync_test: Skip
+io/stdio_implicit_close_test: Skip
+io/stdio_nonblocking_test: Skip
+io/test_extension_fail_test: Skip
+io/test_extension_test: Skip
+io/windows_environment_test: Skip
+package/scenarios/empty_packages_file/empty_packages_file_noimports_test: Skip
+package/scenarios/invalid/invalid_utf8_test: Skip
+package/scenarios/invalid/non_existent_packages_file_test: Skip
+package/scenarios/invalid/same_package_twice_test: Skip
+package/scenarios/packages_file_strange_formatting/empty_lines_test: Skip
+package/scenarios/packages_file_strange_formatting/mixed_line_ends_test: Skip
+package/scenarios/packages_option_only/packages_option_only_noimports_test: Skip
+package/scenarios/packages_option_only/packages_option_only_test: Skip
+
+[ $arch == arm && $mode == release && $runtime == dart_precompiled && $system == android ]
+io/socket_cancel_connect_test: RuntimeError # Issue 34142
+io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 28426
+
+[ $mode == product && $runtime == dart_precompiled ]
+dwarf_stack_trace_test: Pass, RuntimeError # Results will flake due to identical code folding
+
+[ $runtime == dart_precompiled && $checked ]
+io/namespace_test: RuntimeError
+
+[ $mode == product || $runtime == dart_precompiled ]
+no_assert_test: SkipByDesign # Requires checked mode.
diff --git a/tests/standalone/standalone_vm.status b/tests/standalone/standalone_vm.status
new file mode 100644
index 0000000..93e314f
--- /dev/null
+++ b/tests/standalone/standalone_vm.status
@@ -0,0 +1,79 @@
+# Copyright (c) 2017, 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.
+
+[ $arch == ia32 ]
+link_natives_lazily_test: SkipByDesign # Not supported.
+no_allow_absolute_addresses_test: SkipByDesign # Not supported.
+
+[ $system == android ]
+io/file_stat_test: Skip # Issue 26376
+io/file_system_watcher_test: Skip # Issue 26376
+io/file_test: Skip # Issue 26376
+io/http_proxy_advanced_test: Skip # Issue 27638
+io/http_proxy_test: Skip # Issue 27638
+io/https_bad_certificate_test: Skip # Issue 27638
+io/https_server_test: Skip # Issue 27638
+io/non_utf8_output_test: Skip # The Android command runner doesn't correctly handle non-UTF8 formatted output. https://github.com/dart-lang/sdk/issues/28872
+io/process_exit_test: Skip # Issue 29578
+io/process_path_environment_test: Skip # Issue 26376
+io/process_path_test: Skip # Issue 26376
+io/process_segfault_test: Skip # Issue 26376
+io/raw_datagram_socket_test: Skip # Issue 27638
+io/raw_secure_server_closing_test: Skip # Issue 27638
+io/raw_secure_server_socket_test: Skip # Issue 27638
+io/raw_secure_socket_pause_test: Skip # Issue 27638
+io/raw_secure_socket_test: Skip # Issue 27638
+io/regress_21160_test: Skip # Issue 27638
+io/resolve_symbolic_links_test: Skip # Issue 26376
+io/secure_bad_certificate_test: Skip # Issue 27638
+io/secure_client_raw_server_test: Skip # Issue 27638
+io/secure_client_server_test: Skip # Issue 27638
+io/secure_multiple_client_server_test: Skip # Issue 27638
+io/secure_server_client_certificate_test: Skip # Issue 27638
+io/secure_server_closing_test: Skip # Issue 27638
+io/secure_server_socket_test: Skip # Issue 27638
+io/secure_session_resume_test: Skip # Issue 27638
+io/secure_socket_alpn_test: Skip # Issue 27638
+io/secure_socket_test: Skip # Issue 27638
+io/socket_upgrade_to_secure_test: Skip # Issue 27638
+
+[ $system == windows ]
+io/process_sync_test: Pass, Timeout # Issue 24596
+io/sleep_test: Pass, Fail # Issue 25757
+io/socket_info_ipv6_test: Skip
+verbose_gc_to_bmu_test: Skip
+
+[ $arch == arm && $mode == release && $runtime == dart_precompiled && $system == android ]
+io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 28426
+
+[ $arch == x64 && $compiler == dartkb && $runtime == vm && $system == linux ]
+io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
+
+[ $arch == x64 && $mode == release && $runtime == vm && $system == linux ]
+io/http_bind_test: Pass, Timeout # Issue 35192
+
+[ $compiler != dart2analyzer && $system == windows ]
+io/platform_resolved_executable_test/06: RuntimeError # Issue 23641
+
+[ $mode == release && $runtime == vm && $system == macos ]
+io/http_server_close_response_after_error_test: Pass, Timeout # Issue 28370: timeout.
+io/named_pipe_script_test: Pass, RuntimeError # Issue 28737
+
+[ $mode == release && $runtime == vm && $system == windows ]
+io/http_server_close_response_after_error_test: Pass, Timeout # Issue 28370: timeout.
+
+[ $runtime == dart_precompiled && $system == linux && ($arch == simarm || $arch == simarm64 || $arch == x64) ]
+io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
+
+[ $runtime == vm && ($arch == arm || $arch == arm64) ]
+io/dart_std_io_pipe_test: Timeout, Pass
+io/file_input_stream_test: Skip # Issue 26109
+io/file_stream_test: Skip # Issue 26109
+io/file_typed_data_test: Skip # Issue 26109
+io/process_sync_test: Timeout, Pass
+
+[ $runtime == vm && ($arch == simarm || $arch == simarm64) ]
+io/dart_std_io_pipe_test: Timeout, Pass
+io/http_client_stays_alive_test: Skip # Spawns process in Dart2 mode.
+io/process_sync_test: Timeout, Pass
diff --git a/tests/standalone_2/io/http_cookie_date_test.dart b/tests/standalone_2/io/http_cookie_date_test.dart
index 621d9e5..6b94254 100644
--- a/tests/standalone_2/io/http_cookie_date_test.dart
+++ b/tests/standalone_2/io/http_cookie_date_test.dart
@@ -2,11 +2,14 @@
// 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.6
+
library dart._http;
import "dart:async";
import "dart:collection";
import "dart:convert";
+import "dart:developer";
import "dart:io";
import "dart:math";
import "dart:typed_data";
diff --git a/tests/standalone_2/io/http_headers_test.dart b/tests/standalone_2/io/http_headers_test.dart
index 3a2cbb3..ea53d8a 100644
--- a/tests/standalone_2/io/http_headers_test.dart
+++ b/tests/standalone_2/io/http_headers_test.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.6
+
library dart._http;
import "dart:async";
diff --git a/tests/standalone_2/io/http_override_test.dart b/tests/standalone_2/io/http_override_test.dart
index adcb2ab..25d4598 100644
--- a/tests/standalone_2/io/http_override_test.dart
+++ b/tests/standalone_2/io/http_override_test.dart
@@ -16,6 +16,7 @@
Duration connectionTimeout;
int maxConnectionsPerHost;
bool autoUncompress;
+ bool enableTimelineLogging;
Future<HttpClientRequest> open(
String method, String host, int port, String path) =>
@@ -55,6 +56,7 @@
Duration connectionTimeout;
int maxConnectionsPerHost;
bool autoUncompress;
+ bool enableTimelineLogging;
Future<HttpClientRequest> open(
String method, String host, int port, String path) =>
diff --git a/tests/standalone_2/io/http_parser_test.dart b/tests/standalone_2/io/http_parser_test.dart
index d82f355..06ed070 100644
--- a/tests/standalone_2/io/http_parser_test.dart
+++ b/tests/standalone_2/io/http_parser_test.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.6
+
library dart._http;
import "dart:async";
diff --git a/tests/standalone_2/io/process_exit_negative_test.dart b/tests/standalone_2/io/process_exit_negative_test.dart
deleted file mode 100644
index 645f7e6..0000000
--- a/tests/standalone_2/io/process_exit_negative_test.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012, 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.
-//
-// Process test program to test that compilation errors in the process
-// exit handler are reported correctly.
-
-import "dart:io";
-import "process_test_util.dart";
-
-void main() {
- var fp = Process.start(getProcessTestFileName(), const ["0", "0", "0", "0"]);
- fp.then((p) {
- p.exitCode.then((int s) {
- print(a.toString()); // Should cause a compilation error here.
- });
- // Drain stdout and stderr.
- p.stdout.listen((_) {});
- p.stderr.listen((_) {});
- });
-}
diff --git a/tests/standalone_2/io/web_socket_error_test.dart b/tests/standalone_2/io/web_socket_error_test.dart
index c757688..659ee7f 100644
--- a/tests/standalone_2/io/web_socket_error_test.dart
+++ b/tests/standalone_2/io/web_socket_error_test.dart
@@ -9,6 +9,8 @@
// OtherResources=certificates/server_chain.pem
// OtherResources=certificates/server_key.pem
+// @dart = 2.6
+
library dart._http;
import "dart:async";
diff --git a/tests/standalone_2/io/web_socket_ping_test.dart b/tests/standalone_2/io/web_socket_ping_test.dart
index 1ee03b5..3960958 100644
--- a/tests/standalone_2/io/web_socket_ping_test.dart
+++ b/tests/standalone_2/io/web_socket_ping_test.dart
@@ -7,6 +7,8 @@
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write
+// @dart = 2.6
+
library dart._http;
import "package:expect/expect.dart";
diff --git a/tests/standalone_2/io/web_socket_protocol_processor_test.dart b/tests/standalone_2/io/web_socket_protocol_processor_test.dart
index 75ac75a..fc50c61 100644
--- a/tests/standalone_2/io/web_socket_protocol_processor_test.dart
+++ b/tests/standalone_2/io/web_socket_protocol_processor_test.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.6
+
library dart._http;
import "package:async_helper/async_helper.dart";
diff --git a/tests/standalone_2/standalone_2_analyzer.status b/tests/standalone_2/standalone_2_analyzer.status
index fa699b4..170e2de 100644
--- a/tests/standalone_2/standalone_2_analyzer.status
+++ b/tests/standalone_2/standalone_2_analyzer.status
@@ -4,5 +4,3 @@
[ $compiler == dart2analyzer ]
deferred_transitive_import_error_test: Skip # Contains intentional errors.
-io/process_exit_negative_test: Skip
-
diff --git a/tools/VERSION b/tools/VERSION
index 200c0df..20a401d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
MAJOR 2
MINOR 7
PATCH 0
-PRERELEASE 1
+PRERELEASE 2
PRERELEASE_PATCH 0
-ABI_VERSION 23
+ABI_VERSION 24
OLDEST_SUPPORTED_ABI_VERSION 23
diff --git a/tools/bots/dart_sdk.py b/tools/bots/dart_sdk.py
index ac91988..a545a97 100755
--- a/tools/bots/dart_sdk.py
+++ b/tools/bots/dart_sdk.py
@@ -81,6 +81,11 @@
GuessExtension('gen_snapshot'))
CopyBetween(product_sdk_path, sdk_path, 'bin',
GuessExtension('dartaotruntime'))
+ shutil.copy2(
+ os.path.join(product_sdk_path, 'lib', '_internal',
+ 'vm_platform_strong.dill'),
+ os.path.join(sdk_path, 'lib', '_internal',
+ 'vm_platform_strong_product.dill'))
def DartArchiveUploadSDKs(system, arch, sdk_zip):
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index ea209ae..8854609 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -15,7 +15,9 @@
"third_party/pkg_tested/",
"tools/",
"out/ReleaseX64/dart-sdk/",
- "xcodebuild/ReleaseX64/dart-sdk/"
+ "out/ReleaseX64NNBD/dart-sdk/",
+ "xcodebuild/ReleaseX64/dart-sdk/",
+ "xcodebuild/ReleaseX64NNBD/dart-sdk/"
],
"dart2js": [
".packages",
@@ -29,6 +31,7 @@
"sdk/",
"tests/angular/",
"tests/co19_2/co19_2-analyzer.status",
+ "tests/co19_2/co19_2-co19.status",
"tests/co19_2/co19_2-dart2js.status",
"tests/co19_2/co19_2-dartdevc.status",
"tests/co19_2/co19_2-kernel.status",
@@ -66,6 +69,7 @@
"sdk_nnbd/",
"tests/angular/",
"tests/co19_2/co19_2-analyzer.status",
+ "tests/co19_2/co19_2-co19.status",
"tests/co19_2/co19_2-dart2js.status",
"tests/co19_2/co19_2-dartdevc.status",
"tests/co19_2/co19_2-kernel.status",
@@ -106,6 +110,7 @@
"sdk/",
"tests/angular/",
"tests/co19_2/co19_2-analyzer.status",
+ "tests/co19_2/co19_2-co19.status",
"tests/co19_2/co19_2-dart2js.status",
"tests/co19_2/co19_2-dartdevc.status",
"tests/co19_2/co19_2-kernel.status",
@@ -143,6 +148,7 @@
"sdk/",
"tests/angular/",
"tests/co19_2/co19_2-analyzer.status",
+ "tests/co19_2/co19_2-co19.status",
"tests/co19_2/co19_2-dart2js.status",
"tests/co19_2/co19_2-dartdevc.status",
"tests/co19_2/co19_2-kernel.status",
@@ -241,6 +247,7 @@
"third_party/observatory_pub_packages/packages/",
"tests/angular/",
"tests/co19_2/co19_2-analyzer.status",
+ "tests/co19_2/co19_2-co19.status",
"tests/co19_2/co19_2-dart2js.status",
"tests/co19_2/co19_2-dartdevc.status",
"tests/co19_2/co19_2-kernel.status",
@@ -528,7 +535,7 @@
"checked": true,
"use-sdk": true
}},
- "dartdevc-strong-linux-release-chrome": {
+ "dartdevk-strong-linux-release-chrome": {
"options": {
"checked": true,
"use-sdk": true,
@@ -536,7 +543,7 @@
"enable-asserts": true
}},
- "dartdevc-weak-linux-release-chrome": {
+ "dartdevk-weak-linux-release-chrome": {
"options": {
"checked": true,
"use-sdk": true,
@@ -555,6 +562,20 @@
"compiler": "dart2analyzer",
"enable-asserts": true,
"use-sdk": true
+ }},
+ "analyzer-asserts-strong-linux": {
+ "options": {
+ "compiler": "dart2analyzer",
+ "enable-asserts": true,
+ "use-sdk": true,
+ "enable-experiment": ["non-nullable"]
+ }},
+ "analyzer-asserts-weak-linux": {
+ "options": {
+ "compiler": "dart2analyzer",
+ "enable-asserts": true,
+ "use-sdk": true,
+ "enable-experiment": ["non-nullable"]
}}
},
"builder_configurations": [
@@ -1478,14 +1499,14 @@
{
"name": "ddc nnbd strong tests",
"arguments": [
- "-ndartdevc-strong-linux-release-chrome",
+ "-ndartdevk-strong-linux-release-chrome",
"dartdevc_native"
]
},
{
"name": "ddc nnbd weak tests",
"arguments": [
- "-ndartdevc-weak-linux-release-chrome",
+ "-ndartdevk-weak-linux-release-chrome",
"dartdevc_native"
]
}
@@ -1983,7 +2004,7 @@
"name": "build gen_snapshot and dartaotruntime",
"script": "tools/build.py",
"arguments": ["--arch=x64,arm,arm64", "--mode=product",
- "copy_gen_snapshot", "copy_dartaotruntime"]
+ "copy_gen_snapshot", "copy_dartaotruntime", "copy_vm_dill_files"]
},
{
"name": "upload sdk",
@@ -2033,7 +2054,7 @@
"name": "build gen_snapshot and dartaotruntime",
"script": "tools/build.py",
"arguments": ["--arch=x64", "--mode=product",
- "copy_gen_snapshot", "copy_dartaotruntime"]
+ "copy_gen_snapshot", "copy_dartaotruntime", "copy_vm_dill_files"]
},
{
"name": "upload sdk",
@@ -2070,7 +2091,7 @@
"name": "build gen_snapshot and dartaotruntime",
"script": "tools/build.py",
"arguments": ["--arch=x64", "--mode=product",
- "copy_gen_snapshot", "copy_dartaotruntime"]
+ "copy_gen_snapshot", "copy_dartaotruntime", "copy_vm_dill_files"]
},
{
"name": "upload sdk",
@@ -2189,6 +2210,33 @@
},
{
"builders": [
+ "analyzer-nnbd-linux-release"
+ ],
+ "meta": {
+ "description": "This configuration is used by the nnbd analyzer builder."
+ },
+ "steps": [
+ {
+ "name": "build dart",
+ "script": "tools/build.py",
+ "arguments": ["--nnbd", "create_sdk"]
+ },
+ {
+ "name": "analyze nnbd strong tests enable-asserts",
+ "arguments": [
+ "-nanalyzer-asserts-strong-${system}",
+ "language"]
+ },
+ {
+ "name": "analyze nnbd weak tests enable-asserts",
+ "arguments": [
+ "-nanalyzer-asserts-weak-${system}",
+ "language"]
+ }
+ ]
+ },
+ {
+ "builders": [
"analyzer-analysis-server-linux",
"analyzer-analysis-server-linux-analyzer-stable"
],
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index 82358dc..798f942 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -83,6 +83,9 @@
variance:
help: "Sound variance."
+nonfunction-type-aliases:
+ help: "Type aliases define a <type>, not just a <functionType>."
+
#
# Flags below this line are shipped, retired, or rejected, cannot be specified
# on the command line, and will eventually be removed.
diff --git a/tools/gn.py b/tools/gn.py
index 81da03d..1a9908c 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -247,6 +247,7 @@
gn_args['is_tsan'] = args.tsan
gn_args['is_ubsan'] = args.ubsan
gn_args['include_dart2native'] = True
+ gn_args['is_qemu'] = args.use_qemu
if not args.platform_sdk and not gn_args['target_cpu'].startswith('arm'):
gn_args['dart_platform_sdk'] = args.platform_sdk
@@ -522,6 +523,11 @@
default=False,
dest='use_crashpad',
action='store_true')
+ other_group.add_argument(
+ '--use-qemu',
+ default=False,
+ dest='use_qemu',
+ action='store_true')
options = parser.parse_args(args)
if not ProcessOptions(options):
diff --git a/tools/test.dart b/tools/test.dart
index 5a47fb3..f4cbd7b 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -440,7 +440,6 @@
final branches = (testMatrix["branches"] as List).cast<String>();
final buildersConfigurations =
testMatrix["builder_configurations"] as List<dynamic>;
-
// Determine what named configuration to run and which builders to download
// existing results from.
ResolvedConfigurations configurations = resolveNamedConfigurations(
@@ -455,7 +454,7 @@
exitCode = 1;
return;
}
-
+ // Print information about the resolved builders to compare with.
for (final builder in configurations.builders) {
if (localConfiguration != null) {
print("Testing the named configuration $localConfiguration "
@@ -467,27 +466,30 @@
"compared with builder $builder");
}
}
-
// Use given commit or find out where the current HEAD branched.
final commit = options["commit"] ??
await findMergeBase(options["remote"], options["branch"]);
print("Base commit is $commit");
-
// Store the downloaded results and our test results in a temporary directory.
final outDirectory = await Directory.systemTemp.createTemp("test.dart.");
try {
- final mergedResults = <String, Map<String, dynamic>>{};
- final mergedFlaky = <String, Map<String, dynamic>>{};
-
+ final tasks = <Future>[];
bool needsConfigurationOverride = localConfiguration != null &&
localConfiguration != namedConfigurations.single;
bool needsMerge = configurations.builders.length > 1;
-
- // Use the buildbucket API to search for builds of the right commit.
final inexactBuilds = <String, String>{};
+ var previousFileName = "previous.json";
+ var flakyFileName = "flaky.json";
+ var downloadNumber = 0;
+ // Download the previous results and flakiness info from cloud storage.
for (final builder in configurations.builders) {
- // Download the previous results and flakiness info from cloud storage.
+ if (needsMerge) {
+ previousFileName = "previous-$downloadNumber.json";
+ flakyFileName = "flaky-$downloadNumber.json";
+ downloadNumber++;
+ }
print("Finding build on builder $builder to compare with...");
+ // Use the buildbucket API to search for builds of the right commit.
final buildSearchResult =
await searchForApproximateBuild(builder, commit);
if (buildSearchResult.commit != commit) {
@@ -497,50 +499,19 @@
}
final buildNumber = buildSearchResult.build.toString();
print("Downloading results from builder $builder build $buildNumber...");
- await cpGsutil(buildFileCloudPath(builder, buildNumber, "results.json"),
- "${outDirectory.path}/previous.json");
+ tasks.add(cpGsutil(
+ buildFileCloudPath(builder, buildNumber, "results.json"),
+ "${outDirectory.path}/$previousFileName"));
if (!options["report-flakes"]) {
- await cpGsutil(buildFileCloudPath(builder, buildNumber, "flaky.json"),
- "${outDirectory.path}/flaky.json");
- }
- // Merge the results for the builders.
- if (needsMerge || needsConfigurationOverride) {
- var results =
- await loadResultsMap("${outDirectory.path}/previous.json");
- if (needsConfigurationOverride) {
- overrideConfiguration(
- results, namedConfigurations.single, localConfiguration);
- }
- mergedResults.addAll(results);
- if (!options["report-flakes"]) {
- var flakyTests =
- await loadResultsMap("${outDirectory.path}/flaky.json");
- if (needsConfigurationOverride) {
- overrideConfiguration(
- flakyTests, namedConfigurations.single, localConfiguration);
- }
- mergedFlaky.addAll(flakyTests);
- }
+ tasks.add(cpGsutil(
+ buildFileCloudPath(builder, buildNumber, "flaky.json"),
+ "${outDirectory.path}/$flakyFileName"));
}
}
-
- // Write out the merged results for the builders.
- if (needsMerge || needsConfigurationOverride) {
- await new File("${outDirectory.path}/previous.json").writeAsString(
- mergedResults.values.map((data) => jsonEncode(data) + "\n").join(""));
- }
-
- // Ensure that there is a flaky.json even if it wasn't downloaded.
- if (needsMerge || needsConfigurationOverride || options["report-flakes"]) {
- await new File("${outDirectory.path}/flaky.json").writeAsString(
- mergedFlaky.values.map((data) => jsonEncode(data) + "\n").join(""));
- }
-
+ // Run the tests.
final configurationsToRun = localConfiguration != null
? <String>[localConfiguration]
: namedConfigurations;
-
- // Run the tests.
print("".padLeft(80, "="));
print("Running tests");
print("".padLeft(80, "="));
@@ -557,11 +528,47 @@
...options.rest,
],
runInShell: Platform.isWindows);
-
+ // Wait for the downloads and the test run to complete.
+ await Future.wait(tasks);
+ // Merge the results and flaky data downloaded from the builders.
+ final mergedResults = <String, Map<String, dynamic>>{};
+ final mergedFlaky = <String, Map<String, dynamic>>{};
+ if (needsMerge || needsConfigurationOverride) {
+ for (int i = 0; i < downloadNumber; ++i) {
+ previousFileName = needsMerge ? "previous-$i.json" : "previous.json";
+ var results =
+ await loadResultsMap("${outDirectory.path}/$previousFileName");
+ if (needsConfigurationOverride) {
+ overrideConfiguration(
+ results, namedConfigurations.single, localConfiguration);
+ }
+ mergedResults.addAll(results);
+ if (!options["report-flakes"]) {
+ flakyFileName = needsMerge ? "flaky-$i.json" : "flaky.json";
+ var flakyTests =
+ await loadResultsMap("${outDirectory.path}/$flakyFileName");
+ if (needsConfigurationOverride) {
+ overrideConfiguration(
+ flakyTests, namedConfigurations.single, localConfiguration);
+ }
+ mergedFlaky.addAll(flakyTests);
+ }
+ }
+ }
+ // Deflake results of the tests if required.
if (options["deflake"]) {
await deflake(outDirectory, configurationsToRun, options.rest);
}
-
+ // Write out the merged results for the builders.
+ if (needsMerge || needsConfigurationOverride) {
+ await new File("${outDirectory.path}/previous.json").writeAsString(
+ mergedResults.values.map((data) => jsonEncode(data) + "\n").join(""));
+ }
+ // Ensure that there is a flaky.json even if it wasn't downloaded.
+ if (needsMerge || needsConfigurationOverride || options["report-flakes"]) {
+ await new File("${outDirectory.path}/flaky.json").writeAsString(
+ mergedFlaky.values.map((data) => jsonEncode(data) + "\n").join(""));
+ }
// Write out the final comparison.
print("".padLeft(80, "="));
print("Test Results");
diff --git a/utils/compiler/BUILD.gn b/utils/compiler/BUILD.gn
index 27dfc69..81893ed 100644
--- a/utils/compiler/BUILD.gn
+++ b/utils/compiler/BUILD.gn
@@ -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("../../sdk_args.gni")
import("../../utils/compile_platform.gni")
import("../application_snapshot.gni")
import("../create_timestamp.gni")
@@ -51,6 +52,12 @@
]
}
+if (use_nnbd) {
+ libraries_specification_path = "sdk_nnbd/lib/libraries.json"
+} else {
+ libraries_specification_path = "sdk/lib/libraries.json"
+}
+
application_snapshot("dart2js") {
deps = [
":compile_dart2js_platform",
@@ -64,7 +71,7 @@
main_dart = "$target_gen_dir/dart2js.dart"
training_args = [
"--packages=" + rebase_path("../../.packages"),
- "--libraries-spec=" + rebase_path("../../sdk/lib/libraries.json"),
+ "--libraries-spec=" + rebase_path("../../$libraries_specification_path"),
rebase_path("$target_gen_dir/dart2js.dart"),
]
}
@@ -72,7 +79,8 @@
compile_platform("compile_dart2js_platform") {
single_root_scheme = "org-dartlang-sdk"
single_root_base = rebase_path("../../")
- libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json"
+ libraries_specification_uri =
+ "org-dartlang-sdk:///$libraries_specification_path"
outputs = [
"$root_out_dir/dart2js_platform.dill",
@@ -87,7 +95,8 @@
compile_platform("compile_dart2js_server_platform") {
single_root_scheme = "org-dartlang-sdk"
single_root_base = rebase_path("../../")
- libraries_specification_uri = "org-dartlang-sdk:///sdk/lib/libraries.json"
+ libraries_specification_uri =
+ "org-dartlang-sdk:///$libraries_specification_path"
outputs = [
"$root_out_dir/dart2js_server_platform.dill",
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index 8b03d63..c861280 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -4,13 +4,23 @@
import("../../build/dart/dart_action.gni")
import("../../sdk_args.gni")
+import("../../utils/compile_platform.gni")
import("../application_snapshot.gni")
import("../create_timestamp.gni")
patched_sdk_dir = "$target_gen_dir/patched_sdk"
sdk_summary = "$target_gen_dir/ddc_sdk.sum"
-sdk_dill = "$target_gen_dir/kernel/ddc_sdk.dill"
-sdk_libraries_json = "$target_gen_dir/libraries.json"
+
+# TODO(sigmund): rename to ddc_outline.dill to be consistent with the naming
+# convention from other tools.
+sdk_outline_dill = "$root_out_dir/ddc_sdk.dill"
+sdk_full_dill = "$root_out_dir/ddc_platform.dill"
+
+if (use_nnbd) {
+ libraries_specification_path = "sdk_nnbd/lib/libraries.json"
+} else {
+ libraries_specification_path = "sdk/lib/libraries.json"
+}
application_snapshot("dartdevc") {
main_dart = "../../pkg/dev_compiler/bin/dartdevc.dart"
@@ -19,28 +29,43 @@
"--dart-sdk",
rebase_path("../../sdk"),
"--dart-sdk-summary",
- rebase_path(sdk_dill),
+ rebase_path(sdk_outline_dill),
"-k",
"-o",
"dartdevc.js",
- rebase_path("../../pkg/dev_compiler/bin/dartdevc.dart"),
]
+ if (use_nnbd) {
+ training_args += [
+ "--enable-experiment=non-nullable",
+
+ # TODO(sigmund): restore training with dartdevc.dart. Currently blocked by
+ # some regressions in type-promotion in the CFE when nnbd is enabled.
+ # The following test file is pretty simple and has no imports, so it
+ # should be easier to compile while we bootstrap NNBD.
+ rebase_path("../../tests/language_2/abstract_equal_test.dart"),
+ ]
+ } else {
+ training_args += [ rebase_path("../../pkg/dev_compiler/bin/dartdevc.dart") ]
+ }
+
deps = [
":dartdevc_kernel_sdk",
- ":dartdevc_kernel_sdk_outline",
+ ":dartdevc_platform",
]
inputs = [
- sdk_dill,
+ sdk_outline_dill,
]
}
# TODO(#38701) Cleanup after merging the forked SDK into mainline.
if (use_nnbd) {
sdk_root = "../../sdk_nnbd"
+ libraries_specification_path = "sdk_nnbd/lib/libraries.json"
} else {
sdk_root = "../../sdk"
+ libraries_specification_path = "sdk/lib/libraries.json"
}
sdk_lib_files = exec_script("../../tools/list_dart_files.py",
@@ -229,7 +254,8 @@
":dartdevc",
":dartdevc_kernel_sdk",
":dartdevc_sdk",
- ":dartdevc_test_pkg",
+ ":dartdevc_test_kernel_pkg",
+ ":dartdevc_test_legacy_pkg",
"../..:create_sdk",
]
}
@@ -241,7 +267,15 @@
deps = [
":dartdevc_kernel_sdk",
":dartdevc_sdk",
- ":dartdevc_test_pkg",
+ ":dartdevc_test_kernel_pkg",
+ ":dartdevc_test_legacy_pkg",
+ ]
+}
+
+group("dartdevc_test_kernel_local") {
+ deps = [
+ ":dartdevc_kernel_sdk",
+ ":dartdevc_test_kernel_pkg",
]
}
@@ -257,19 +291,14 @@
# Compiles the packages used by the tests to JS with dartdevc so that they are
# available for loading by the tests.
-prebuilt_dart_action("dartdevc_test_pkg") {
+prebuilt_dart_action("dartdevc_test_legacy_pkg") {
deps = [
":dartdevc_files_stamp",
- ":dartdevc_kernel_sdk",
- ":dartdevc_kernel_sdk_libraries_json",
- ":dartdevc_kernel_sdk_outline",
":dartdevc_sdk",
"../../pkg:pkg_files_stamp",
]
inputs = [
- sdk_dill,
- sdk_libraries_json,
sdk_summary,
"$target_gen_dir/dartdevc_files.stamp",
"$root_gen_dir/pkg_files.stamp",
@@ -297,28 +326,6 @@
# any of the above packages that are only here because unittest uses them.
"$target_gen_dir/pkg/unittest.js",
"$target_gen_dir/pkg/unittest.sum",
-
- "$target_gen_dir/pkg_kernel/async_helper.dill",
- "$target_gen_dir/pkg_kernel/async_helper.js",
- "$target_gen_dir/pkg_kernel/collection.dill",
- "$target_gen_dir/pkg_kernel/collection.js",
- "$target_gen_dir/pkg_kernel/expect.dill",
- "$target_gen_dir/pkg_kernel/expect.js",
- "$target_gen_dir/pkg_kernel/js.dill",
- "$target_gen_dir/pkg_kernel/js.js",
- "$target_gen_dir/pkg_kernel/matcher.dill",
- "$target_gen_dir/pkg_kernel/matcher.js",
- "$target_gen_dir/pkg_kernel/meta.dill",
- "$target_gen_dir/pkg_kernel/meta.js",
- "$target_gen_dir/pkg_kernel/path.dill",
- "$target_gen_dir/pkg_kernel/path.js",
- "$target_gen_dir/pkg_kernel/stack_trace.dill",
- "$target_gen_dir/pkg_kernel/stack_trace.js",
-
- # TODO(rnystrom): Remove this when unittest is no longer used. Also remove
- # any of the above packages that are only here because unittest uses them.
- "$target_gen_dir/pkg_kernel/unittest.dill",
- "$target_gen_dir/pkg_kernel/unittest.js",
]
script = "../../pkg/dev_compiler/tool/build_pkgs.dart"
@@ -326,8 +333,6 @@
args = [
"--analyzer-sdk",
rebase_path(sdk_summary),
- "--kernel-sdk",
- rebase_path(sdk_dill),
"--output",
rebase_path("$target_gen_dir"),
]
@@ -335,7 +340,11 @@
# TODO(38701): Cleanup after merging the forked SDK into mainline.
if (use_nnbd) {
args += [
- "--enable-experiment=non-nullable",
+ # TODO(sigmund): reenable. We turned this off temporarily while the
+ # migration of libraries is in flux, this step otherwise fails
+ # with many nnbd-related compile-time errors because the packages are
+ # assumed to be nnbd compilant.
+ # "--enable-experiment=non-nullable",
# TODO(rnystrom): Most of the packages used by tests can be cleanly
# compiled as opted-in libraries, but js.dart has an optional parameter
@@ -346,38 +355,172 @@
}
}
-prebuilt_dart_action("dartdevc_kernel_sdk_outline") {
+# Compiles to JavaScript any package used from tests.
+# TODO(sigmund): generate a js bundle or a module that load these indirectly so
+# we can stop referring to this list of packages explicitly in the test_runner.
+group("dartdevc_test_kernel_pkg") {
deps = [
- ":dartdevc_files_stamp",
- ":dartdevc_sdk_patch_stamp",
- "../../pkg:pkg_files_stamp",
+ ":async_helper_js",
+ ":collection_js",
+ ":expect_js",
+ ":js_js",
+ ":matcher_js",
+ ":meta_js",
+ ":path_js",
+ ":stack_trace_js",
+ ":unittest_js",
]
+}
- inputs = [
- "../../utils/bazel/kernel_worker.dart",
- "$target_gen_dir/dartdevc_files.stamp",
- "$root_gen_dir/pkg_files.stamp",
+template("dartdevc_kernel_compile") {
+ assert(defined(invoker.package),
+ "Need 'package' in $target_name (the name of the package)")
+
+ # Other optional invoker parameters:
+ # * extra_libraries: entrypoints to include in the module as
+ # "package:package_name/library_name.dart" (the rule implicitly adds
+ # the default import "package:package_name/package_name.dart").
+ # * package_dependencies: the name of other packages this package depends
+ # on. When providing `name`, a separate `dartdevc_kernel_compile` target
+ # named `${name}_js` must exist.
+ # * nnbd_disabled: whether to disable the non-nullable experiment under the
+ # NNBD build. This is used temporariy until we either migrate the packages
+ # or add support to read the language version information from the package
+ # itself.
+ # * args: additional args to pass to dartdevc
+
+ prebuilt_dart_action(target_name) {
+ script = "../../pkg/dev_compiler/bin/dartdevc.dart"
+ module = invoker.package
+ outdir = rebase_path("$target_gen_dir")
+ sdk_path = rebase_path(sdk_outline_dill)
+
+ deps = [
+ ":dartdevc_files_stamp",
+ ":dartdevc_platform",
+
+ # TODO(sigmund): depend only on the compiler and the actual files in the
+ # package
+ "../../pkg:pkg_files_stamp",
+ ]
+
+ inputs = [
+ sdk_outline_dill,
+ "$target_gen_dir/dartdevc_files.stamp",
+ "$root_gen_dir/pkg_files.stamp",
+ ]
+
+ outputs = [
+ "$target_gen_dir/pkg_kernel/$module.dill",
+ "$target_gen_dir/pkg_kernel/$module.js",
+ ]
+
+ args = [
+ "-k",
+ "--dart-sdk-summary=$sdk_path",
+ "-o$outdir/pkg_kernel/$module.js",
+ "package:$module/$module.dart",
+ ]
+
+ if (defined(invoker.extra_libraries)) {
+ foreach(lib, invoker.extra_libraries) {
+ args += [ "package:$module/$lib.dart" ]
+ }
+ }
+
+ if (defined(invoker.package_dependencies)) {
+ foreach(dep, invoker.package_dependencies) {
+ deps += [ ":${dep}_js" ]
+ args += [ "-s$outdir/pkg_kernel/$dep.dill" ]
+ }
+ }
+
+ if (defined(invoker.args)) {
+ args += invoker.args
+ }
+
+ # TODO(sigmund): remove nnbd_disabled. We turned this off temporarily while
+ # the migration of libraries is in flux, this step otherwise fails with many
+ # nnbd-related compile-time errors because the packages are assumed to be
+ # nnbd compilant.
+ if (!defined(invoker.nnbd_disabled) || !invoker.nnbd_disabled) {
+ # TODO(38701): Cleanup after merging the forked SDK into mainline.
+ if (use_nnbd) {
+ args += [ "--enable-experiment=non-nullable" ]
+ }
+ }
+ }
+}
+
+dartdevc_kernel_compile("async_helper_js") {
+ package = "async_helper"
+}
+
+dartdevc_kernel_compile("collection_js") {
+ package = "collection"
+ nnbd_disabled = true
+}
+
+dartdevc_kernel_compile("expect_js") {
+ package = "expect"
+ extra_libraries = [ "minitest" ]
+}
+
+dartdevc_kernel_compile("js_js") {
+ package = "js"
+ extra_libraries = [ "js_util" ]
+}
+
+dartdevc_kernel_compile("matcher_js") {
+ package = "matcher"
+ package_dependencies = [ "stack_trace" ]
+ nnbd_disabled = true
+}
+
+dartdevc_kernel_compile("meta_js") {
+ package = "meta"
+}
+
+dartdevc_kernel_compile("path_js") {
+ package = "path"
+ nnbd_disabled = true
+}
+
+dartdevc_kernel_compile("stack_trace_js") {
+ package = "stack_trace"
+ package_dependencies = [ "path" ]
+ nnbd_disabled = true
+}
+
+# TODO(rnystrom): Remove this when unittest is no longer used. Also remove
+# any of the above packages that are only here because unittest uses them.
+dartdevc_kernel_compile("unittest_js") {
+ package = "unittest"
+ package_dependencies = [
+ "path",
+ "stack_trace",
]
+ extra_libraries = [
+ "html_config",
+ "html_individual_config",
+ "html_enhanced_config",
+ ]
+ nnbd_disabled = true
+}
+
+compile_platform("dartdevc_platform") {
+ single_root_scheme = "org-dartlang-sdk"
+ single_root_base = rebase_path("../../")
+ libraries_specification_uri =
+ "org-dartlang-sdk:///$libraries_specification_path"
outputs = [
- sdk_dill,
+ sdk_full_dill,
+ sdk_outline_dill,
]
- script = "../../utils/bazel/kernel_worker.dart"
-
args = [
- "--summary-only",
- "--target",
- "ddc",
- "--multi-root-scheme",
- "org-dartlang-sdk",
- "--multi-root",
- "file:///" + rebase_path(sdk_root),
- "--libraries-file",
- "org-dartlang-sdk:///lib/libraries.json",
- "--output",
- rebase_path(sdk_dill),
- "--source",
+ "--target=dartdevc",
"dart:core",
]
@@ -387,26 +530,18 @@
}
}
-copy("dartdevc_kernel_sdk_libraries_json") {
- sources = [
- rebase_path("$sdk_root/lib/libraries.json"),
- ]
- outputs = [
- sdk_libraries_json,
- ]
-}
-
# Compiles the DDC SDK's kernel summary and JS code.
prebuilt_dart_action("dartdevc_kernel_sdk") {
deps = [
":dartdevc_files_stamp",
- ":dartdevc_sdk_patch_stamp",
+ ":dartdevc_platform",
"../../pkg:pkg_files_stamp",
]
inputs = [
"$target_gen_dir/dartdevc_files.stamp",
"$root_gen_dir/pkg_files.stamp",
+ sdk_full_dill,
]
outputs = [
@@ -420,21 +555,13 @@
"$target_gen_dir/kernel/legacy/dart_sdk.js.map",
]
- script = "../../pkg/dev_compiler/bin/dartdevc.dart"
+ script = "../../pkg/dev_compiler/tool/compile_dartdevc_sdk.dart"
args = [
- "-k",
- "--compile-sdk",
- "dart:core",
- "--no-summarize",
"--multi-root-scheme",
"org-dartlang-sdk",
- "--multi-root",
- "file:///" + rebase_path(sdk_root),
"--multi-root-output-path",
- rebase_path("$target_gen_dir/../../"),
- "--libraries-file",
- "org-dartlang-sdk:///lib/libraries.json",
+ rebase_path("$target_gen_dir/../../../"),
"--modules",
"amd",
"-o",
@@ -451,6 +578,7 @@
"legacy",
"-o",
rebase_path("$target_gen_dir/kernel/legacy/dart_sdk.js"),
+ rebase_path("$sdk_full_dill"),
]
# TODO(38701): Cleanup after merging the forked SDK into mainline.