Version 2.13.0-39.0.dev
Merge commit '02f0f53ddf6c91a2bed4614d95743ee56cff8077' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_typedef.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_typedef.dart
new file mode 100644
index 0000000..a3c4ea0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/top_merge_typedef.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*library: nnbd=true*/
+
+typedef Typedef1 = void Function();
+typedef Typedef2 = dynamic Function();
+
+/*class: A:A,Object*/
+abstract class A {
+ /*member: A.method1:void Function(void Function())*/
+ void method1(void Function() f);
+
+ /*member: A.method2:void Function(void Function())*/
+ void method2(Typedef1 f);
+
+ /*member: A.method3:void Function(void Function())*/
+ void method3(Typedef1 f);
+
+ /*member: A.method4:void Function(void Function())*/
+ void method4(void Function() f);
+}
+
+/*class: B:B,Object*/
+abstract class B {
+ /*member: B.method1:void Function(dynamic Function())*/
+ void method1(dynamic Function() f);
+
+ /*member: B.method2:void Function(dynamic Function())*/
+ void method2(Typedef2 f);
+
+ /*member: B.method3:void Function(dynamic Function())*/
+ void method3(dynamic Function() f);
+
+ /*member: B.method4:void Function(dynamic Function())*/
+ void method4(Typedef2 f);
+}
+
+/*class: C:A,B,C,Object*/
+abstract class C implements A, B {
+ /*member: C.method1:void Function(Object? Function())*/
+ /*member: C.method2:void Function(Object? Function())*/
+ /*member: C.method3:void Function(Object? Function())*/
+ /*member: C.method4:void Function(Object? Function())*/
+}
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 7beabe0..f6a2f41 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -6,6 +6,8 @@
library fasta.incremental_compiler;
+import 'dart:async' show Completer;
+
import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
show ScannerConfiguration;
@@ -167,6 +169,10 @@
IncrementalKernelTarget userCode;
Set<Library> previousSourceBuilders;
+ /// Guard against multiple computeDelta calls at the same time (possibly
+ /// caused by lacking awaits etc).
+ Completer currentlyCompiling;
+
IncrementalCompiler.fromComponent(
this.context, this.componentToInitializeFrom,
[bool outlineOnly, this.incrementalSerializer])
@@ -216,6 +222,10 @@
@override
Future<Component> computeDelta(
{List<Uri> entryPoints, bool fullComponent: false}) async {
+ while (currentlyCompiling != null) {
+ await currentlyCompiling.future;
+ }
+ currentlyCompiling = new Completer();
if (resetTicker) {
ticker.reset();
}
@@ -365,10 +375,17 @@
NonNullableByDefaultCompiledMode compiledMode = componentWithDill == null
? data.component?.mode
: componentWithDill.mode;
- return context.options.target.configureComponent(
+ Component result = context.options.target.configureComponent(
new Component(libraries: outputLibraries, uriToSource: uriToSource))
..setMainMethodAndMode(mainMethod?.reference, true, compiledMode)
..problemsAsJson = problemsAsJson;
+
+ // We're now done. Allow any waiting compile to start.
+ Completer currentlyCompilingLocal = currentlyCompiling;
+ currentlyCompiling = null;
+ currentlyCompilingLocal.complete();
+
+ return result;
});
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart b/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart
index 2f22878..641352a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/combined_member_signature.dart
@@ -332,6 +332,10 @@
_coreTypes,
_combinedMemberSignatureType,
norm(_coreTypes, getMemberType(index)));
+ assert(
+ _combinedMemberSignatureType != null,
+ "No combined member signature found for "
+ "${_mutualSubtypes.values.map((int i) => getMemberType(i))}");
}
}
_neededNnbdTopMerge =
diff --git a/pkg/front_end/test/multiple_simultaneous_compiles_test.dart b/pkg/front_end/test/multiple_simultaneous_compiles_test.dart
new file mode 100644
index 0000000..6d3e9e1
--- /dev/null
+++ b/pkg/front_end/test/multiple_simultaneous_compiles_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+import 'dart:io';
+
+import 'package:front_end/src/api_unstable/vm.dart';
+import 'package:front_end/src/fasta/incremental_compiler.dart';
+import 'package:kernel/ast.dart';
+
+import 'incremental_load_from_dill_suite.dart' show getOptions;
+
+main() async {
+ Uri compileTarget = Platform.script.resolve("binary_md_dill_reader.dart");
+ if (!(new File.fromUri(compileTarget)).existsSync()) {
+ throw "$compileTarget doesn't exist";
+ }
+
+ List<Future> futures = [];
+ List<int> compilesLeft = new List<int>.filled(5, 8);
+ for (int i = 0; i < compilesLeft.length; i++) {
+ Future<Component> compileAgain() async {
+ print("$i has ${compilesLeft[i]} left.");
+ if (compilesLeft[i] > 0) {
+ compilesLeft[i]--;
+ return compile(i, compileTarget).then((value) => compileAgain());
+ }
+ return null;
+ }
+
+ print("Starting first compile for $i");
+ futures.add(compile(i, compileTarget).then((value) => compileAgain()));
+ }
+ await Future.wait(futures);
+
+ print("Checkpoint #1: Can compiles several at once "
+ "(with different compilers!)");
+
+ for (int i = 0; i < 5; i++) {
+ futures.clear();
+ for (int j = 0; j < 10; j++) {
+ futures.add(compile(0, compileTarget));
+ }
+ await Future.wait(futures);
+ }
+
+ print("Checkpoint #2: Can compiles several at once "
+ "(with the same compiler) (without crashing)");
+}
+
+List<IncrementalCompiler> compilers = [];
+
+Future<Component> compile(int compilerNum, Uri uri) async {
+ if (compilers.length <= compilerNum) {
+ compilers.length = compilerNum + 1;
+ }
+ IncrementalCompiler compiler = compilers[compilerNum];
+ if (compiler == null) {
+ var options = getOptions();
+ compiler = new IncrementalCompiler(new CompilerContext(
+ new ProcessedOptions(options: options, inputs: [uri])));
+ compilers[compilerNum] = compiler;
+ } else {
+ compiler.invalidateAllSources();
+ }
+ Component result = await compiler.computeDelta();
+ print("Now compile is done!");
+ return result;
+}
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 5d9da02..69f280f 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -75,6 +75,7 @@
auxiliary
awaited
awaiting
+awaits
b
b0i
b0m
@@ -1334,6 +1335,7 @@
vs
vtab
w
+waiting
waste
wasted
watch
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index cd57d77..fa63366 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -162,8 +162,9 @@
///
/// Has no effect if [child] is not actually a child of this node.
///
- /// If [replacement] is `null`, this will [remove] the [child] node.
+ /// [replacement] must be non-null.
void replaceChild(TreeNode child, TreeNode replacement) {
+ assert(replacement != null);
transformChildren(new _ChildReplacer(child, replacement));
}
@@ -173,21 +174,13 @@
/// particular, [replacement] should be an orphan or be part of an orphaned
/// subtree.
///
- /// If [replacement] is `null`, this will [remove] the node.
+ /// [replacement] must be non-null.
void replaceWith(TreeNode replacement) {
+ assert(replacement != null);
parent.replaceChild(this, replacement);
parent = null;
}
- /// Removes this node from the [List] it is currently stored in, or assigns
- /// `null` to the field on the parent currently pointing to the node.
- ///
- /// Has no effect if the node is orphaned or if the parent pointer is stale.
- void remove() {
- parent?.replaceChild(this, null);
- parent = null;
- }
-
Component get enclosingComponent => parent?.enclosingComponent;
/// Returns the best known source location of the given AST node, or `null` if
@@ -11559,3 +11552,7 @@
/// `List.filled` constructor.
const NamedType namedTypeDummy =
const NamedType('', dartTypeDummy, isRequired: false);
+
+/// Non-nullable `Member` value to be used as a dummy initial value for the
+/// `List.filled` constructor.
+final Member dummyMember = new Field.mutable(new _PublicName(''));
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 30fc980..08ed371 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -248,7 +248,9 @@
List<Member> first, List<Member> second) {
if (first.isEmpty) return second;
if (second.isEmpty) return first;
- List<Member> result = <Member>[]..length = first.length + second.length;
+ List<Member> result = new List<Member>.filled(
+ first.length + second.length, dummyMember,
+ growable: true);
int storeIndex = 0;
int i = 0, j = 0;
while (i < first.length && j < second.length) {
@@ -1282,8 +1284,9 @@
static List<Member> _inheritMembers(
List<Member> declared, List<Member> inherited,
{bool skipAbstractMembers: false}) {
- List<Member> result = <Member>[]..length =
- declared.length + inherited.length;
+ List<Member> result = new List<Member>.filled(
+ declared.length + inherited.length, dummyMember,
+ growable: true);
// Since both lists are sorted, we can fuse them like in merge sort.
int storeIndex = 0;
int i = 0, j = 0;
@@ -1333,7 +1336,8 @@
/// The input lists must be sorted, and the returned list is sorted.
static List<Member> _getUnshadowedInheritedMembers(
List<Member> declared, List<Member> inherited) {
- List<Member> result = <Member>[]..length = inherited.length;
+ List<Member> result =
+ new List<Member>.filled(inherited.length, dummyMember, growable: true);
int storeIndex = 0;
int i = 0, j = 0;
while (i < declared.length && j < inherited.length) {
@@ -1433,10 +1437,8 @@
for (Class class_ in _infoMap.keys) {
_ClassInfo info = _infoMap[class_]!;
int intervals = info.supertypeIntervalList.length ~/ 2;
- if (intervals >= result.length) {
- int oldLength = result.length;
- result.length = intervals + 1;
- result.fillRange(oldLength, result.length, 0);
+ while (result.length <= intervals) {
+ result.add(0);
}
result[intervals] += 1;
}
diff --git a/pkg/kernel/lib/src/merge_visitor.dart b/pkg/kernel/lib/src/merge_visitor.dart
index de66d20..f089d75 100644
--- a/pkg/kernel/lib/src/merge_visitor.dart
+++ b/pkg/kernel/lib/src/merge_visitor.dart
@@ -115,9 +115,10 @@
newNamedParameters[i] = newNamedType;
}
TypedefType? newTypedefType;
- if (a.typedefType != null) {
+ if (a.typedefType != null && b.typedefType != null) {
newTypedefType = mergeTypes(a.typedefType, b.typedefType) as TypedefType?;
- if (newTypedefType == null) return null;
+ // If the typedef couldn't be merged we just omit it from the resulting
+ // function type since the typedef type is only informational.
}
return new FunctionType(newPositionalParameters, newReturnType, nullability,
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index a558085..7e0dc6a 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -350,7 +350,8 @@
experimentalFlags: experimentalFlags,
packageConfig: packageConfig,
invocationModes: invocationModes);
-
+ // TODO(VM TEAM): This does not seem safe. What if cloning while having
+ // pending deltas for instance?
generator.resetDeltaState();
Component fullComponent = await generator.compile();
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index 10cfe47..688af2c 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -348,7 +348,8 @@
}
// Remove initializers referring to fields to prevent cascading errors.
for (final Initializer i in toRemove) {
- i.remove();
+ final Constructor c = i.parent;
+ c.initializers.remove(i);
}
// Add a constructor which 'load' can use.
@@ -444,7 +445,7 @@
}
for (final Field f in fields.values) {
- f.remove();
+ node.fields.remove(f);
}
for (final i in getters.keys) {
diff --git a/tools/VERSION b/tools/VERSION
index 9f1a7ac..9c16a52 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 38
+PRERELEASE 39
PRERELEASE_PATCH 0
\ No newline at end of file