Version 2.11.0-225.0.dev
Merge commit '00a28b579771f74efbcc274e3a40c5840f57820b' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index f28f239..1402523 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -235,14 +235,6 @@
librariesLoaded += cycle.libraries.length;
}
- // We are about to load dart:core, but if we have just linked it, the
- // linker might have set the type provider. So, clear it, and recreate
- // the element factory - it is empty anyway.
- if (!elementFactory.hasDartCore) {
- analysisContext.clearTypeProvider();
- _createElementFactory();
- }
-
var bundle = LinkedNodeBundle.fromBuffer(bytes);
inputBundles.add(bundle);
elementFactory.addBundle(
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 53409d0..bd7ab2fa 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -271,6 +271,49 @@
return file.libraryCycle.signatureStr;
}
+ /// Ensure that libraries necessary for resolving [path] are linked.
+ ///
+ /// Libraries are linked in library cycles, from the bottom to top, so that
+ /// when we link a cycle, everything it transitively depends is ready. We
+ /// load newly linked libraries from bytes, and when we link a new library
+ /// cycle we partially resynthesize AST and elements from previously
+ /// loaded libraries.
+ ///
+ /// But when we are done linking libraries, and want to resolve just the
+ /// very top library that transitively depends on the whole dependency
+ /// tree, this library will not reference as many elements in the
+ /// dependencies as we needed for linking. Most probably it references
+ /// elements from directly imported libraries, and a couple of layers below.
+ /// So, keeping all previously resynthesized data is usually a waste.
+ ///
+ /// This method ensures that we discard the libraries context, with all its
+ /// partially resynthesized data, and so prepare for loading linked summaries
+ /// from bytes, which will be done by [getErrors]. It is OK for it to
+ /// spend some more time on this.
+ void linkLibraries({
+ @required String path,
+ }) {
+ _throwIfNotAbsoluteNormalizedPath(path);
+
+ var performance = OperationPerformanceImpl('<unused>');
+
+ _withLibraryContextReset(() {
+ var fileContext = getFileContext(
+ path: path,
+ performance: performance,
+ );
+ var file = fileContext.file;
+ var libraryFile = file.partOfLibrary ?? file;
+
+ libraryContext.load2(
+ targetLibrary: libraryFile,
+ performance: performance,
+ );
+ });
+
+ _resetContextObjects();
+ }
+
/// The [completionLine] and [completionColumn] are zero based.
ResolvedUnitResult resolve({
int completionLine,
@@ -531,6 +574,13 @@
}
}
+ void _resetContextObjects() {
+ if (libraryContext != null) {
+ contextObjects = null;
+ libraryContext = null;
+ }
+ }
+
void _throwIfNotAbsoluteNormalizedPath(String path) {
var pathContext = resourceProvider.pathContext;
if (pathContext.normalize(path) != path) {
@@ -691,14 +741,6 @@
performance.getDataInt('libraryLoadCount').add(cycle.libraries.length);
}
- // We are about to load dart:core, but if we have just linked it, the
- // linker might have set the type provider. So, clear it, and recreate
- // the element factory - it is empty anyway.
- if (!elementFactory.hasDartCore) {
- contextObjects.analysisContext.clearTypeProvider();
- elementFactory.declareDartCoreDynamicNever();
- }
-
var cBundle = CiderLinkedLibraryCycle.fromBuffer(bytes);
inputBundles.add(cBundle.bundle);
elementFactory.addBundle(
@@ -715,6 +757,9 @@
);
}
}
+
+ // We might have just linked dart:core, ensure the type provider.
+ _createElementFactoryTypeProvider();
}
logger.run('Prepare linked bundles', () {
@@ -732,7 +777,7 @@
/// If we need these libraries later, we will relink and reattach them.
void remove(List<FileState> removed) {
elementFactory.removeLibraries(
- removed.map((e) => e.uriStr).toList(),
+ removed.map((e) => e.uriStr).toSet(),
);
var removedSet = removed.toSet();
@@ -741,6 +786,16 @@
});
}
+ /// Ensure that type provider is created.
+ void _createElementFactoryTypeProvider() {
+ var analysisContext = contextObjects.analysisContext;
+ if (analysisContext.typeProviderNonNullableByDefault == null) {
+ var dartCore = elementFactory.libraryOfUri('dart:core');
+ var dartAsync = elementFactory.libraryOfUri('dart:async');
+ elementFactory.createTypeProviders(dartCore, dartAsync);
+ }
+ }
+
static CiderLinkedLibraryCycleBuilder serializeBundle(
List<int> signature, link2.LinkResult linkResult) {
return CiderLinkedLibraryCycleBuilder(
@@ -791,10 +846,7 @@
if (resetTimeout != null) {
_timer = Timer(resetTimeout, () {
_timer = null;
- if (fileResolver.libraryContext != null) {
- fileResolver.contextObjects = null;
- fileResolver.libraryContext = null;
- }
+ fileResolver._resetContextObjects();
});
}
}
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 8dd1b7c..abfaeec 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -28,7 +28,7 @@
) {
ArgumentError.checkNotNull(analysisContext, 'analysisContext');
ArgumentError.checkNotNull(analysisSession, 'analysisSession');
- declareDartCoreDynamicNever();
+ _declareDartCoreDynamicNever();
}
Reference get dynamicRef {
@@ -95,12 +95,6 @@
}
}
- void declareDartCoreDynamicNever() {
- var dartCoreRef = rootReference.getChild('dart:core');
- dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
- dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
- }
-
Element elementOfReference(Reference reference) {
if (reference.element != null) {
return reference.element;
@@ -147,19 +141,38 @@
/// We have linked the bundle, and need to disconnect its libraries, so
/// that the client can re-add the bundle, this time read from bytes.
void removeBundle(LinkedBundleContext context) {
- var uriStrList = context.libraryMap.keys.toList();
- removeLibraries(uriStrList);
+ var uriStrSet = context.libraryMap.keys.toSet();
+ removeLibraries(uriStrSet);
+
+ // This is the bundle with dart:core and dart:async, based on full ASTs.
+ // To link them, the linker set the type provider. We are removing these
+ // libraries, and we should also remove the type provider.
+ if (uriStrSet.contains('dart:core')) {
+ if (!uriStrSet.contains('dart:async')) {
+ throw StateError(
+ 'Expected to link dart:core and dart:async together: '
+ '${uriStrSet.toList()}',
+ );
+ }
+ if (libraryMap.isNotEmpty) {
+ throw StateError(
+ 'Expected to link dart:core and dart:async first: '
+ '${libraryMap.keys.toList()}',
+ );
+ }
+ analysisContext.clearTypeProvider();
+ _declareDartCoreDynamicNever();
+ }
}
/// Remove libraries with the specified URIs from the reference tree, and
/// any session level caches.
- void removeLibraries(List<String> uriStrList) {
- for (var uriStr in uriStrList) {
+ void removeLibraries(Set<String> uriStrSet) {
+ for (var uriStr in uriStrSet) {
libraryMap.remove(uriStr);
rootReference.removeChild(uriStr);
}
- var uriStrSet = uriStrList.toSet();
analysisSession.classHierarchy.removeOfLibraries(uriStrSet);
analysisSession.inheritanceManager.removeOfLibraries(uriStrSet);
}
@@ -181,6 +194,12 @@
}
}
+ void _declareDartCoreDynamicNever() {
+ var dartCoreRef = rootReference.getChild('dart:core');
+ dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
+ dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
+ }
+
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.
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 45500b8..5a7a974 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -464,6 +464,24 @@
]);
}
+ test_linkLibraries_getErrors() {
+ addTestFile(r'''
+var a = b;
+var foo = 0;
+''');
+
+ var path = convertPath('/workspace/dart/test/lib/test.dart');
+ fileResolver.linkLibraries(path: path);
+
+ var result = getTestErrors();
+ expect(result.path, path);
+ expect(result.uri.toString(), 'package:dart.test/test.dart');
+ assertErrorsInList(result.errors, [
+ error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 8, 1),
+ ]);
+ expect(result.lineInfo.lineStarts, [0, 11, 24]);
+ }
+
test_nullSafety_enabled() async {
typeToStringWithNullability = true;
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index d54ecef..d12313b 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -1776,14 +1776,23 @@
js_ast.Fun _emitNativeFunctionBody(Procedure node) {
var name = _annotationName(node, isJSAnnotation) ?? node.name.text;
if (node.isGetter) {
- return js_ast.Fun([], js.block('{ return this.#; }', [name]));
+ var returnValue = js('this.#', [name]);
+ if (_isNullCheckableNative(node)) {
+ // Add a potential null-check on native getter if type is non-nullable.
+ returnValue = runtimeCall('checkNativeNonNull(#)', [returnValue]);
+ }
+ return js_ast.Fun([], js.block('{ return #; }', [returnValue]));
} else if (node.isSetter) {
var params = _emitParameters(node.function);
return js_ast.Fun(
params, js.block('{ this.# = #; }', [name, params.last]));
} else {
- return js.fun(
- 'function (...args) { return this.#.apply(this, args); }', name);
+ var returnValue = js('this.#.apply(this, args)', [name]);
+ if (_isNullCheckableNative(node)) {
+ // Add a potential null-check on return value if type is non-nullable.
+ returnValue = runtimeCall('checkNativeNonNull(#)', [returnValue]);
+ }
+ return js.fun('function (...args) { return #; }', [returnValue]);
}
}
@@ -2270,6 +2279,9 @@
// Fields on a native class are implicitly native.
// Methods/getters/setters are marked external/native.
if (member is Field || _isExternal(member)) {
+ // If the native member needs to be null-checked, we require symbolizing
+ // it in order to access the null-check at the member definition.
+ if (_isNullCheckableNative(member)) return true;
var jsName = _annotationName(member, isJSName);
return jsName != null && jsName != name;
} else {
@@ -4215,14 +4227,8 @@
@override
js_ast.Expression visitPropertyGet(PropertyGet node) {
- var propertyGet =
- _emitPropertyGet(node.receiver, node.interfaceTarget, node.name.text);
- if (_isCheckableNative(node.interfaceTarget)) {
- // If target is a native getter with a non-nullable type, add a null check
- // for soundness.
- return runtimeCall('checkNativeNonNull(#)', [propertyGet]);
- }
- return propertyGet;
+ return _emitPropertyGet(
+ node.receiver, node.interfaceTarget, node.name.text);
}
@override
@@ -4276,8 +4282,8 @@
}
/// Return whether [member] returns a native object whose type needs to be
- /// checked.
- bool _isCheckableNative(Member member) =>
+ /// null-checked. This is true for non-nullable native return types.
+ bool _isNullCheckableNative(Member member) =>
member != null &&
member.isExternal &&
_extensionTypes.isNativeClass(member.enclosingClass) &&
@@ -4355,14 +4361,8 @@
@override
js_ast.Expression visitMethodInvocation(MethodInvocation node) {
- var methodCall = _emitMethodCall(
+ return _emitMethodCall(
node.receiver, node.interfaceTarget, node.arguments, node);
- if (_isCheckableNative(node.interfaceTarget)) {
- // If target is a native method with a non-nullable type, add a null check
- // for soundness.
- return runtimeCall('checkNativeNonNull(#)', [methodCall]);
- }
- return methodCall;
}
js_ast.Expression _emitMethodCall(Expression receiver, Member target,
diff --git a/runtime/tools/dartfuzz/README.md b/runtime/tools/dartfuzz/README.md
index 7165b63..b1531d0 100644
--- a/runtime/tools/dartfuzz/README.md
+++ b/runtime/tools/dartfuzz/README.md
@@ -61,10 +61,6 @@
--mode2 : m2, and values one of
jit-[debug-][ia32|x64|arm32|arm64] = Dart JIT
aot-[debug-][x64|arm32|arm64] = Dart AOT
- kbc-[int|mix|cmp]-[debug-][ia32|x64|arm32|arm64] = Dart KBC
- (interpreted/
- mixed-mode/
- compiled bytecode)
djs-x64 = dart2js + Node.JS
--[no-]rerun : re-run a testcase if there is only a divergence in
the return codes outside the range [-255,+255];
diff --git a/runtime/tools/dartfuzz/dartfuzz_test.dart b/runtime/tools/dartfuzz/dartfuzz_test.dart
index 8093309..8e826fa 100644
--- a/runtime/tools/dartfuzz/dartfuzz_test.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_test.dart
@@ -51,26 +51,6 @@
String prefix = mode.substring(0, 3).toUpperCase();
String tag = getTag(mode);
List<String> extraFlags = [];
- // Required extra flags for kbc.
- if (mode.startsWith('kbc-int')) {
- prefix += '-INT';
- extraFlags += [
- '--enable-interpreter',
- '--compilation-counter-threshold=-1'
- ];
- } else if (mode.startsWith('kbc-mix')) {
- prefix += '-MIX';
- extraFlags += ['--enable-interpreter'];
- } else if (mode.startsWith('kbc-cmp')) {
- prefix += '-CMP';
- extraFlags += ['--use-bytecode-compiler'];
- }
- // Every once in a while, go directly from source for kbc.
- bool kbcSrc = false;
- if (mode.startsWith('kbc') && rand.nextInt(4) == 0) {
- prefix += '-SRC';
- kbcSrc = true;
- }
// Every once in a while, stress test JIT.
if (mode.startsWith('jit') && rand.nextInt(4) == 0) {
final r = rand.nextInt(7);
@@ -126,9 +106,6 @@
return TestRunnerJIT(prefix, tag, top, tmp, env, fileName, extraFlags);
} else if (mode.startsWith('aot')) {
return TestRunnerAOT(prefix, tag, top, tmp, env, fileName, extraFlags);
- } else if (mode.startsWith('kbc')) {
- return TestRunnerKBC(
- prefix, tag, top, tmp, env, fileName, extraFlags, kbcSrc);
} else if (mode.startsWith('djs')) {
return TestRunnerDJS(prefix, tag, top, tmp, env, fileName);
}
@@ -227,60 +204,6 @@
List<String> cmd;
}
-/// Concrete test runner of bytecode.
-class TestRunnerKBC implements TestRunner {
- TestRunnerKBC(String prefix, String tag, this.top, this.tmp, this.env,
- this.fileName, List<String> extraFlags, bool kbcSrc) {
- description = '$prefix-$tag';
- dart = '$top/out/$tag/dart';
- if (kbcSrc) {
- cmd = [
- dart,
- ...extraFlags,
- '--old_gen_heap_size=${dartHeapSize}',
- fileName
- ];
- } else {
- generate = '$top/pkg/vm/tool/gen_kernel';
- platform = '--platform=$top/out/$tag/vm_platform_strong.dill';
- dill = '$tmp/out.dill';
- cmd = [dart, ...extraFlags, '--old_gen_heap_size=${dartHeapSize}', dill];
- }
- }
-
- TestResult run() {
- if (generate != null) {
- TestResult result = runCommand(
- [generate, '--gen-bytecode', platform, '-o', dill, fileName], env);
- if (result.exitCode != 0) {
- return result;
- }
- }
- return runCommand(cmd, env);
- }
-
- void printReproductionCommand() {
- if (generate != null) {
- print([generate, '--gen-bytecode', platform, '-o', dill, fileName]
- .join(" ")
- .replaceAll('$top/', '')
- .replaceAll('$tmp/', ''));
- }
- print(cmd.join(" ").replaceAll('$top/', '').replaceAll('$tmp/', ''));
- }
-
- String description;
- String generate;
- String platform;
- String dill;
- String dart;
- String fileName;
- final String top;
- final String tmp;
- Map<String, String> env;
- List<String> cmd;
-}
-
/// Concrete test runner of Dart2JS.
class TestRunnerDJS implements TestRunner {
TestRunnerDJS(
@@ -413,8 +336,8 @@
(mode1.contains('ia32') && mode2.contains('ia32')));
bool ffiCapable(String mode1, String mode2) =>
- (mode1.startsWith('jit') || mode1.startsWith('kbc')) &&
- (mode2.startsWith('jit') || mode2.startsWith('kbc')) &&
+ mode1.startsWith('jit') &&
+ mode2.startsWith('jit') &&
(!mode1.contains('arm') && !mode2.contains('arm'));
bool nestedTypesAllowed(String mode1, String mode2) =>
@@ -759,30 +682,6 @@
'jit-arm64',
'aot-debug-x64',
'aot-x64',
- 'kbc-int-debug-ia32',
- 'kbc-cmp-debug-ia32',
- 'kbc-mix-debug-ia32',
- 'kbc-int-debug-x64',
- 'kbc-cmp-debug-x64',
- 'kbc-mix-debug-x64',
- 'kbc-int-debug-arm32',
- 'kbc-cmp-debug-arm32',
- 'kbc-mix-debug-arm32',
- 'kbc-int-debug-arm64',
- 'kbc-cmp-debug-arm64',
- 'kbc-mix-debug-arm64',
- 'kbc-int-ia32',
- 'kbc-cmp-ia32',
- 'kbc-mix-ia32',
- 'kbc-int-x64',
- 'kbc-cmp-x64',
- 'kbc-mix-x64',
- 'kbc-int-arm32',
- 'kbc-cmp-arm32',
- 'kbc-mix-arm32',
- 'kbc-int-arm64',
- 'kbc-cmp-arm64',
- 'kbc-mix-arm64',
];
// Modes not used on cluster runs because they have outstanding issues.
diff --git a/tests/language/nnbd/inference/late_variable_type_for_promotion_test.dart b/tests/language/nnbd/inference/late_variable_type_for_promotion_test.dart
index d6223d5..fd4ebed 100644
--- a/tests/language/nnbd/inference/late_variable_type_for_promotion_test.dart
+++ b/tests/language/nnbd/inference/late_variable_type_for_promotion_test.dart
@@ -95,7 +95,7 @@
}
void uninitializedUntyped() {
- late x;
+ late var x;
x = 0;
x.expectStaticType<Exactly<dynamic>>();
// Attempting to promote to `int?` should be ok, since `int?` is a subtype of
diff --git a/tools/VERSION b/tools/VERSION
index f320424..70adc94 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 224
+PRERELEASE 225
PRERELEASE_PATCH 0
\ No newline at end of file