Version 2.18.0-67.0.dev
Merge commit '08c60454c1f3de61c474ee1663d9cd6dcd751c5d' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 689dd80..74c2841 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -860,7 +860,8 @@
// Optionally add Flutter child widget details.
// todo (pq): revisit this special casing; likely it can be generalized away
var element = parameter.enclosingElement;
- if (element is ConstructorElement) {
+ // If appendColon is false, default values should never be appended.
+ if (element is ConstructorElement && appendColon) {
if (Flutter.instance.isWidget(element.enclosingElement)) {
// Don't bother with nullability. It won't affect default list values.
var defaultValue =
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index 66574a8..3a55f69 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -1117,6 +1117,53 @@
expect(res.items.map((item) => item.label).contains('aaa'), isTrue);
}
+ Future<void> test_namedArg_flutterChildren() async {
+ final content = '''
+import 'package:flutter/widgets.dart';
+
+final a = Flex(c^);
+''';
+
+ final expectedContent = '''
+import 'package:flutter/widgets.dart';
+
+final a = Flex(children: [^],);
+''';
+
+ await verifyCompletions(
+ mainFileUri,
+ content,
+ expectCompletions: ['children: []'],
+ applyEditsFor: 'children: []',
+ expectedContent: expectedContent,
+ );
+ }
+
+ Future<void> test_namedArg_flutterChildren_existingValue() async {
+ // Flutter's widget classes have special handling that adds `[]` after the
+ // children named arg, but this should not occur if there's already a value
+ // for this named arg.
+ final content = '''
+import 'package:flutter/widgets.dart';
+
+final a = Flex(c^: []);
+''';
+
+ final expectedContent = '''
+import 'package:flutter/widgets.dart';
+
+final a = Flex(children: []);
+''';
+
+ await verifyCompletions(
+ mainFileUri,
+ content,
+ expectCompletions: ['children'],
+ applyEditsFor: 'children',
+ expectedContent: expectedContent,
+ );
+ }
+
Future<void> test_namedArg_insertReplaceRanges() async {
/// Helper to check multiple completions in the same template file.
Future<void> check(
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index ed5279a..57dca5f 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -216,6 +216,28 @@
]);
}
+ Future<void>
+ test_flutter_InstanceCreationExpression_children_existingValue() async {
+ // Ensure we don't include list markers if there's already a value.
+ writeTestPackageConfig(flutter: true);
+
+ addTestSource('''
+import 'package:flutter/material.dart';
+
+build() => new Row(
+ ch^: []
+ );
+''');
+
+ var response = await computeSuggestions2();
+ _checkNamedArguments(response).containsMatch(
+ (suggestion) => suggestion
+ ..completion.isEqualTo('children')
+ ..defaultArgumentListString.isNull
+ ..hasSelection(offset: 8),
+ );
+ }
+
Future<void> test_flutter_InstanceCreationExpression_children_Map() async {
// Ensure we don't generate Map params for a future API
writeTestPackageConfig(flutter: true);
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index a0f91f2..c203686 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -48,7 +48,7 @@
/// A concrete implementation of a [ClassElement].
abstract class AbstractClassElementImpl extends _ExistingElementImpl
- with TypeParameterizedElementMixin, HasCompletionData
+ with TypeParameterizedElementMixin, HasCompletionData, MacroTargetElement
implements ClassElement {
/// The superclass of the class, or `null` for [Object].
InterfaceType? _supertype;
@@ -78,9 +78,6 @@
List<InterfaceType>? Function(AbstractClassElementImpl)?
mixinInferenceCallback;
- /// Errors registered while applying macros to this element.
- List<MacroApplicationError> macroApplicationErrors = [];
-
/// Initialize a newly created class element to have the given [name] at the
/// given [offset] in the file that contains the declaration of this element.
AbstractClassElementImpl(String name, int offset) : super(name, offset);
@@ -4155,6 +4152,11 @@
visitor.visitLocalVariableElement(this);
}
+mixin MacroTargetElement {
+ /// Errors registered while applying macros to this element.
+ List<MacroApplicationError> macroApplicationErrors = [];
+}
+
/// A concrete implementation of a [MethodElement].
class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
/// Is `true` if this method is `operator==`, and there is no explicit
diff --git a/pkg/analyzer/lib/src/dart/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
index 2e85266..e6bd686 100644
--- a/pkg/analyzer/lib/src/dart/scanner/scanner.dart
+++ b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
@@ -221,5 +221,7 @@
enableExtensionMethods:
featureSet.isEnabled(Feature.extension_methods),
enableTripleShift: featureSet.isEnabled(Feature.triple_shift),
- enableNonNullable: featureSet.isEnabled(Feature.non_nullable));
+ enableNonNullable: featureSet.isEnabled(Feature.non_nullable),
+ forAugmentationLibrary: featureSet.isEnabled(Feature.macros),
+ );
}
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 3f1f4a4..8864dac 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -182,8 +182,14 @@
return;
}
- var applier = LibraryMacroApplier(this);
- var augmentationLibrary = await applier.executeMacroTypesPhase();
+ final macroExecutor = linker.macroExecutor;
+ if (macroExecutor == null) {
+ return;
+ }
+
+ var applier = LibraryMacroApplier(macroExecutor, this);
+ await applier.buildApplications();
+ var augmentationLibrary = await applier.executeTypesPhase();
if (augmentationLibrary == null) {
return;
}
diff --git a/pkg/analyzer/lib/src/summary2/macro.dart b/pkg/analyzer/lib/src/summary2/macro.dart
index bf4756d..c9931b4 100644
--- a/pkg/analyzer/lib/src/summary2/macro.dart
+++ b/pkg/analyzer/lib/src/summary2/macro.dart
@@ -58,13 +58,14 @@
required String className,
required String constructorName,
required macro.Arguments arguments,
- required macro.Declaration declaration,
required macro.IdentifierResolver identifierResolver,
+ required macro.DeclarationKind declarationKind,
+ required macro.Declaration declaration,
}) async {
var instanceIdentifier = await macroExecutor.instantiateMacro(
libraryUri, className, constructorName, arguments);
- return MacroClassInstance._(
- this, identifierResolver, declaration, instanceIdentifier);
+ return MacroClassInstance._(this, identifierResolver, instanceIdentifier,
+ declarationKind, declaration);
}
}
@@ -81,14 +82,16 @@
class MacroClassInstance {
final BundleMacroExecutor _bundleExecutor;
final macro.IdentifierResolver _identifierResolver;
- final macro.Declaration _declaration;
final macro.MacroInstanceIdentifier _instanceIdentifier;
+ final macro.DeclarationKind _declarationKind;
+ final macro.Declaration _declaration;
MacroClassInstance._(
this._bundleExecutor,
this._identifierResolver,
- this._declaration,
this._instanceIdentifier,
+ this._declarationKind,
+ this._declaration,
);
Future<macro.MacroExecutionResult> executeTypesPhase() async {
@@ -96,6 +99,10 @@
return await executor.executeTypesPhase(
_instanceIdentifier, _declaration, _identifierResolver);
}
+
+ bool shouldExecute(macro.Phase phase) {
+ return _instanceIdentifier.shouldExecute(_declarationKind, phase);
+ }
}
abstract class MacroFileEntry {
diff --git a/pkg/analyzer/lib/src/summary2/macro_application.dart b/pkg/analyzer/lib/src/summary2/macro_application.dart
index d9719b2..15da245 100644
--- a/pkg/analyzer/lib/src/summary2/macro_application.dart
+++ b/pkg/analyzer/lib/src/summary2/macro_application.dart
@@ -6,6 +6,7 @@
import 'package:_fe_analyzer_shared/src/macros/executor.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/introspection_impls.dart'
as macro;
+import 'package:_fe_analyzer_shared/src/macros/executor/multi_executor.dart';
import 'package:_fe_analyzer_shared/src/macros/executor/protocol.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor/remote_instance.dart'
as macro;
@@ -13,95 +14,71 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
+import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/macro.dart';
import 'package:analyzer/src/summary2/macro_application_error.dart';
class LibraryMacroApplier {
+ final MultiMacroExecutor macroExecutor;
final LibraryBuilder libraryBuilder;
+ final Map<MacroTargetElement, List<MacroApplication>> _applications =
+ Map.identity();
+
final Map<ClassDeclaration, macro.ClassDeclaration> _classDeclarations = {};
- LibraryMacroApplier(this.libraryBuilder);
+ LibraryMacroApplier(this.macroExecutor, this.libraryBuilder);
- /// TODO(scheglov) check `shouldExecute`.
- /// TODO(scheglov) check `supportsDeclarationKind`.
- Future<String?> executeMacroTypesPhase() async {
- var macroResults = <macro.MacroExecutionResult>[];
- for (var unitElement in libraryBuilder.element.units) {
- for (var classElement in unitElement.classes) {
+ Linker get _linker => libraryBuilder.linker;
+
+ /// Fill [_applications]s with macro applications.
+ Future<void> buildApplications() async {
+ for (final unitElement in libraryBuilder.element.units) {
+ for (final classElement in unitElement.classes) {
classElement as ClassElementImpl;
- var classNode = libraryBuilder.linker.elementNodes[classElement];
+ final classNode = _linker.elementNodes[classElement];
// TODO(scheglov) support other declarations
if (classNode is ClassDeclaration) {
- var annotationList = classNode.metadata;
- for (var i = 0; i < annotationList.length; i++) {
- final annotation = annotationList[i];
- var annotationNameNode = annotation.name;
- var argumentsNode = annotation.arguments;
- if (annotationNameNode is SimpleIdentifier &&
- argumentsNode != null) {
- // TODO(scheglov) Create a Scope.
- for (var import in libraryBuilder.element.imports) {
- var importedLibrary = import.importedLibrary;
- if (importedLibrary is LibraryElementImpl) {
- var importedUri = importedLibrary.source.uri;
- if (!libraryBuilder.linker.builders
- .containsKey(importedUri)) {
- var lookupResult = importedLibrary.scope.lookup(
- annotationNameNode.name,
- );
- var getter = lookupResult.getter;
- if (getter is ClassElementImpl && getter.isMacro) {
- var macroExecutor = importedLibrary.bundleMacroExecutor;
- if (macroExecutor != null) {
- try {
- final arguments = _buildArguments(
- annotationIndex: i,
- node: argumentsNode,
- );
- final macroResult = await _runSingleMacro(
- macroExecutor,
- getClassDeclaration(classNode),
- getter,
- arguments,
- );
- if (macroResult.isNotEmpty) {
- macroResults.add(macroResult);
- }
- } on MacroApplicationError catch (e) {
- classElement.macroApplicationErrors.add(e);
- } on macro.RemoteException catch (e) {
- classElement.macroApplicationErrors.add(
- UnknownMacroApplicationError(
- annotationIndex: i,
- message: e.error,
- stackTrace: e.stackTrace ?? '<null>',
- ),
- );
- } catch (e, stackTrace) {
- classElement.macroApplicationErrors.add(
- UnknownMacroApplicationError(
- annotationIndex: i,
- message: e.toString(),
- stackTrace: stackTrace.toString(),
- ),
- );
- }
- }
- }
+ await _buildApplications(
+ classElement,
+ classNode.metadata,
+ () => getClassDeclaration(classNode),
+ );
+ }
+ }
+ }
+ }
+
+ Future<String?> executeTypesPhase() async {
+ final results = <macro.MacroExecutionResult>[];
+ for (final unitElement in libraryBuilder.element.units) {
+ for (final classElement in unitElement.classes) {
+ classElement as ClassElementImpl;
+ final applications = _applications[classElement];
+ if (applications != null) {
+ for (final application in applications) {
+ if (application.shouldExecute(macro.Phase.types)) {
+ await _runWithCatchingExceptions(
+ () async {
+ final result = await application.instance.executeTypesPhase();
+ if (result.isNotEmpty) {
+ results.add(result);
}
- }
- }
+ },
+ annotationIndex: application.annotationIndex,
+ onError: (error) {
+ classElement.macroApplicationErrors.add(error);
+ },
+ );
}
}
}
}
}
- var macroExecutor = libraryBuilder.linker.macroExecutor;
- if (macroExecutor != null && macroResults.isNotEmpty) {
- var code = macroExecutor.buildAugmentationLibrary(
- macroResults,
+ if (results.isNotEmpty) {
+ final code = macroExecutor.buildAugmentationLibrary(
+ results,
_resolveIdentifier,
_inferOmittedType,
);
@@ -110,10 +87,103 @@
return null;
}
+ /// TODO(scheglov) Do we need this caching?
+ /// Or do we need it only during macro applications creation?
macro.ClassDeclaration getClassDeclaration(ClassDeclaration node) {
return _classDeclarations[node] ??= _buildClassDeclaration(node);
}
+ /// If there are any macro applications in [annotations], record for the
+ /// [targetElement] in [_applications], for future execution.
+ Future<void> _buildApplications(
+ MacroTargetElement targetElement,
+ List<Annotation> annotations,
+ macro.Declaration Function() getDeclaration,
+ ) async {
+ final applications = <MacroApplication>[];
+ for (var i = 0; i < annotations.length; i++) {
+ final annotation = annotations[i];
+ final macroElement = _importedMacroElement(annotation.name);
+ final argumentsNode = annotation.arguments;
+ if (macroElement is ClassElementImpl && argumentsNode != null) {
+ final importedLibrary = macroElement.library;
+ final macroExecutor = importedLibrary.bundleMacroExecutor;
+ if (macroExecutor != null) {
+ await _runWithCatchingExceptions(
+ () async {
+ final arguments = _buildArguments(
+ annotationIndex: i,
+ node: argumentsNode,
+ );
+ final declaration = getDeclaration();
+ final macroInstance = await macroExecutor.instantiate(
+ libraryUri: macroElement.librarySource.uri,
+ className: macroElement.name,
+ constructorName: '', // TODO
+ arguments: arguments,
+ identifierResolver: _FakeIdentifierResolver(),
+ declarationKind: macro.DeclarationKind.clazz,
+ declaration: declaration,
+ );
+ applications.add(
+ MacroApplication(
+ annotationIndex: i,
+ instance: macroInstance,
+ ),
+ );
+ },
+ annotationIndex: i,
+ onError: (error) {
+ targetElement.macroApplicationErrors.add(error);
+ },
+ );
+ }
+ }
+ }
+ if (applications.isNotEmpty) {
+ _applications[targetElement] = applications;
+ }
+ }
+
+ /// Return the macro element referenced by the [node].
+ ElementImpl? _importedMacroElement(Identifier node) {
+ final String? prefix;
+ final String name;
+ if (node is PrefixedIdentifier) {
+ prefix = node.prefix.name;
+ name = node.identifier.name;
+ } else if (node is SimpleIdentifier) {
+ prefix = null;
+ name = node.name;
+ } else {
+ throw StateError('${node.runtimeType} $node');
+ }
+
+ for (final import in libraryBuilder.element.imports) {
+ if (import.prefix?.name != prefix) {
+ continue;
+ }
+
+ final importedLibrary = import.importedLibrary;
+ if (importedLibrary == null) {
+ continue;
+ }
+
+ // Skip if a library that is being linked.
+ final importedUri = importedLibrary.source.uri;
+ if (_linker.builders.containsKey(importedUri)) {
+ continue;
+ }
+
+ final lookupResult = importedLibrary.scope.lookup(name);
+ final element = lookupResult.getter;
+ if (element is ClassElementImpl && element.isMacro) {
+ return element;
+ }
+ }
+ return null;
+ }
+
macro.TypeAnnotation _inferOmittedType(
macro.OmittedTypeAnnotation omittedType,
) {
@@ -124,23 +194,6 @@
throw UnimplementedError();
}
- Future<macro.MacroExecutionResult> _runSingleMacro(
- BundleMacroExecutor macroExecutor,
- macro.Declaration declaration,
- ClassElementImpl classElement,
- macro.Arguments arguments,
- ) async {
- var macroInstance = await macroExecutor.instantiate(
- libraryUri: classElement.librarySource.uri,
- className: classElement.name,
- constructorName: '', // TODO
- arguments: arguments,
- declaration: declaration,
- identifierResolver: _FakeIdentifierResolver(),
- );
- return await macroInstance.executeTypesPhase();
- }
-
static macro.Arguments _buildArguments({
required int annotationIndex,
required ArgumentList node,
@@ -278,6 +331,47 @@
return const [];
}
}
+
+ /// Run the [body], report exceptions as [MacroApplicationError]s to [onError].
+ static Future<void> _runWithCatchingExceptions<T>(
+ Future<T> Function() body, {
+ required int annotationIndex,
+ required void Function(MacroApplicationError) onError,
+ }) async {
+ try {
+ await body();
+ } on MacroApplicationError catch (e) {
+ onError(e);
+ } on macro.RemoteException catch (e) {
+ onError(
+ UnknownMacroApplicationError(
+ annotationIndex: annotationIndex,
+ message: e.error,
+ stackTrace: e.stackTrace ?? '<null>',
+ ),
+ );
+ } catch (e, stackTrace) {
+ onError(
+ UnknownMacroApplicationError(
+ annotationIndex: annotationIndex,
+ message: e.toString(),
+ stackTrace: stackTrace.toString(),
+ ),
+ );
+ }
+ }
+}
+
+class MacroApplication {
+ final int annotationIndex;
+ final MacroClassInstance instance;
+
+ MacroApplication({
+ required this.annotationIndex,
+ required this.instance,
+ });
+
+ bool shouldExecute(macro.Phase phase) => instance.shouldExecute(phase);
}
/// Helper class for evaluating arguments for a single constructor based
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 48deb10..6f7b7b7 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
@@ -233,7 +233,6 @@
_assertSource("abstract macro class C {}", declaration);
}
- @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/48541')
void test_visitClassDeclaration_augment() {
var findNode = _parseStringToFindNode(r'''
augment class A {}
@@ -461,7 +460,6 @@
isMacro: true));
}
- @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/48541')
void test_visitClassTypeAlias_augment() {
var findNode = _parseStringToFindNode(r'''
augment class A = S with M;
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart
index fe971f4..c4ea903 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/inference_update_1_test.dart
@@ -356,4 +356,34 @@
// regardless of whether the experiment is enabled.
assertType(findNode.simple('i; // (2)'), 'int?');
}
+
+ test_write_capture_deferred_redirecting_constructor() async {
+ await assertNoErrorsInCode('''
+class C {
+ C(int? i) : this.other(i!, () { i = null; }, i);
+ C.other(Object? x, void Function() g, Object? y);
+}
+''');
+ // With the feature enabled, analysis of the closure is deferred until after
+ // all the other arguments to `this.other`, so the `i` passed to `y` is not
+ // yet write captured and retains its promoted value. With the experiment
+ // disabled, it is write captured immediately.
+ assertType(findNode.simple('i);'), _isEnabled ? 'int' : 'int?');
+ }
+
+ test_write_capture_deferred_super_constructor() async {
+ await assertNoErrorsInCode('''
+class B {
+ B(Object? x, void Function() g, Object? y);
+}
+class C extends B {
+ C(int? i) : super(i!, () { i = null; }, i);
+}
+''');
+ // With the feature enabled, analysis of the closure is deferred until after
+ // all the other arguments to `this.other`, so the `i` passed to `y` is not
+ // yet write captured and retains its promoted value. With the experiment
+ // disabled, it is write captured immediately.
+ assertType(findNode.simple('i);'), _isEnabled ? 'int' : 'int?');
+ }
}
diff --git a/pkg/analyzer/test/src/fasta/ast_builder_test.dart b/pkg/analyzer/test/src/fasta/ast_builder_test.dart
index 8c4659e..b1cbcbd 100644
--- a/pkg/analyzer/test/src/fasta/ast_builder_test.dart
+++ b/pkg/analyzer/test/src/fasta/ast_builder_test.dart
@@ -15,7 +15,6 @@
@reflectiveTest
class AstBuilderTest extends ParserDiagnosticsTest {
- @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/48541')
void test_class_augment() {
var parseResult = parseStringWithErrors(r'''
augment class A {}
diff --git a/pkg/analyzer/test/src/summary/macro_test.dart b/pkg/analyzer/test/src/summary/macro_test.dart
index e2dd9f2..e073d88 100644
--- a/pkg/analyzer/test/src/summary/macro_test.dart
+++ b/pkg/analyzer/test/src/summary/macro_test.dart
@@ -63,6 +63,131 @@
);
}
+ test_application_newInstance_withoutPrefix() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import 'dart:async';
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+macro class MyMacro implements ClassTypesMacro {
+ FutureOr<void> buildTypesForClass(clazz, builder) {
+ builder.declareType(
+ 'MyClass',
+ DeclarationCode.fromString('class MyClass {}'),
+ );
+ }
+}
+''');
+
+ var library = await buildLibrary(r'''
+import 'a.dart';
+
+@MyMacro()
+class A {}
+''', preBuildSequence: [
+ {'package:test/a.dart'}
+ ]);
+
+ checkElementText(
+ library,
+ r'''
+library
+ imports
+ package:test/a.dart
+ definingUnit
+ classes
+ class A @35
+ metadata
+ Annotation
+ atSign: @ @18
+ name: SimpleIdentifier
+ token: MyMacro @19
+ staticElement: package:test/a.dart::@class::MyMacro
+ staticType: null
+ arguments: ArgumentList
+ leftParenthesis: ( @26
+ rightParenthesis: ) @27
+ element: package:test/a.dart::@class::MyMacro::@constructor::•
+ constructors
+ synthetic @-1
+ parts
+ package:test/_macro_types.dart
+ classes
+ class MyClass @6
+ constructors
+ synthetic @-1
+ exportScope
+ A: package:test/test.dart;A
+ MyClass: package:test/test.dart;package:test/_macro_types.dart;MyClass
+''',
+ withExportScope: true);
+ }
+
+ test_application_newInstance_withPrefix() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+import 'package:_fe_analyzer_shared/src/macros/api.dart';
+
+macro class MyMacro implements ClassTypesMacro {
+ buildTypesForClass(clazz, builder) {
+ builder.declareType(
+ 'MyClass',
+ DeclarationCode.fromString('class MyClass {}'),
+ );
+ }
+}
+''');
+
+ var library = await buildLibrary(r'''
+import 'a.dart' as prefix;
+
+@prefix.MyMacro()
+class A {}
+''', preBuildSequence: [
+ {'package:test/a.dart'}
+ ]);
+
+ checkElementText(
+ library,
+ r'''
+library
+ imports
+ package:test/a.dart as prefix @19
+ definingUnit
+ classes
+ class A @52
+ metadata
+ Annotation
+ atSign: @ @28
+ name: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: prefix @29
+ staticElement: self::@prefix::prefix
+ staticType: null
+ period: . @35
+ identifier: SimpleIdentifier
+ token: MyMacro @36
+ staticElement: package:test/a.dart::@class::MyMacro
+ staticType: null
+ staticElement: package:test/a.dart::@class::MyMacro
+ staticType: null
+ arguments: ArgumentList
+ leftParenthesis: ( @43
+ rightParenthesis: ) @44
+ element: package:test/a.dart::@class::MyMacro::@constructor::•
+ constructors
+ synthetic @-1
+ parts
+ package:test/_macro_types.dart
+ classes
+ class MyClass @6
+ constructors
+ synthetic @-1
+ exportScope
+ A: package:test/test.dart;A
+ MyClass: package:test/test.dart;package:test/_macro_types.dart;MyClass
+''',
+ withExportScope: true);
+ }
+
test_arguments_error() async {
await _assertTypesPhaseArgumentsText(
fields: {
@@ -259,65 +384,6 @@
);
}
- test_build_types() async {
- newFile('$testPackageLibPath/a.dart', r'''
-import 'dart:async';
-import 'package:_fe_analyzer_shared/src/macros/api.dart';
-
-macro class MyMacro implements ClassTypesMacro {
- FutureOr<void> buildTypesForClass(clazz, builder) {
- builder.declareType(
- 'MyClass',
- DeclarationCode.fromString('class MyClass {}'),
- );
- }
-}
-''');
-
- var library = await buildLibrary(r'''
-import 'a.dart';
-
-@MyMacro()
-class A {}
-''', preBuildSequence: [
- {'package:test/a.dart'}
- ]);
-
- checkElementText(
- library,
- r'''
-library
- imports
- package:test/a.dart
- definingUnit
- classes
- class A @35
- metadata
- Annotation
- atSign: @ @18
- name: SimpleIdentifier
- token: MyMacro @19
- staticElement: package:test/a.dart::@class::MyMacro
- staticType: null
- arguments: ArgumentList
- leftParenthesis: ( @26
- rightParenthesis: ) @27
- element: package:test/a.dart::@class::MyMacro::@constructor::•
- constructors
- synthetic @-1
- parts
- package:test/_macro_types.dart
- classes
- class MyClass @6
- constructors
- synthetic @-1
- exportScope
- A: package:test/test.dart;A
- MyClass: package:test/test.dart;package:test/_macro_types.dart;MyClass
-''',
- withExportScope: true);
- }
-
test_introspect_types_ClassDeclaration_interfaces() async {
await _assertTypesPhaseIntrospectionText(r'''
class A implements B, C<int, String> {}
diff --git a/pkg/compiler/lib/src/common/elements.dart b/pkg/compiler/lib/src/common/elements.dart
index c190bfc..27c63f4 100644
--- a/pkg/compiler/lib/src/common/elements.dart
+++ b/pkg/compiler/lib/src/common/elements.dart
@@ -17,7 +17,7 @@
import 'names.dart' show Identifiers, Uris;
/// The common elements and types in Dart.
-abstract class CommonElements {
+abstract class CommonElements implements CommonElementsForDartTypes {
final DartTypes dartTypes;
final ElementEnvironment _env;
ClassEntity _objectClass;
@@ -332,6 +332,7 @@
DynamicType get dynamicType => _env.dynamicType;
/// The `Object` type defined in 'dart:core'.
+ @override // CommonElementsForDartTypes
InterfaceType get objectType => _getRawType(objectClass);
/// The `bool` type defined in 'dart:core'.
@@ -341,9 +342,11 @@
InterfaceType get numType => _getRawType(numClass);
/// The `int` type defined in 'dart:core'.
+ @override // CommonElementsForDartTypes
InterfaceType get intType => _getRawType(intClass);
/// The `double` type defined in 'dart:core'.
+ @override // CommonElementsForDartTypes
InterfaceType get doubleType => _getRawType(doubleClass);
/// The `String` type defined in 'dart:core'.
@@ -353,9 +356,11 @@
InterfaceType get symbolType => _getRawType(symbolClass);
/// The `Function` type defined in 'dart:core'.
+ @override // CommonElementsForDartTypes
InterfaceType get functionType => _getRawType(functionClass);
/// The `Null` type defined in 'dart:core'.
+ @override // CommonElementsForDartTypes
InterfaceType get nullType => _getRawType(nullClass);
/// The `Type` type defined in 'dart:core'.
@@ -418,6 +423,7 @@
/// [elementType] as its type argument.
///
/// If no type argument is provided, the canonical raw type is returned.
+ @override // CommonElementsForDartTypes
InterfaceType futureType([DartType elementType]) {
if (elementType == null) {
return _getRawType(futureClass);
@@ -701,6 +707,7 @@
ClassEntity get jsJavaScriptFunctionClass => _jsJavaScriptFunctionClass ??=
_findInterceptorsClass('JavaScriptFunction');
+ @override // CommonElementsForDartTypes
InterfaceType get jsJavaScriptFunctionType =>
_getRawType(jsJavaScriptFunctionClass);
@@ -1567,7 +1574,7 @@
InterfaceType getThisType(ClassEntity cls);
/// Returns the instantiation of [cls] to bounds.
- InterfaceType getClassInstantiationToBounds(ClassEntity cls);
+ InterfaceType /*!*/ getClassInstantiationToBounds(ClassEntity cls);
/// Returns `true` if [cls] is generic.
bool isGenericClass(ClassEntity cls);
@@ -1595,7 +1602,7 @@
FunctionType getLocalFunctionType(Local local);
/// Returns the type of [field].
- DartType getFieldType(FieldEntity field);
+ DartType /*!*/ getFieldType(FieldEntity field);
/// Returns `true` if [cls] is a Dart enum class.
bool isEnumClass(ClassEntity cls);
diff --git a/pkg/compiler/lib/src/elements/entities.dart b/pkg/compiler/lib/src/elements/entities.dart
index 737b529..5a4ac84 100644
--- a/pkg/compiler/lib/src/elements/entities.dart
+++ b/pkg/compiler/lib/src/elements/entities.dart
@@ -245,6 +245,10 @@
// TODO(johnniwinther): Remove factory constructors from the set of
// constructors.
abstract class ConstructorEntity extends FunctionEntity {
+ // Constructors always have an enclosing class.
+ @override
+ ClassEntity get enclosingClass;
+
/// Whether this is a generative constructor, possibly redirecting.
bool get isGenerativeConstructor;
diff --git a/pkg/compiler/lib/src/elements/indexed.dart b/pkg/compiler/lib/src/elements/indexed.dart
index efc5b92..fef7e77 100644
--- a/pkg/compiler/lib/src/elements/indexed.dart
+++ b/pkg/compiler/lib/src/elements/indexed.dart
@@ -241,6 +241,46 @@
return register(entity, data, env);
}
+ void _preRegister<E0 extends E, V0 extends V>(E0 entity, V0 env) {
+ assert(
+ !_closed, "Trying to register $entity @ ${_list.length} when closed.");
+ assert(entity != null);
+ assert(entity._index == null);
+ assert(
+ _list.length == _env.length,
+ 'Env list length ${_env.length} inconsistent '
+ 'with entity list length ${_list.length}.');
+ entity._index = _list.length;
+ _list.add(entity);
+ _size++;
+ assert(env != null);
+ _env.add(env);
+ }
+
+ /// Registers a new [entity] with an associated environment [env] by the given
+ /// [index]. [postRegisterData] should be called with the same [entity] after
+ /// this is called and before any other entity is registered.
+ void preRegisterByIndex<E0 extends E, V0 extends V>(
+ int index, E0 entity, V0 env) {
+ assert(index >= _list.length);
+ _list.length = _data.length = _env.length = index;
+ _preRegister(entity, env);
+ }
+
+ /// Registers an [entity] with an associated [data] object. This should only
+ /// be used if the entity was pre-registered with [preRegisterByIndex].
+ void postRegisterData<E0 extends E, D0 extends D>(E0 entity, D0 data) {
+ assert(
+ !_closed, "Trying to register $entity @ ${_list.length} when closed.");
+ assert(entity != null);
+ assert(
+ (_list.length - 1) == _data.length,
+ 'Data list length ${_data.length} inconsistent '
+ 'with entity list length ${_list.length}.');
+ assert(data != null);
+ _data.add(data);
+ }
+
/// Calls [f] for each non-null entity with its corresponding data object and
/// environment.
void forEach<E0 extends E, D0 extends D, V0 extends V>(
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 27ab75c..6f217cd 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -2,12 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart = 2.10
-
-import '../common/elements.dart';
import '../common/names.dart';
import '../options.dart';
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
import '../util/util.dart' show equalElements, equalSets, identicalElements;
import 'entities.dart';
@@ -39,8 +36,8 @@
}
extension on DataSinkWriter {
- void _writeDartTypes(List<DartType /*!*/ > types,
- List<FunctionTypeVariable /*!*/ > functionTypeVariables) {
+ void _writeDartTypes(
+ List<DartType> types, List<FunctionTypeVariable> functionTypeVariables) {
writeInt(types.length);
for (DartType type in types) {
type.writeToDataSink(this, functionTypeVariables);
@@ -53,12 +50,12 @@
static DartType readFromDataSource(DataSourceReader source,
List<FunctionTypeVariable> functionTypeVariables) {
- DartType type = readFromDataSourceOrNull(source, functionTypeVariables);
+ DartType? type = readFromDataSourceOrNull(source, functionTypeVariables);
if (type == null) throw StateError('Unexpected null DartType');
return type;
}
- static DartType readFromDataSourceOrNull(DataSourceReader source,
+ static DartType? readFromDataSourceOrNull(DataSourceReader source,
List<FunctionTypeVariable> functionTypeVariables) {
DartTypeKind kind = source.readEnum(DartTypeKind.values);
switch (kind) {
@@ -91,11 +88,10 @@
case DartTypeKind.futureOr:
return FutureOrType._readFromDataSource(source, functionTypeVariables);
}
- throw UnsupportedError('Unexpected DartTypeKind $kind');
}
- void writeToDataSink(DataSinkWriter sink,
- List<FunctionTypeVariable /*!*/ > functionTypeVariables);
+ void writeToDataSink(
+ DataSinkWriter sink, List<FunctionTypeVariable> functionTypeVariables);
/// Returns the base type if this is a [LegacyType] or [NullableType] and
/// returns this type otherwise.
@@ -124,12 +120,12 @@
/// Calls the visit method on [visitor] corresponding to this type.
R accept<R, A>(DartTypeVisitor<R, A> visitor, A argument);
- bool _equals(DartType other, _Assumptions assumptions);
+ bool _equals(DartType other, _Assumptions? assumptions);
@override
String toString() => toStructuredText(null, null);
- String toStructuredText(DartTypes dartTypes, CompilerOptions options) =>
+ String toStructuredText(DartTypes? dartTypes, CompilerOptions? options) =>
_DartTypeToStringVisitor(dartTypes, options).run(this);
}
@@ -163,7 +159,7 @@
}
void _removeAssumption(FunctionTypeVariable a, FunctionTypeVariable b) {
- Set<FunctionTypeVariable> set = _assumptionMap[a];
+ Set<FunctionTypeVariable>? set = _assumptionMap[a];
if (set != null) {
set.remove(b);
if (set.isEmpty) {
@@ -209,7 +205,7 @@
}
class LegacyType extends DartType {
- final DartType /*!*/ baseType;
+ final DartType baseType;
const LegacyType._(this.baseType);
@@ -253,18 +249,18 @@
}
@override
- bool _equals(DartType other, _Assumptions assumptions) {
+ 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) =>
+ bool _equalsInternal(LegacyType other, _Assumptions? assumptions) =>
baseType._equals(other.baseType, assumptions);
}
class NullableType extends DartType {
- final DartType /*!*/ baseType;
+ final DartType baseType;
const NullableType._(this.baseType);
@@ -308,23 +304,25 @@
}
@override
- bool _equals(DartType other, _Assumptions assumptions) {
+ 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) =>
+ bool _equalsInternal(NullableType other, _Assumptions? assumptions) =>
baseType._equals(other.baseType, assumptions);
}
class InterfaceType extends DartType {
- final ClassEntity /*!*/ element;
- final List<DartType /*!*/ > typeArguments;
+ final ClassEntity element;
+ final List<DartType> typeArguments;
InterfaceType._allocate(this.element, this.typeArguments);
factory InterfaceType._(ClassEntity element, List<DartType> typeArguments) {
+ // TODO(48820): Remove:
+ // ignore: unnecessary_null_comparison
assert(typeArguments.every((e) => e != null));
if (typeArguments.isEmpty) typeArguments = const [];
return InterfaceType._allocate(element, typeArguments);
@@ -371,8 +369,7 @@
int get hashCode {
int hash = element.hashCode;
for (DartType argument in typeArguments) {
- int argumentHash = argument != null ? argument.hashCode : 0;
- hash = 17 * hash + 3 * argumentHash;
+ hash = 17 * hash + 3 * argument.hashCode;
}
return hash;
}
@@ -385,13 +382,13 @@
}
@override
- bool _equals(DartType other, _Assumptions assumptions) {
+ bool _equals(DartType other, _Assumptions? assumptions) {
if (identical(this, other)) return true;
if (other is! InterfaceType) return false;
return _equalsInternal(other, assumptions);
}
- bool _equalsInternal(InterfaceType other, _Assumptions assumptions) {
+ bool _equalsInternal(InterfaceType other, _Assumptions? assumptions) {
return identical(element, other.element) &&
_equalTypes(typeArguments, other.typeArguments, assumptions);
}
@@ -436,7 +433,7 @@
other is TypeVariableType && identical(other.element, element);
@override
- bool _equals(DartType other, _Assumptions assumptions) => this == other;
+ bool _equals(DartType other, _Assumptions? assumptions) => this == other;
}
/// A type variable declared on a function type.
@@ -454,7 +451,8 @@
final int index;
/// The bound of this function type variable.
- DartType _bound;
+ // TODO(48820): `bound` getter/setter can be a late final field.
+ DartType? _bound;
FunctionTypeVariable._(this.index);
@@ -478,9 +476,9 @@
}
}
- DartType /*!*/ get bound {
+ DartType get bound {
assert(_bound != null, "Bound has not been set.");
- return _bound;
+ return _bound!;
}
void set bound(DartType value) {
@@ -492,7 +490,7 @@
int get hashCode => index * 113; // ignore bound which can have cycles.
@override
- bool _equals(DartType other, _Assumptions assumptions) {
+ bool _equals(DartType other, _Assumptions? assumptions) {
if (identical(this, other)) return true;
if (other is! FunctionTypeVariable) return false;
if (assumptions != null) return assumptions.isAssumed(this, other);
@@ -529,7 +527,7 @@
bool operator ==(other) => identical(this, other) || other is NeverType;
@override
- bool _equals(DartType other, _Assumptions assumptions) => this == other;
+ bool _equals(DartType other, _Assumptions? assumptions) => this == other;
}
class VoidType extends DartType {
@@ -556,7 +554,7 @@
bool operator ==(other) => identical(this, other) || other is VoidType;
@override
- bool _equals(DartType other, _Assumptions assumptions) => this == other;
+ bool _equals(DartType other, _Assumptions? assumptions) => this == other;
}
class DynamicType extends DartType {
@@ -583,7 +581,7 @@
bool operator ==(other) => identical(this, other) || other is DynamicType;
@override
- bool _equals(DartType other, _Assumptions assumptions) => this == other;
+ bool _equals(DartType other, _Assumptions? assumptions) => this == other;
}
class ErasedType extends DartType {
@@ -610,7 +608,7 @@
bool operator ==(other) => identical(this, other) || other is ErasedType;
@override
- bool _equals(DartType other, _Assumptions assumptions) => this == other;
+ bool _equals(DartType other, _Assumptions? assumptions) => this == other;
}
/// Represents a type which is simultaneously top and bottom.
@@ -648,13 +646,13 @@
bool operator ==(other) => identical(this, other) || other is AnyType;
@override
- bool _equals(DartType other, _Assumptions assumptions) => this == other;
+ bool _equals(DartType other, _Assumptions? assumptions) => this == other;
}
class FunctionType extends DartType {
final DartType returnType;
- final List<DartType /*!*/ > parameterTypes;
- final List<DartType /*!*/ > optionalParameterTypes;
+ final List<DartType> parameterTypes;
+ final List<DartType> optionalParameterTypes;
/// The names of all named parameters ordered lexicographically.
final List<String> namedParameters;
@@ -664,9 +662,9 @@
/// The types of the named parameters in the order corresponding to the
/// [namedParameters].
- final List<DartType /*!*/ > namedParameterTypes;
+ final List<DartType> namedParameterTypes;
- final List<FunctionTypeVariable /*!*/ > typeVariables;
+ final List<FunctionTypeVariable> typeVariables;
FunctionType._allocate(
this.returnType,
@@ -676,6 +674,8 @@
this.requiredNamedParameters,
this.namedParameterTypes,
this.typeVariables) {
+ // TODO(48820): Remove:
+ // ignore: unnecessary_null_comparison
assert(returnType != null, 'Invalid return type in $this.');
assert(!parameterTypes.contains(null), 'Invalid parameter types in $this.');
assert(!optionalParameterTypes.contains(null),
@@ -691,12 +691,12 @@
factory FunctionType._(
DartType returnType,
- List<DartType /*!*/ > parameterTypes,
- List<DartType /*!*/ > optionalParameterTypes,
- List<String /*!*/ > namedParameters,
- Set<String /*!*/ > requiredNamedParameters,
- List<DartType /*!*/ > namedParameterTypes,
- List<FunctionTypeVariable /*!*/ > typeVariables) {
+ List<DartType> parameterTypes,
+ List<DartType> optionalParameterTypes,
+ List<String> namedParameters,
+ Set<String> requiredNamedParameters,
+ List<DartType> namedParameterTypes,
+ List<FunctionTypeVariable> typeVariables) {
// Canonicalize empty collections to constants to save storage.
if (parameterTypes.isEmpty) parameterTypes = const [];
if (optionalParameterTypes.isEmpty) optionalParameterTypes = const [];
@@ -823,13 +823,13 @@
}
@override
- bool _equals(DartType other, _Assumptions assumptions) {
+ bool _equals(DartType other, _Assumptions? assumptions) {
if (identical(this, other)) return true;
if (other is! FunctionType) return false;
return _equalsInternal(other, assumptions);
}
- bool _equalsInternal(FunctionType other, _Assumptions assumptions) {
+ bool _equalsInternal(FunctionType other, _Assumptions? assumptions) {
if (typeVariables.length != other.typeVariables.length) return false;
assumptions ??= _Assumptions();
assumptions.assumePairs(typeVariables, other.typeVariables);
@@ -856,7 +856,7 @@
}
class FutureOrType extends DartType {
- final DartType /*!*/ typeArgument;
+ final DartType typeArgument;
const FutureOrType._(this.typeArgument);
@@ -897,18 +897,19 @@
}
@override
- bool _equals(DartType other, _Assumptions assumptions) {
+ bool _equals(DartType other, _Assumptions? assumptions) {
if (identical(this, other)) return true;
if (other is! FutureOrType) return false;
return _equalsInternal(other, assumptions);
}
- bool _equalsInternal(FutureOrType other, _Assumptions assumptions) {
+ bool _equalsInternal(FutureOrType other, _Assumptions? assumptions) {
return typeArgument._equals(other.typeArgument, assumptions);
}
}
-bool _equalTypes(List<DartType> a, List<DartType> b, _Assumptions assumptions) {
+bool _equalTypes(
+ List<DartType> a, List<DartType> b, _Assumptions? assumptions) {
if (a.length != b.length) return false;
for (int index = 0; index < a.length; index++) {
if (!a[index]._equals(b[index], assumptions)) {
@@ -921,36 +922,34 @@
abstract class DartTypeVisitor<R, A> {
const DartTypeVisitor();
- R /*!*/ visit(covariant DartType type, A argument) =>
- type.accept(this, argument);
+ R visit(covariant DartType type, A argument) => type.accept(this, argument);
- R /*!*/ visitLegacyType(covariant LegacyType type, A argument);
+ R visitLegacyType(covariant LegacyType type, A argument);
- R /*!*/ visitNullableType(covariant NullableType type, A argument);
+ R visitNullableType(covariant NullableType type, A argument);
- R /*!*/ visitNeverType(covariant NeverType type, A argument);
+ R visitNeverType(covariant NeverType type, A argument);
- R /*!*/ visitVoidType(covariant VoidType type, A argument);
+ R visitVoidType(covariant VoidType type, A argument);
- R /*!*/ visitTypeVariableType(covariant TypeVariableType type, A argument);
+ R visitTypeVariableType(covariant TypeVariableType type, A argument);
- R /*!*/ visitFunctionTypeVariable(
- covariant FunctionTypeVariable type, A argument);
+ R visitFunctionTypeVariable(covariant FunctionTypeVariable type, A argument);
- R /*!*/ visitFunctionType(covariant FunctionType type, A argument);
+ R visitFunctionType(covariant FunctionType type, A argument);
- R /*!*/ visitInterfaceType(covariant InterfaceType type, A argument);
+ R visitInterfaceType(covariant InterfaceType type, A argument);
- R /*!*/ visitDynamicType(covariant DynamicType type, A argument);
+ R visitDynamicType(covariant DynamicType type, A argument);
- R /*!*/ visitErasedType(covariant ErasedType type, A argument);
+ R visitErasedType(covariant ErasedType type, A argument);
- R /*!*/ visitAnyType(covariant AnyType type, A argument);
+ R visitAnyType(covariant AnyType type, A argument);
- R /*!*/ visitFutureOrType(covariant FutureOrType type, A argument);
+ R visitFutureOrType(covariant FutureOrType type, A argument);
}
-class _LegacyErasureVisitor extends DartTypeVisitor<DartType /*!*/, Null> {
+class _LegacyErasureVisitor extends DartTypeVisitor<DartType, Null> {
final DartTypes _dartTypes;
_LegacyErasureVisitor(this._dartTypes);
@@ -1024,6 +1023,7 @@
identical(namedParameterTypes, type.namedParameterTypes) &&
erasableTypeVariables.isEmpty) return type;
+ // TODO(48820): Can we avoid the cast?
return _dartTypes.subst(
erasedTypeVariables,
erasableTypeVariables,
@@ -1034,7 +1034,7 @@
type.namedParameters,
type.requiredNamedParameters,
namedParameterTypes,
- typeVariables));
+ typeVariables)) as FunctionType;
}
@override
@@ -1062,13 +1062,13 @@
}
abstract class DartTypeSubstitutionVisitor<A>
- extends DartTypeVisitor<DartType /*!*/, A> {
+ extends DartTypeVisitor<DartType, A> {
DartTypes get dartTypes;
// The input type is a DAG and we must preserve the sharing.
final Map<DartType, DartType> _map = Map.identity();
- DartType _mapped(DartType oldType, DartType /*!*/ newType) {
+ DartType _mapped(DartType oldType, DartType newType) {
assert(_map[oldType] == null);
return _map[oldType] = newType;
}
@@ -1093,7 +1093,7 @@
@override
DartType visitLegacyType(covariant LegacyType type, A argument) {
- DartType probe = _map[type];
+ DartType? probe = _map[type];
if (probe != null) return probe;
DartType newBaseType = visit(type.baseType, argument);
@@ -1106,7 +1106,7 @@
@override
DartType visitNullableType(covariant NullableType type, A argument) {
- DartType probe = _map[type];
+ DartType? probe = _map[type];
if (probe != null) return probe;
DartType newBaseType = visit(type.baseType, argument);
@@ -1130,7 +1130,7 @@
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 probe = _map[type];
+ DartType? probe = _map[type];
if (probe != null) return probe;
return substituteFunctionTypeVariable(type, argument, true);
}
@@ -1140,7 +1140,7 @@
@override
DartType visitFunctionType(covariant FunctionType type, A argument) {
- DartType probe = _map[type];
+ DartType? probe = _map[type];
if (probe != null) return probe;
List<FunctionTypeVariable> newTypeVariables =
@@ -1190,9 +1190,8 @@
// indirectly changed by the substitution of F. When D is replaced by `D2
// extends Map<B,G>`, C must be replaced by `C2 extends D2`.
- List<FunctionTypeVariable /*?*/ > undecided =
- List.of(variables, growable: false);
- List<FunctionTypeVariable> newVariables;
+ List<FunctionTypeVariable?> undecided = List.of(variables, growable: false);
+ List<FunctionTypeVariable>? newVariables;
_DependencyCheck<A> dependencyCheck = _DependencyCheck<A>(this, argument);
@@ -1200,7 +1199,7 @@
while (changed) {
changed = false;
for (int i = 0; i < undecided.length; i++) {
- FunctionTypeVariable variable = undecided[i];
+ FunctionTypeVariable? variable = undecided[i];
if (variable == null) continue;
if (dependencyCheck.run(variable.bound)) {
changed = true;
@@ -1233,7 +1232,7 @@
return type;
}
- DartType probe = _map[type];
+ DartType? probe = _map[type];
if (probe != null) return probe;
List<DartType> newTypeArguments = _substTypes(typeArguments, argument);
@@ -1256,7 +1255,7 @@
@override
DartType visitFutureOrType(covariant FutureOrType type, A argument) {
- DartType probe = _map[type];
+ DartType? probe = _map[type];
if (probe != null) return probe;
DartType newTypeArgument = visit(type.typeArgument, argument);
@@ -1268,7 +1267,7 @@
}
List<DartType> _substTypes(List<DartType> types, A argument) {
- List<DartType> result;
+ List<DartType>? result;
for (int i = 0; i < types.length; i++) {
DartType oldType = types[i];
DartType newType = visit(oldType, argument);
@@ -1297,7 +1296,7 @@
bool handleFreeFunctionTypeVariable(FunctionTypeVariable type) {
// Function type variables are added to the map for type variables that need
// to be replaced with updated bounds.
- DartType probe = _substitutionVisitor._map[type];
+ DartType? probe = _substitutionVisitor._map[type];
if (probe != null) return probe != type;
return !identical(
type,
@@ -1310,7 +1309,7 @@
/// visit returns `true`. The default handlers return `false` which will search
/// the whole structure unless overridden.
abstract class DartTypeStructuralPredicateVisitor
- extends DartTypeVisitor<bool, List<FunctionTypeVariable> /*?*/ > {
+ extends DartTypeVisitor<bool, List<FunctionTypeVariable>?> {
const DartTypeStructuralPredicateVisitor();
bool run(DartType type) => visit(type, null);
@@ -1330,30 +1329,30 @@
bool handleFutureOrType(FutureOrType type) => false;
@override
- bool visitLegacyType(LegacyType type, List<FunctionTypeVariable> bindings) =>
+ bool visitLegacyType(LegacyType type, List<FunctionTypeVariable>? bindings) =>
handleLegacyType(type) || visit(type.baseType, bindings);
@override
bool visitNullableType(
- NullableType type, List<FunctionTypeVariable> bindings) =>
+ NullableType type, List<FunctionTypeVariable>? bindings) =>
handleNullableType(type) || visit(type.baseType, bindings);
@override
- bool visitNeverType(NeverType type, List<FunctionTypeVariable> bindings) =>
+ bool visitNeverType(NeverType type, List<FunctionTypeVariable>? bindings) =>
handleNeverType(type);
@override
- bool visitVoidType(VoidType type, List<FunctionTypeVariable> bindings) =>
+ bool visitVoidType(VoidType type, List<FunctionTypeVariable>? bindings) =>
handleVoidType(type);
@override
bool visitTypeVariableType(
- TypeVariableType type, List<FunctionTypeVariable> bindings) =>
+ TypeVariableType type, List<FunctionTypeVariable>? bindings) =>
handleTypeVariableType(type);
@override
bool visitFunctionTypeVariable(
- FunctionTypeVariable type, List<FunctionTypeVariable> bindings) {
+ FunctionTypeVariable type, List<FunctionTypeVariable>? bindings) {
return bindings != null && bindings.indexOf(type) >= 0
? handleBoundFunctionTypeVariable(type)
: handleFreeFunctionTypeVariable(type);
@@ -1361,7 +1360,7 @@
@override
bool visitFunctionType(
- FunctionType type, List<FunctionTypeVariable> bindings) {
+ FunctionType type, List<FunctionTypeVariable>? bindings) {
if (handleFunctionType(type)) return true;
List<FunctionTypeVariable> typeVariables = type.typeVariables;
if (typeVariables.isNotEmpty) {
@@ -1383,32 +1382,32 @@
@override
bool visitInterfaceType(
- InterfaceType type, List<FunctionTypeVariable> bindings) {
+ InterfaceType type, List<FunctionTypeVariable>? bindings) {
if (handleInterfaceType(type)) return true;
return _visitAll(type.typeArguments, bindings);
}
@override
bool visitDynamicType(
- DynamicType type, List<FunctionTypeVariable> bindings) =>
+ DynamicType type, List<FunctionTypeVariable>? bindings) =>
handleDynamicType(type);
@override
- bool visitErasedType(ErasedType type, List<FunctionTypeVariable> bindings) =>
+ bool visitErasedType(ErasedType type, List<FunctionTypeVariable>? bindings) =>
handleErasedType(type);
@override
- bool visitAnyType(AnyType type, List<FunctionTypeVariable> bindings) =>
+ bool visitAnyType(AnyType type, List<FunctionTypeVariable>? bindings) =>
handleAnyType(type);
@override
bool visitFutureOrType(
- FutureOrType type, List<FunctionTypeVariable> bindings) {
+ FutureOrType type, List<FunctionTypeVariable>? bindings) {
if (handleFutureOrType(type)) return true;
return visit(type.typeArgument, bindings);
}
- bool _visitAll(List<DartType> types, List<FunctionTypeVariable> bindings) {
+ bool _visitAll(List<DartType> types, List<FunctionTypeVariable>? bindings) {
for (DartType type in types) {
if (visit(type, bindings)) return true;
}
@@ -1461,33 +1460,36 @@
}
class _DeferredName {
- String name;
+ String? name;
_DeferredName();
@override
- String toString() => name;
+ String toString() => name!;
}
class _DartTypeToStringVisitor extends DartTypeVisitor<void, void> {
- final DartTypes _dartTypes; // May be null.
- final CompilerOptions _options; // May be null.
+ final DartTypes? _dartTypes; // May be null.
+ final CompilerOptions? _options; // May be null.
final List _fragments = []; // Strings and _DeferredNames
bool _lastIsIdentifier = false;
- List<FunctionTypeVariable> _boundVariables;
- Map<FunctionTypeVariable, _DeferredName> _variableToName;
- Set<FunctionType> _genericFunctions;
+ List<FunctionTypeVariable>? _boundVariables;
+ Map<FunctionTypeVariable, _DeferredName>? _variableToName;
+ Set<FunctionType>? _genericFunctions;
_DartTypeToStringVisitor(this._dartTypes, this._options);
String run(DartType type) {
_visit(type);
- if (_variableToName != null &&
- _variableToName.values.any((deferred) => deferred.name == null)) {
+ final variableToName = _variableToName;
+ if (variableToName != null &&
+ variableToName.values.any((deferred) => deferred.name == null)) {
// Assign names to _DeferredNames that were not assigned while visiting a
// generic function type.
- Set<String> usedNames =
- _variableToName.values.map((deferred) => deferred.name).toSet();
+ Set<String> usedNames = {
+ for (final deferred in variableToName.values)
+ if (deferred.name != null) deferred.name!
+ };
int startGroup = (_genericFunctions?.length ?? 0) + 1;
- for (var entry in _variableToName.entries) {
+ for (var entry in variableToName.entries) {
if (entry.value.name != null) continue;
for (int group = startGroup;; group++) {
String name = _functionTypeVariableName(entry.key, group);
@@ -1539,7 +1541,7 @@
// internal notion. The language specification does not define a '*' token
// in the type language, and no such token should be surfaced to users.
// For debugging, pass `--debug-print-legacy-stars` to emit the '*'.
- if (_options == null || _options.printLegacyStars) {
+ if (_options == null || _options!.printLegacyStars) {
_token('*');
}
}
@@ -1577,14 +1579,14 @@
@override
void visitTypeVariableType(covariant TypeVariableType type, _) {
- _identifier(type.element.typeDeclaration.name);
+ _identifier(type.element.typeDeclaration!.name!);
_token('.');
- _identifier(type.element.name);
+ _identifier(type.element.name!);
}
_DeferredName _nameFor(FunctionTypeVariable type) {
_variableToName ??= Map.identity();
- return _variableToName[type] ??= _DeferredName();
+ return _variableToName![type] ??= _DeferredName();
}
@override
@@ -1594,7 +1596,7 @@
// A3, etc).
_token('#');
_deferredNameIdentifier(_nameFor(type));
- if (_boundVariables == null || !_boundVariables.contains(type)) {
+ if (_boundVariables == null || !_boundVariables!.contains(type)) {
_token('/*free*/');
}
}
@@ -1603,13 +1605,12 @@
void visitFunctionType(covariant FunctionType type, _) {
if (type.typeVariables.isNotEmpty) {
// Enter function type variable scope.
- _boundVariables ??= [];
- _boundVariables.addAll(type.typeVariables);
+ (_boundVariables ??= []).addAll(type.typeVariables);
// Assign names for the function type variables. We could have already
// assigned names for this node if we are printing a DAG.
- _genericFunctions ??= Set.identity();
- if (_genericFunctions.add(type)) {
- int group = _genericFunctions.length;
+ final genericFunctions = _genericFunctions ??= Set.identity();
+ if (genericFunctions.add(type)) {
+ int group = genericFunctions.length;
for (FunctionTypeVariable variable in type.typeVariables) {
_DeferredName deferredName = _nameFor(variable);
// If there is a structural error where one FunctionTypeVariable is
@@ -1628,7 +1629,7 @@
needsComma = _comma(needsComma);
_visit(typeVariable);
DartType bound = typeVariable.bound;
- if (_dartTypes == null || !_dartTypes.isTopType(bound)) {
+ if (_dartTypes == null || !_dartTypes!.isTopType(bound)) {
_token(' extends ');
_visit(bound);
}
@@ -1695,17 +1696,29 @@
}
}
+/// The subset of CommonElements methods needed for DartTypes.
+// TODO(48820): Replace with CommonElements once that is migrated.
+abstract class CommonElementsForDartTypes {
+ InterfaceType get nullType;
+ InterfaceType get intType;
+ InterfaceType get doubleType;
+ InterfaceType get functionType;
+ InterfaceType get objectType;
+ InterfaceType get jsJavaScriptFunctionType;
+ InterfaceType futureType(DartType elementType);
+}
+
/// Basic interface for the Dart type system.
abstract class DartTypes {
/// The types defined in 'dart:core'.
- CommonElements get commonElements;
+ CommonElementsForDartTypes get commonElements;
bool get useLegacySubtyping;
DartType bottomType() =>
useLegacySubtyping ? commonElements.nullType : neverType();
- DartType legacyType(DartType /*!*/ baseType) {
+ DartType legacyType(DartType baseType) {
DartType result;
if (isStrongTopType(baseType) ||
baseType.isNull ||
@@ -1718,7 +1731,7 @@
return result;
}
- DartType nullableType(DartType /*!*/ baseType) {
+ DartType nullableType(DartType baseType) {
bool _isNullable(DartType t) =>
// Note that we can assume null safety is enabled here.
t.isNull ||
@@ -1752,7 +1765,7 @@
}
InterfaceType interfaceType(
- ClassEntity element, List<DartType /*!*/ > typeArguments) =>
+ ClassEntity element, List<DartType> typeArguments) =>
InterfaceType._(element, typeArguments);
// TODO(fishythefish): Normalize `T extends Never` to `Never`.
@@ -1775,12 +1788,12 @@
FunctionType functionType(
DartType returnType,
- List<DartType /*!*/ > parameterTypes,
- List<DartType /*!*/ > optionalParameterTypes,
+ List<DartType> parameterTypes,
+ List<DartType> optionalParameterTypes,
List<String> namedParameters,
Set<String> requiredNamedParameters,
- List<DartType /*!*/ > namedParameterTypes,
- List<FunctionTypeVariable /*!*/ > typeVariables) {
+ List<DartType> namedParameterTypes,
+ List<FunctionTypeVariable> typeVariables) {
FunctionType type = FunctionType._(
returnType,
parameterTypes,
@@ -1797,7 +1810,7 @@
: subst(
List<DartType>.filled(normalizableVariables.length, neverType()),
normalizableVariables,
- type);
+ type) as FunctionType;
}
DartType futureOrType(DartType typeArgument) {
@@ -1914,7 +1927,7 @@
/// Based on
/// https://github.com/dart-lang/language/blob/master/resources/type-system/subtyping.md.
/// See also [_isSubtype] in `dart:_rti`.
- bool _isSubtype(DartType s, DartType t, _Assumptions env) {
+ bool _isSubtype(DartType s, DartType t, _Assumptions? env) {
// Reflexivity:
if (s == t) return true;
if (env != null &&
@@ -1938,7 +1951,7 @@
if (_isSubtype(getTypeVariableBound(s.element), t, env)) return true;
}
if (s is FunctionTypeVariable) {
- if (_isSubtype(s._bound, t, env)) return true;
+ if (_isSubtype(s.bound, t, env)) return true;
}
// Left Null:
@@ -2137,7 +2150,7 @@
// Interface Compositionality + Super-Interface:
if (s is InterfaceType) {
if (t is InterfaceType) {
- InterfaceType instance =
+ InterfaceType? instance =
s.element == t.element ? s : asInstanceOf(s, t.element);
if (instance == null) return false;
List<DartType> sArgs = instance.typeArguments;
@@ -2178,7 +2191,7 @@
/// subtype of [cls].
///
/// For example: `asInstanceOf(List<String>, Iterable) = Iterable<String>`.
- InterfaceType asInstanceOf(InterfaceType type, ClassEntity cls);
+ InterfaceType? asInstanceOf(InterfaceType type, ClassEntity cls);
/// Return [base] where the type variable of `context.element` are replaced
/// by the type arguments of [context].
@@ -2195,7 +2208,7 @@
/// Returns the supertype of [cls], i.e. the type in the `extends` clause of
/// [cls].
- InterfaceType getSupertype(ClassEntity cls);
+ InterfaceType? getSupertype(ClassEntity cls);
/// Returns all supertypes of [cls].
// TODO(johnniwinther): This should include `Function` if [cls] declares
@@ -2207,7 +2220,7 @@
/// Returns the type of the `call` method on [type], or `null` if the class
/// of [type] does not have a `call` method.
- FunctionType getCallType(InterfaceType type);
+ FunctionType? getCallType(InterfaceType type);
/// Checks the type arguments of [type] against the type variable bounds
/// declared on `type.element`. Calls [checkTypeVariableBound] on each type
@@ -2221,11 +2234,12 @@
/// Returns the [ClassEntity] which declares the type variables occurring in
// [type], or `null` if [type] does not contain class type variables.
- static ClassEntity getClassContext(DartType type) {
- ClassEntity contextClass;
+ static ClassEntity? getClassContext(DartType type) {
+ ClassEntity? contextClass;
type.forEachTypeVariable((TypeVariableType typeVariable) {
- if (typeVariable.element.typeDeclaration is! ClassEntity) return;
- contextClass = typeVariable.element.typeDeclaration;
+ final typeDeclaration = typeVariable.element.typeDeclaration;
+ if (typeDeclaration is! ClassEntity) return;
+ contextClass = typeDeclaration;
});
// GENERIC_METHODS: When generic method support is complete enough to
// include a runtime value for method type variables this must be updated.
@@ -2268,7 +2282,7 @@
/// Returns `true` if [type] occuring in a program with no sound null safety
/// cannot accept `null` under sound rules.
- bool isNonNullableIfSound(DartType /*!*/ type) {
+ bool isNonNullableIfSound(DartType type) {
if (type is DynamicType ||
type is VoidType ||
type is AnyType ||
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index e2d23d2..39ee49c 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -1361,21 +1361,18 @@
AbstractValueDomain abstractValueDomain) {
return source.inMemberContext(context, () {
source.begin(tag);
- Map<ir.TreeNode, AbstractValue> sendMap = source.readTreeNodeMapInContext(
- () => abstractValueDomain.readAbstractValueFromDataSource(source),
- emptyAsNull: true);
+ Map<ir.TreeNode, AbstractValue> sendMap =
+ source.readTreeNodeMapInContextOrNull(() =>
+ abstractValueDomain.readAbstractValueFromDataSource(source));
Map<ir.ForInStatement, AbstractValue> iteratorMap =
- source.readTreeNodeMapInContext(
- () => abstractValueDomain.readAbstractValueFromDataSource(source),
- emptyAsNull: true);
+ source.readTreeNodeMapInContextOrNull(() =>
+ abstractValueDomain.readAbstractValueFromDataSource(source));
Map<ir.ForInStatement, AbstractValue> currentMap =
- source.readTreeNodeMapInContext(
- () => abstractValueDomain.readAbstractValueFromDataSource(source),
- emptyAsNull: true);
+ source.readTreeNodeMapInContextOrNull(() =>
+ abstractValueDomain.readAbstractValueFromDataSource(source));
Map<ir.ForInStatement, AbstractValue> moveNextMap =
- source.readTreeNodeMapInContext(
- () => abstractValueDomain.readAbstractValueFromDataSource(source),
- emptyAsNull: true);
+ source.readTreeNodeMapInContextOrNull(() =>
+ abstractValueDomain.readAbstractValueFromDataSource(source));
source.end(tag);
return KernelGlobalTypeInferenceElementData.internal(
sendMap, iteratorMap, currentMap, moveNextMap);
diff --git a/pkg/compiler/lib/src/ir/element_map.dart b/pkg/compiler/lib/src/ir/element_map.dart
index 6d8c86a..51f1e6f 100644
--- a/pkg/compiler/lib/src/ir/element_map.dart
+++ b/pkg/compiler/lib/src/ir/element_map.dart
@@ -57,14 +57,14 @@
CommonElements /*!*/ get commonElements;
DiagnosticReporter get reporter;
ir.CoreTypes get coreTypes;
- InterfaceType getThisType(IndexedClass cls);
- InterfaceType getSuperType(IndexedClass cls);
- OrderedTypeSet getOrderedTypeSet(IndexedClass cls);
- Iterable<InterfaceType> getInterfaces(IndexedClass cls);
+ InterfaceType /*!*/ getThisType(covariant ClassEntity cls);
+ InterfaceType getSuperType(covariant ClassEntity cls);
+ OrderedTypeSet getOrderedTypeSet(covariant ClassEntity cls);
+ Iterable<InterfaceType> getInterfaces(covariant ClassEntity cls);
InterfaceType asInstanceOf(InterfaceType type, ClassEntity cls);
DartType substByContext(DartType type, InterfaceType context);
FunctionType getCallType(InterfaceType type);
- int getHierarchyDepth(IndexedClass cls);
+ int getHierarchyDepth(covariant ClassEntity cls);
DartType getTypeVariableBound(IndexedTypeVariable typeVariable);
- List<Variance> getTypeVariableVariances(IndexedClass cls);
+ List<Variance> getTypeVariableVariances(covariant ClassEntity cls);
}
diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart
index 462b6c3..38886b0 100644
--- a/pkg/compiler/lib/src/ir/impact_data.dart
+++ b/pkg/compiler/lib/src/ir/impact_data.dart
@@ -2122,7 +2122,7 @@
source.begin(tag);
RuntimeTypeUseKind kind = source.readEnum(RuntimeTypeUseKind.values);
ir.DartType receiverType = source.readDartTypeNode();
- ir.DartType argumentType = source.readDartTypeNode(allowNull: true);
+ ir.DartType argumentType = source.readDartTypeNodeOrNull();
source.end(tag);
return _RuntimeTypeUse(kind, receiverType, argumentType);
}
@@ -2131,7 +2131,7 @@
sink.begin(tag);
sink.writeEnum(kind);
sink.writeDartTypeNode(receiverType);
- sink.writeDartTypeNode(argumentType, allowNull: true);
+ sink.writeDartTypeNodeOrNull(argumentType);
sink.end(tag);
}
}
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 35f8fee..4d1e7f4 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -826,9 +826,10 @@
@override
EvaluationComplexity visitFunctionNode(ir.FunctionNode node) {
- VariableUse parameterUsage = node.parent is ir.Member
- ? VariableUse.memberParameter(node.parent)
- : VariableUse.localParameter(node.parent);
+ final parent = node.parent;
+ VariableUse parameterUsage = parent is ir.Member
+ ? VariableUse.memberParameter(parent)
+ : VariableUse.localParameter(parent);
visitNodesInContext(node.typeParameters, parameterUsage);
for (ir.VariableDeclaration declaration in node.positionalParameters) {
_handleVariableDeclaration(declaration, parameterUsage);
@@ -838,9 +839,9 @@
}
visitInContext(
node.returnType,
- node.parent is ir.Member
- ? VariableUse.memberReturnType(node.parent)
- : VariableUse.localReturnType(node.parent));
+ parent is ir.Member
+ ? VariableUse.memberReturnType(parent)
+ : VariableUse.localReturnType(parent));
if (node.body != null) {
visitNode(node.body);
}
diff --git a/pkg/compiler/lib/src/ir/static_type_cache.dart b/pkg/compiler/lib/src/ir/static_type_cache.dart
index 32d2384..92e0023 100644
--- a/pkg/compiler/lib/src/ir/static_type_cache.dart
+++ b/pkg/compiler/lib/src/ir/static_type_cache.dart
@@ -2,17 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart = 2.10
-
import 'package:kernel/ast.dart' as ir;
-import '../serialization/serialization.dart';
+import '../serialization/serialization_interfaces.dart';
class StaticTypeCache {
static const String tag = 'static-type-cache';
final Map<ir.Expression, ir.DartType> _expressionTypes;
- final Map<ir.ForInStatement, ir.DartType> _forInIteratorTypes;
+ final Map<ir.ForInStatement, ir.DartType>? _forInIteratorTypes;
const StaticTypeCache(
[this._expressionTypes = const {}, this._forInIteratorTypes]);
@@ -23,8 +21,8 @@
source.begin(tag);
Map<ir.Expression, ir.DartType> expressionTypes =
source.readTreeNodeMapInContext(source.readDartTypeNode);
- Map<ir.ForInStatement, ir.DartType> forInIteratorTypes = source
- .readTreeNodeMapInContext(source.readDartTypeNode, emptyAsNull: true);
+ Map<ir.ForInStatement, ir.DartType>? forInIteratorTypes =
+ source.readTreeNodeMapInContextOrNull(source.readDartTypeNode);
source.end(tag);
return StaticTypeCache(expressionTypes, forInIteratorTypes);
});
@@ -41,9 +39,9 @@
});
}
- ir.DartType operator [](ir.Expression node) => _expressionTypes[node];
+ ir.DartType? operator [](ir.Expression node) => _expressionTypes[node];
- ir.DartType getForInIteratorType(ir.ForInStatement node) {
- return _forInIteratorTypes != null ? _forInIteratorTypes[node] : null;
+ ir.DartType? getForInIteratorType(ir.ForInStatement node) {
+ return _forInIteratorTypes?[node];
}
}
diff --git a/pkg/compiler/lib/src/ir/types.dart b/pkg/compiler/lib/src/ir/types.dart
index 4242166..a14ddbb 100644
--- a/pkg/compiler/lib/src/ir/types.dart
+++ b/pkg/compiler/lib/src/ir/types.dart
@@ -33,7 +33,7 @@
@override
Iterable<InterfaceType> getSupertypes(ClassEntity cls) {
- return elementMap.getOrderedTypeSet(cls).supertypes;
+ return elementMap.getOrderedTypeSet(cls).supertypes ?? const [];
}
@override
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index d0cd046..e4f6701 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -57,7 +57,9 @@
DartTypes get _dartTypes => _closedWorld.dartTypes;
- void onIsCheckForCodegen(DartType type, TransformedWorldImpact transformed) {
+ void onIsCheckForCodegen(
+ DartType /*!*/ type, TransformedWorldImpact transformed) {
+ assert((type as dynamic) != null);
if (_dartTypes.isTopType(type)) return;
_impacts.typeCheck.registerImpact(transformed, _elementEnvironment);
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 5e14de3..96d0951 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -482,10 +482,11 @@
void _propagateTests() {
void processTypeVariableType(TypeVariableType type) {
TypeVariableEntity variable = type.element;
- if (variable.typeDeclaration is ClassEntity) {
- _getClassNode(variable.typeDeclaration).markTest();
+ final typeDeclaration = variable.typeDeclaration;
+ if (typeDeclaration is ClassEntity) {
+ _getClassNode(typeDeclaration).markTest();
} else {
- _getMethodNode(variable.typeDeclaration).markTest();
+ _getMethodNode(typeDeclaration).markTest();
}
}
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 ee8f10c..6cbb34b 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -358,8 +358,10 @@
source.begin(classDataTag);
entityLookup.forEachClass((int index, JClass cls) {
JClassEnv env = JClassEnv.readFromDataSource(source);
+ classes.preRegisterByIndex(index, cls, env);
JClassData data = JClassData.readFromDataSource(source);
- classMap[env.cls] = classes.registerByIndex(index, cls, data, env);
+ classes.postRegisterData(cls, data);
+ classMap[env.cls] = cls;
if (cls is! JRecord && cls is! JClosureClass) {
// Synthesized classes are not part of the library environment.
libraries.getEnv(cls.library).registerClass(cls.name, env);
@@ -1130,7 +1132,7 @@
assert(checkFamily(cls));
JClassData data = classes.getData(cls);
_ensureSupertypes(cls, data);
- return data.interfaces;
+ return data.interfaces /*!*/;
}
MemberDefinition getMemberDefinitionInternal(covariant IndexedMember member) {
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index c59e85e..a3a0c0c 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -673,7 +673,8 @@
return data.getFunctionType(this);
}
- List<TypeVariableType> _getFunctionTypeVariables(IndexedFunction function) {
+ List<TypeVariableType> /*!*/ _getFunctionTypeVariables(
+ IndexedFunction function) {
assert(checkFamily(function));
KFunctionData data = members.getData(function);
return data.getFunctionTypeVariables(this);
@@ -786,7 +787,7 @@
}
@override
- OrderedTypeSet getOrderedTypeSet(IndexedClass cls) {
+ OrderedTypeSet /*!*/ getOrderedTypeSet(IndexedClass cls) {
assert(checkFamily(cls));
KClassData data = classes.getData(cls);
_ensureSupertypes(cls, data);
@@ -808,10 +809,11 @@
}
@override
- Iterable<InterfaceType> getInterfaces(IndexedClass cls) {
+ Iterable<InterfaceType> /*!*/ getInterfaces(IndexedClass cls) {
assert(checkFamily(cls));
KClassData data = classes.getData(cls);
_ensureSupertypes(cls, data);
+ assert(data.interfaces != null);
return data.interfaces;
}
@@ -1164,7 +1166,7 @@
List<ConstantValue> getMetadata(
ir.StaticTypeContext staticTypeContext, List<ir.Expression> annotations) {
if (annotations.isEmpty) return const <ConstantValue>[];
- List<ConstantValue> metadata = <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.
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 5829b7d..4611754 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -539,8 +539,8 @@
InterfaceType get thisType;
InterfaceType get jsInteropType;
- InterfaceType get rawType;
- InterfaceType get instantiationToBounds;
+ InterfaceType /*?*/ get rawType;
+ InterfaceType /*?*/ get instantiationToBounds;
InterfaceType get supertype;
InterfaceType get mixedInType;
List<InterfaceType> get interfaces;
@@ -668,7 +668,7 @@
List<TypeVariableType> _typeVariables;
@override
- List<TypeVariableType> getFunctionTypeVariables(
+ List<TypeVariableType> /*!*/ getFunctionTypeVariables(
covariant KernelToElementMap elementMap) {
if (_typeVariables == null) {
if (functionNode.typeParameters.isEmpty) {
diff --git a/pkg/compiler/lib/src/kernel/kelements.dart b/pkg/compiler/lib/src/kernel/kelements.dart
index 8f185cc..1731db7 100644
--- a/pkg/compiler/lib/src/kernel/kelements.dart
+++ b/pkg/compiler/lib/src/kernel/kelements.dart
@@ -282,7 +282,7 @@
final MemberEntity memberContext;
final Entity executableContext;
final ir.LocalFunction node;
- FunctionType functionType;
+ /*late final*/ FunctionType functionType;
KLocalFunction(
this.name, this.memberContext, this.executableContext, this.node);
@@ -299,8 +299,8 @@
final String name;
@override
final int index;
- DartType bound;
- DartType defaultType;
+ /*late final*/ DartType bound;
+ /*late final*/ DartType defaultType;
KLocalTypeVariable(this.typeDeclaration, this.name, this.index);
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index ab584e3..64c7386 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -90,11 +90,12 @@
/// Whether or not the CFE should evaluate constants.
FeatureOption cfeConstants = FeatureOption('cfe-constants');
+ /// Whether or not to intern composite values during deserialization
+ /// (e.g. DartType).
+ FeatureOption internValues = FeatureOption('intern-composite-values');
+
/// [FeatureOption]s which are shipped and cannot be toggled.
- late final List<FeatureOption> shipped = [
- newHolders,
- legacyJavaScript,
- ];
+ late final List<FeatureOption> shipped = [newHolders, legacyJavaScript];
/// [FeatureOption]s which default to enabled.
late final List<FeatureOption> shipping = [
@@ -107,6 +108,7 @@
newDumpInfo,
simpleAsyncToFuture,
cfeConstants,
+ internValues,
];
/// Forces canary feature on. This must run after [Option].parse.
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 08d77ed..51e28e1 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -6,43 +6,6 @@
part of 'serialization.dart';
-/// Enum values used for identifying different kinds of serialized data.
-///
-/// This is used to for debugging data inconsistencies between serialization
-/// and deserialization.
-enum DataKind {
- bool,
- uint30,
- string,
- enumValue,
- uri,
- libraryNode,
- classNode,
- typedefNode,
- memberNode,
- treeNode,
- typeParameterNode,
- dartType,
- dartTypeNode,
- sourceSpan,
- constant,
- import,
- double,
- int,
-}
-
-/// Enum used for identifying the enclosing entity of a member in serialization.
-enum MemberContextKind { library, cls }
-
-/// Enum used for identifying [Local] subclasses in serialization.
-enum LocalKind {
- jLocal,
- thisLocal,
- boxLocal,
- anonymousClosureLocal,
- typeVariableLocal,
-}
-
/// Enum used for identifying [ir.TreeNode] subclasses in serialization.
enum _TreeNodeKind {
cls,
@@ -68,64 +31,6 @@
functionNode,
}
-/// Class used for encoding tags in [ObjectDataSink] and [ObjectDataSource].
-class Tag {
- final String value;
-
- Tag(this.value);
-
- @override
- int get hashCode => value.hashCode * 13;
-
- @override
- bool operator ==(other) {
- if (identical(this, other)) return true;
- if (other is! Tag) return false;
- return value == other.value;
- }
-
- @override
- String toString() => 'Tag($value)';
-}
-
-/// Enum used for identifying [DartType] subclasses in serialization.
-enum DartTypeKind {
- none,
- legacyType,
- nullableType,
- neverType,
- voidType,
- typeVariable,
- functionTypeVariable,
- functionType,
- interfaceType,
- dynamicType,
- erasedType,
- anyType,
- futureOr,
-}
-
-/// Enum used for identifying [ir.DartType] subclasses in serialization.
-enum DartTypeNodeKind {
- none,
- voidType,
- typeParameterType,
- functionType,
- functionTypeVariable,
- interfaceType,
- typedef,
- dynamicType,
- invalidType,
- thisInterfaceType,
- exactInterfaceType,
- doesNotComplete,
- neverType,
- futureOrType,
- nullType,
-}
-
-const String functionTypeNodeTag = 'function-type-node';
-
class DartTypeNodeWriter
extends ir.DartTypeVisitor1<void, List<ir.TypeParameter>> {
final DataSinkWriter _sink;
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 26a8468..2cf3679 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -4,6 +4,7 @@
// @dart = 2.10
+import 'dart:collection';
import 'dart:convert';
import 'dart:typed_data';
import 'package:kernel/ast.dart' as ir;
@@ -26,6 +27,8 @@
import 'serialization_interfaces.dart' as migrated
show DataSourceReader, DataSinkWriter;
+import 'tags.dart';
+export 'tags.dart';
part 'sink.dart';
part 'source.dart';
@@ -41,6 +44,19 @@
String internString(String string);
}
+class ValueInterner {
+ final Map<DartType, DartType> _dartTypeMap = HashMap();
+ final Map<ir.DartType, ir.DartType> _dartTypeNodeMap = HashMap();
+
+ DartType internDartType(DartType dartType) {
+ return _dartTypeMap[dartType] ??= dartType;
+ }
+
+ ir.DartType internDartTypeNode(ir.DartType dartType) {
+ return _dartTypeNodeMap[dartType] ??= dartType;
+ }
+}
+
/// Data class representing cache information for a given [T] which can be
/// passed from a [DataSourceReader] to other [DataSourceReader]s and [DataSinkWriter]s.
class DataSourceTypeIndices<E, T> {
diff --git a/pkg/compiler/lib/src/serialization/serialization_interfaces.dart b/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
index 4f241ec..161aa37 100644
--- a/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
+++ b/pkg/compiler/lib/src/serialization/serialization_interfaces.dart
@@ -2,8 +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:kernel/ast.dart' as ir show DartType, Member, TreeNode;
+
import '../elements/entities.dart';
+export 'tags.dart';
+
/// NNBD-migrated interface for methods of DataSinkWriter.
///
/// This is a pure interface or facade for DataSinkWriter.
@@ -55,6 +59,12 @@
void writeLibrary(covariant LibraryEntity value); // IndexedLibrary
void writeLibraryOrNull(covariant LibraryEntity? value); // IndexedLibrary
+ void writeDartTypeNode(ir.DartType value);
+ void writeDartTypeNodeOrNull(ir.DartType? value);
+
+ void inMemberContext(ir.Member context, void f());
+ void writeTreeNodeMapInContext<V>(Map<ir.TreeNode, V>? map, void f(V value),
+ {bool allowNull = false});
}
/// Migrated interface for methods of DataSourceReader.
@@ -78,4 +88,11 @@
LibraryEntity readLibrary(); // IndexedLibrary;
LibraryEntity? readLibraryOrNull(); // IndexedLibrary;
+
+ ir.DartType readDartTypeNode();
+ ir.DartType? readDartTypeNodeOrNull();
+
+ T inMemberContext<T>(ir.Member context, T f());
+ Map<K, V> readTreeNodeMapInContext<K extends ir.TreeNode, V>(V f());
+ Map<K, V>? readTreeNodeMapInContextOrNull<K extends ir.TreeNode, V>(V f());
}
diff --git a/pkg/compiler/lib/src/serialization/sink.dart b/pkg/compiler/lib/src/serialization/sink.dart
index b70e081..a3e37af 100644
--- a/pkg/compiler/lib/src/serialization/sink.dart
+++ b/pkg/compiler/lib/src/serialization/sink.dart
@@ -544,7 +544,9 @@
///
/// This is a convenience method to be used together with
/// [DataSourceReader.readTreeNodeMapInContext].
- void writeTreeNodeMapInContext<V>(Map<ir.TreeNode, V> map, void f(V value),
+ @override
+ void writeTreeNodeMapInContext<V>(
+ Map<ir.TreeNode, V> /*?*/ map, void f(V value),
{bool allowNull = false}) {
if (map == null) {
assert(allowNull);
@@ -640,11 +642,18 @@
}
}
- /// Writes the kernel type node [value] to this data sink. If [allowNull] is
- /// `true`, [value] is allowed to be `null`.
- void writeDartTypeNode(ir.DartType value, {bool allowNull = false}) {
+ /// Writes the kernel type node [value] to this data sink.
+ @override
+ void writeDartTypeNode(ir.DartType /*!*/ value) {
_writeDataKind(DataKind.dartTypeNode);
- _writeDartTypeNode(value, [], allowNull: allowNull);
+ _writeDartTypeNode(value, [], allowNull: false);
+ }
+
+ /// Writes the kernel type node [value] to this data sink, `null` permitted.
+ @override
+ void writeDartTypeNodeOrNull(ir.DartType /*?*/ value) {
+ _writeDataKind(DataKind.dartTypeNode);
+ _writeDartTypeNode(value, [], allowNull: true);
}
void _writeDartTypeNode(
@@ -1231,6 +1240,7 @@
/// Invoke [f] in the context of [member]. This sets up support for
/// serialization of `ir.TreeNode`s using the `writeTreeNode*InContext`
/// methods.
+ @override
void inMemberContext(ir.Member context, void f()) {
ir.Member oldMemberContext = _currentMemberContext;
_MemberData oldMemberData = _currentMemberData;
diff --git a/pkg/compiler/lib/src/serialization/source.dart b/pkg/compiler/lib/src/serialization/source.dart
index a81a4c9..df62ec5 100644
--- a/pkg/compiler/lib/src/serialization/source.dart
+++ b/pkg/compiler/lib/src/serialization/source.dart
@@ -43,6 +43,7 @@
List<ir.DartType>.empty();
final bool useDataKinds;
+ final ValueInterner /*?*/ interner;
DataSourceIndices importedIndices;
EntityReader _entityReader = const EntityReader();
ComponentLookup _componentLookup;
@@ -71,7 +72,7 @@
}
DataSourceReader(this._sourceReader,
- {this.useDataKinds = false, this.importedIndices}) {
+ {this.useDataKinds = false, this.importedIndices, this.interner}) {
_stringIndex = _createSource<String>();
_uriIndex = _createSource<Uri>();
_memberNodeIndex = _createSource<_MemberData>();
@@ -176,6 +177,7 @@
/// Invoke [f] in the context of [member]. This sets up support for
/// deserialization of `ir.TreeNode`s using the `readTreeNode*InContext`
/// methods.
+ @override
T inMemberContext<T>(ir.Member context, T f()) {
ir.Member oldMemberContext = _currentMemberContext;
_MemberData oldMemberData = _currentMemberData;
@@ -591,15 +593,26 @@
/// Reads a map from kernel tree nodes to [V] values in the known [context]
/// from this data source, calling [f] to read each value from the data
- /// source. If [emptyAsNull] is `true`, `null` is returned instead of an empty
- /// map.
+ /// source.
///
/// This is a convenience method to be used together with
/// [DataSinkWriter.writeTreeNodeMapInContext].
- Map<K, V> readTreeNodeMapInContext<K extends ir.TreeNode, V>(V f(),
- {bool emptyAsNull = false}) {
+ @override
+ Map<K, V> readTreeNodeMapInContext<K extends ir.TreeNode, V>(V f()) {
+ return readTreeNodeMapInContextOrNull<K, V>(f) ?? {};
+ }
+
+ /// Reads a map from kernel tree nodes to [V] values in the known [context]
+ /// from this data source, calling [f] to read each value from the data
+ /// source. `null` is returned for an empty map.
+ ///
+ /// This is a convenience method to be used together with
+ /// [DataSinkWriter.writeTreeNodeMapInContext].
+ @override
+ Map<K, V> /*?*/ readTreeNodeMapInContextOrNull<K extends ir.TreeNode, V>(
+ V f()) {
int count = readInt();
- if (count == 0 && emptyAsNull) return null;
+ if (count == 0) return null;
Map<K, V> map = {};
for (int i = 0; i < count; i++) {
ir.TreeNode node = readTreeNodeInContextInternal(currentMemberData);
@@ -647,7 +660,8 @@
/// Reads a type from this data source.
DartType /*!*/ readDartType() {
_checkDataKind(DataKind.dartType);
- return DartType.readFromDataSource(this, []);
+ final type = DartType.readFromDataSource(this, []);
+ return interner?.internDartType(type) ?? type;
}
/// Reads a nullable type from this data source.
@@ -678,13 +692,23 @@
/// Reads a kernel type node from this data source. If [allowNull], the
/// returned type is allowed to be `null`.
- ir.DartType readDartTypeNode({bool allowNull = false}) {
+ @override
+ ir.DartType /*!*/ readDartTypeNode() {
_checkDataKind(DataKind.dartTypeNode);
- ir.DartType type = _readDartTypeNode([]);
- assert(type != null || allowNull);
+ ir.DartType type = readDartTypeNodeOrNull();
+ if (type == null) throw UnsupportedError('Unexpected `null` DartTypeNode');
return type;
}
+ /// Reads a kernel type node from this data source. The returned type is
+ /// allowed to be `null`.
+ @override
+ ir.DartType /*?*/ readDartTypeNodeOrNull() {
+ _checkDataKind(DataKind.dartTypeNode);
+ final type = _readDartTypeNode([]);
+ return interner?.internDartTypeNode(type) ?? type;
+ }
+
ir.DartType _readDartTypeNode(List<ir.TypeParameter> functionTypeVariables) {
DartTypeNodeKind kind = readEnum(DartTypeNodeKind.values);
switch (kind) {
diff --git a/pkg/compiler/lib/src/serialization/tags.dart b/pkg/compiler/lib/src/serialization/tags.dart
new file mode 100644
index 0000000..9af5c36
--- /dev/null
+++ b/pkg/compiler/lib/src/serialization/tags.dart
@@ -0,0 +1,98 @@
+// 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.
+
+/// Enum values used for identifying different kinds of serialized data.
+///
+/// This is used to for debugging data inconsistencies between serialization
+/// and deserialization.
+enum DataKind {
+ bool,
+ uint30,
+ string,
+ enumValue,
+ uri,
+ libraryNode,
+ classNode,
+ typedefNode,
+ memberNode,
+ treeNode,
+ typeParameterNode,
+ dartType,
+ dartTypeNode,
+ sourceSpan,
+ constant,
+ import,
+ double,
+ int,
+}
+
+/// Enum used for identifying the enclosing entity of a member in serialization.
+enum MemberContextKind { library, cls }
+
+/// Enum used for identifying [Local] subclasses in serialization.
+enum LocalKind {
+ jLocal,
+ thisLocal,
+ boxLocal,
+ anonymousClosureLocal,
+ typeVariableLocal,
+}
+
+/// Class used for encoding tags in [ObjectDataSink] and [ObjectDataSource].
+class Tag {
+ final String value;
+
+ Tag(this.value);
+
+ @override
+ int get hashCode => value.hashCode * 13;
+
+ @override
+ bool operator ==(other) {
+ if (identical(this, other)) return true;
+ if (other is! Tag) return false;
+ return value == other.value;
+ }
+
+ @override
+ String toString() => 'Tag($value)';
+}
+
+/// Enum used for identifying [DartType] subclasses in serialization.
+enum DartTypeKind {
+ none,
+ legacyType,
+ nullableType,
+ neverType,
+ voidType,
+ typeVariable,
+ functionTypeVariable,
+ functionType,
+ interfaceType,
+ dynamicType,
+ erasedType,
+ anyType,
+ futureOr,
+}
+
+/// Enum used for identifying [ir.DartType] subclasses in serialization.
+enum DartTypeNodeKind {
+ none,
+ voidType,
+ typeParameterType,
+ functionType,
+ functionTypeVariable,
+ interfaceType,
+ typedef,
+ dynamicType,
+ invalidType,
+ thisInterfaceType,
+ exactInterfaceType,
+ doesNotComplete,
+ neverType,
+ futureOrType,
+ nullType,
+}
+
+const String functionTypeNodeTag = 'function-type-node';
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index a534865..6f9d2c4 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -100,10 +100,13 @@
final api.CompilerInput _provider;
final api.CompilerOutput _outputProvider;
final _stringInterner = _StringInterner();
+ final ValueInterner /*?*/ _valueInterner;
SerializationTask(this._options, this._reporter, this._provider,
this._outputProvider, Measurer measurer)
- : super(measurer);
+ : _valueInterner =
+ _options.features.internValues.isEnabled ? ValueInterner() : null,
+ super(measurer);
@override
String get name => 'Serialization';
@@ -204,7 +207,7 @@
data.toDataSink(binarySink);
binarySink.close();
var source = DataSourceReader(BinaryDataSource(bytes.builder.toBytes()),
- useDataKinds: true);
+ useDataKinds: true, interner: _valueInterner);
source.registerComponentLookup(ComponentLookup(component));
ModuleData.fromDataSource(source);
}
@@ -217,8 +220,10 @@
for (Uri uri in _options.modularAnalysisInputs) {
api.Input<List<int>> dataInput =
await _provider.readFromUri(uri, inputKind: api.InputKind.binary);
- DataSourceReader source =
- DataSourceReader(BinaryDataSource(dataInput.data));
+ DataSourceReader source = DataSourceReader(
+ BinaryDataSource(dataInput.data),
+ interner: _valueInterner,
+ );
source.registerComponentLookup(ComponentLookup(component));
results.readMoreFromDataSource(source);
}
@@ -247,7 +252,8 @@
_options.readClosedWorldUri,
inputKind: api.InputKind.binary);
DataSourceReader source = DataSourceReader(
- BinaryDataSource(dataInput.data, stringInterner: _stringInterner));
+ BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
+ interner: _valueInterner);
var closedWorld = deserializeClosedWorldFromSource(_options, _reporter,
environment, abstractValueStrategy, component, source);
return ClosedWorldAndIndices(closedWorld, source.exportIndices());
@@ -282,6 +288,7 @@
.readFromUri(_options.readDataUri, inputKind: api.InputKind.binary);
DataSourceReader source = DataSourceReader(
BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
+ interner: _valueInterner,
importedIndices: closedWorldAndIndices.indices);
return deserializeGlobalTypeInferenceResultsFromSource(
_options,
@@ -362,6 +369,7 @@
Map<MemberEntity, CodegenResult> results) {
DataSourceReader source = DataSourceReader(
BinaryDataSource(dataInput.data, stringInterner: _stringInterner),
+ interner: _valueInterner,
importedIndices: importedIndices);
backendStrategy.prepareCodegenReader(source);
Map<MemberEntity, CodegenResult> codegenResults =
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 02d707c..d897f20 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -622,7 +622,7 @@
}
DartType _getDartTypeIfValid(ir.DartType type) {
- if (type is ir.InvalidType) return null;
+ if (type is ir.InvalidType) return dartTypes.dynamicType();
return _elementMap.getDartType(type);
}
@@ -5186,7 +5186,8 @@
// we could assert that the trailing arguments are all null.
// TODO(jacobr): rewrite named arguments to an object literal matching
// the factory constructor case.
- List<HInstruction> inputs = arguments.where((arg) => arg != null).toList();
+ List<HInstruction /*!*/ > inputs =
+ arguments.where((arg) => arg != null).toList();
var nativeBehavior = NativeBehavior()..sideEffects.setAllSideEffects();
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 3a96d59..36f104e 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -4321,7 +4321,7 @@
AbstractValue supersetType = checkedAbstractValue.abstractValue;
AbstractBool expressionIsNull = expression.isNull(abstractValueDomain);
- bool _nullIs(DartType type) =>
+ bool _nullIs(DartType /*!*/ type) =>
dartTypes.isStrongTopType(type) ||
type is LegacyType &&
(type.baseType.isObject || type.baseType is NeverType) ||
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index c545b07..5919cd6 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -530,19 +530,19 @@
/// the usage changes for each member.
void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
if (staticUse.kind == StaticUseKind.CLOSURE) {
- Local localFunction = staticUse.element;
+ Local /*!*/ localFunction = staticUse.element;
FunctionType type =
_elementEnvironment.getLocalFunctionType(localFunction);
if (type.typeVariables.isNotEmpty) {
_genericLocalFunctions.add(localFunction);
}
- _localFunctions.add(staticUse.element);
+ _localFunctions.add(localFunction);
return;
} else if (staticUse.kind == StaticUseKind.CLOSURE_CALL) {
- if (staticUse.typeArguments?.isNotEmpty ?? false) {
+ final typeArguments = staticUse.typeArguments;
+ if (typeArguments != null && typeArguments.isNotEmpty) {
registerDynamicInvocation(
- Selector.call(Names.call, staticUse.callStructure),
- staticUse.typeArguments);
+ Selector.call(Names.call, staticUse.callStructure), typeArguments);
}
return;
}
diff --git a/pkg/dart2native/lib/macho.dart b/pkg/dart2native/lib/macho.dart
index 7aaccb8..e0d8f93 100644
--- a/pkg/dart2native/lib/macho.dart
+++ b/pkg/dart2native/lib/macho.dart
@@ -1176,7 +1176,7 @@
* this requires the r_address field to be something other than a section
* offset to identify the item to be relocated. In this case r_address is
* set to the offset from the vmaddr of the first LC_SEGMENT command.
- * For MH_SPLIT_SEGS images r_address is set to the the offset from the
+ * For MH_SPLIT_SEGS images r_address is set to the offset from the
* vmaddr of the first read-write LC_SEGMENT command.
*
* The relocation entries are grouped by module and the module table
@@ -1412,7 +1412,7 @@
* isub_image field is an index into the sub-images (sub-frameworks and
* sub-umbrellas list) that made up the two-level image that the undefined
* symbol was found in when it was built by the static link editor. If
- * isub-image is 0 the the symbol is expected to be defined in library and not
+ * isub-image is 0 the symbol is expected to be defined in library and not
* in the sub-images. If isub-image is non-zero it is an index into the array
* of sub-images for the umbrella with the first index in the sub-images being
* 1. The array of sub-images is the ordered list of sub-images of the umbrella
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 a367a17..77c6eaa 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
@@ -463,6 +463,11 @@
return type;
}
+ bool get isInferenceUpdate1Enabled =>
+ libraryFeatures.inferenceUpdate1.isSupported &&
+ languageVersion.version >=
+ libraryFeatures.inferenceUpdate1.enabledVersion;
+
bool? _isNonNullableByDefault;
@override
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 65866a4..415fe83 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
@@ -250,6 +250,9 @@
CoreTypes get coreTypes => engine.coreTypes;
+ bool get isInferenceUpdate1Enabled =>
+ libraryBuilder.isInferenceUpdate1Enabled;
+
bool get isNonNullableByDefault => libraryBuilder.isNonNullableByDefault;
NnbdMode get nnbdMode => libraryBuilder.loader.nnbdMode;
@@ -2395,10 +2398,41 @@
hoistingEndIndex = 0;
}
+ ExpressionInferenceResult inferArgument(
+ DartType formalType, Expression argumentExpression,
+ {required bool isNamed}) {
+ DartType inferredFormalType = substitution != null
+ ? substitution.substituteType(formalType)
+ : formalType;
+ if (!isNamed) {
+ if (isSpecialCasedBinaryOperator) {
+ inferredFormalType =
+ typeSchemaEnvironment.getContextTypeOfSpecialCasedBinaryOperator(
+ typeContext, receiverType!, inferredFormalType,
+ isNonNullableByDefault: isNonNullableByDefault);
+ } else if (isSpecialCasedTernaryOperator) {
+ inferredFormalType =
+ typeSchemaEnvironment.getContextTypeOfSpecialCasedTernaryOperator(
+ typeContext, receiverType!, inferredFormalType,
+ isNonNullableByDefault: isNonNullableByDefault);
+ }
+ }
+ return inferExpression(
+ argumentExpression,
+ isNonNullableByDefault
+ ? inferredFormalType
+ : legacyErasure(inferredFormalType),
+ inferenceNeeded ||
+ isSpecialCasedBinaryOperator ||
+ isSpecialCasedTernaryOperator ||
+ typeChecksNeeded);
+ }
+
List<EqualityInfo<VariableDeclaration, DartType>?>? identicalInfo =
isIdentical && arguments.positional.length == 2 ? [] : null;
int positionalIndex = 0;
int namedIndex = 0;
+ List<_DeferredParamInfo>? deferredFunctionLiterals;
for (int evaluationOrderIndex = 0;
evaluationOrderIndex < argumentsEvaluationOrder.length;
evaluationOrderIndex++) {
@@ -2421,60 +2455,77 @@
formalType = getNamedParameterType(calleeType, namedArgument.name);
argumentExpression = namedArgument.value;
}
- DartType inferredFormalType = substitution != null
- ? substitution.substituteType(formalType)
- : formalType;
- if (isExpression) {
- if (isImplicitExtensionMember && index == 0) {
- assert(
- receiverType != null,
- "No receiver type provided for implicit extension member "
- "invocation.");
- continue;
- }
- if (isSpecialCasedBinaryOperator) {
- inferredFormalType =
- typeSchemaEnvironment.getContextTypeOfSpecialCasedBinaryOperator(
- typeContext, receiverType!, inferredFormalType,
- isNonNullableByDefault: isNonNullableByDefault);
- } else if (isSpecialCasedTernaryOperator) {
- inferredFormalType =
- typeSchemaEnvironment.getContextTypeOfSpecialCasedTernaryOperator(
- typeContext, receiverType!, inferredFormalType,
- isNonNullableByDefault: isNonNullableByDefault);
- }
+ if (isExpression && isImplicitExtensionMember && index == 0) {
+ assert(
+ receiverType != null,
+ "No receiver type provided for implicit extension member "
+ "invocation.");
+ continue;
}
- ExpressionInferenceResult result = inferExpression(
- argumentExpression,
- isNonNullableByDefault
- ? inferredFormalType
- : legacyErasure(inferredFormalType),
- inferenceNeeded ||
- isSpecialCasedBinaryOperator ||
- isSpecialCasedTernaryOperator ||
- typeChecksNeeded);
- DartType inferredType = identical(result.inferredType, noInferredType) ||
- isNonNullableByDefault
- ? result.inferredType
- : legacyErasure(result.inferredType);
- if (localHoistedExpressions != null &&
- evaluationOrderIndex >= hoistingEndIndex) {
- hoistedExpressions = null;
- }
- Expression expression =
- _hoist(result.expression, inferredType, hoistedExpressions);
- identicalInfo
- ?.add(flowAnalysis.equalityOperand_end(expression, inferredType));
- if (isExpression) {
- arguments.positional[index] = expression..parent = arguments;
+ if (isInferenceUpdate1Enabled &&
+ argumentExpression is FunctionExpression) {
+ (deferredFunctionLiterals ??= []).add(new _DeferredParamInfo(
+ formalType: formalType,
+ argumentExpression: argumentExpression,
+ isNamed: !isExpression,
+ evaluationOrderIndex: evaluationOrderIndex,
+ index: index));
+ // We don't have `identical` info yet, so fill it in with `null` for
+ // now. Later, when we visit the function literal, we'll replace it.
+ identicalInfo?.add(null);
+ if (useFormalAndActualTypes) {
+ formalTypes!.add(formalType);
+ // We don't have an inferred type yet, so fill it in with UnknownType
+ // for now. Later, when we infer a type, we'll replace it.
+ actualTypes!.add(const UnknownType());
+ }
} else {
- NamedExpression namedArgument = arguments.named[index];
- namedArgument.value = expression..parent = namedArgument;
+ ExpressionInferenceResult result = inferArgument(
+ formalType, argumentExpression,
+ isNamed: !isExpression);
+ DartType inferredType = _computeInferredType(result);
+ if (localHoistedExpressions != null &&
+ evaluationOrderIndex >= hoistingEndIndex) {
+ hoistedExpressions = null;
+ }
+ Expression expression =
+ _hoist(result.expression, inferredType, hoistedExpressions);
+ identicalInfo
+ ?.add(flowAnalysis.equalityOperand_end(expression, inferredType));
+ if (isExpression) {
+ arguments.positional[index] = expression..parent = arguments;
+ } else {
+ NamedExpression namedArgument = arguments.named[index];
+ namedArgument.value = expression..parent = namedArgument;
+ }
+ gatherer?.tryConstrainLower(formalType, inferredType);
+ if (useFormalAndActualTypes) {
+ formalTypes!.add(formalType);
+ actualTypes!.add(inferredType);
+ }
}
- gatherer?.tryConstrainLower(formalType, inferredType);
- if (useFormalAndActualTypes) {
- formalTypes!.add(formalType);
- actualTypes!.add(inferredType);
+ }
+ if (deferredFunctionLiterals != null) {
+ for (_DeferredParamInfo deferredArgument in deferredFunctionLiterals) {
+ ExpressionInferenceResult result = inferArgument(
+ deferredArgument.formalType, deferredArgument.argumentExpression,
+ isNamed: deferredArgument.isNamed);
+ DartType inferredType = _computeInferredType(result);
+ Expression expression = result.expression;
+ identicalInfo?[deferredArgument.evaluationOrderIndex] =
+ flowAnalysis.equalityOperand_end(expression, inferredType);
+ if (deferredArgument.isNamed) {
+ NamedExpression namedArgument =
+ arguments.named[deferredArgument.index];
+ namedArgument.value = expression..parent = namedArgument;
+ } else {
+ arguments.positional[deferredArgument.index] = expression
+ ..parent = arguments;
+ }
+ gatherer?.tryConstrainLower(deferredArgument.formalType, inferredType);
+ if (useFormalAndActualTypes) {
+ actualTypes![deferredArgument.evaluationOrderIndex] = inferredType;
+ }
}
}
if (identicalInfo != null) {
@@ -4718,6 +4769,11 @@
Expression createEqualsNull(int fileOffset, Expression left) {
return new EqualsNull(left)..fileOffset = fileOffset;
}
+
+ DartType _computeInferredType(ExpressionInferenceResult result) =>
+ identical(result.inferredType, noInferredType) || isNonNullableByDefault
+ ? result.inferredType
+ : legacyErasure(result.inferredType);
}
class TypeInferrerImplBenchmarked implements TypeInferrer {
@@ -5877,3 +5933,33 @@
ImplicitInstantiation(
this.typeArguments, this.functionType, this.instantiatedType);
}
+
+/// Information about an invocation argument that needs to be resolved later due
+/// to the fact that it's a function literal and the `inference-update-1`
+/// feature is enabled.
+class _DeferredParamInfo {
+ /// The (unsubstituted) type of the formal parameter corresponding to this
+ /// argument.
+ final DartType formalType;
+
+ /// The function literal expression.
+ final FunctionExpression argumentExpression;
+
+ /// Indicates whether this is a named argument.
+ final bool isNamed;
+
+ /// The index into the full argument list (considering both named and unnamed
+ /// arguments) of the function literal expression.
+ final int evaluationOrderIndex;
+
+ /// The index into either [Arguments.named] or [Arguments.positional] of the
+ /// function literal expression (depending upon the value of [isNamed]).
+ final int index;
+
+ _DeferredParamInfo(
+ {required this.formalType,
+ required this.argumentExpression,
+ required this.isNamed,
+ required this.evaluationOrderIndex,
+ required this.index});
+}
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 3d62028..65269dd 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -68,20 +68,25 @@
show
AwaitExpression,
BasicLiteral,
+ Class,
Component,
Constant,
ConstantExpression,
Expression,
FileUriExpression,
FileUriNode,
+ InstanceInvocation,
+ InstanceSet,
InvalidExpression,
Library,
LibraryPart,
Member,
Node,
NonNullableByDefaultCompiledMode,
+ Reference,
TreeNode,
UnevaluatedConstant,
+ VariableDeclaration,
Version,
Visitor,
VisitorVoidMixin;
@@ -91,6 +96,15 @@
import 'package:kernel/kernel.dart'
show RecursiveResultVisitor, loadComponentFromBytes;
import 'package:kernel/reference_from_index.dart' show ReferenceFromIndex;
+
+import 'package:kernel/src/equivalence.dart'
+ show
+ EquivalenceResult,
+ EquivalenceStrategy,
+ EquivalenceVisitor,
+ ReferenceName,
+ checkEquivalence;
+
import 'package:kernel/target/changed_structure_notifier.dart'
show ChangedStructureNotifier;
import 'package:kernel/target/targets.dart'
@@ -103,6 +117,7 @@
TestTargetFlags,
TestTargetMixin,
TestTargetWrapper;
+
import 'package:kernel/type_environment.dart'
show StaticTypeContext, TypeEnvironment;
import 'package:testing/testing.dart'
@@ -1371,11 +1386,39 @@
"${newUserLibraries.map((e) => e.toString()).join("\n")}\n\n"
"${originalCompileString}");
}
+
+ if (!compareComponents(component, newComponent)) {
+ return new Result<ComponentResult>(originalCompilationResult,
+ semiFuzzFailure, "Fuzzed component changed in an unexpected way.");
+ }
}
return null;
}
+ bool compareComponents(Component a, Component b) {
+ if (a.libraries.length != b.libraries.length) {
+ print("Not the same number of libraries.");
+ return false;
+ }
+ a.libraries.sort((l1, l2) {
+ return "${l1.importUri}".compareTo("${l2.importUri}");
+ });
+ b.libraries.sort((l1, l2) {
+ return "${l1.importUri}".compareTo("${l2.importUri}");
+ });
+ for (int i = 0; i < a.libraries.length; i++) {
+ EquivalenceResult result = checkEquivalence(
+ a.libraries[i], b.libraries[i],
+ strategy: const Strategy());
+ if (!result.isEquivalent) {
+ print(result.toString());
+ return false;
+ }
+ }
+ return true;
+ }
+
bool canSerialize(Component component) {
ByteSink byteSink = new ByteSink();
try {
@@ -1670,6 +1713,83 @@
}
}
+class Strategy extends EquivalenceStrategy {
+ const Strategy();
+
+ @override
+ bool checkLibrary_procedures(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkSets(node.procedures.toSet(), other.procedures.toSet(),
+ visitor.matchNamedNodes, visitor.checkNodes, 'procedures');
+ }
+
+ @override
+ bool checkClass_procedures(
+ EquivalenceVisitor visitor, Class node, Class other) {
+ return visitor.checkSets(node.procedures.toSet(), other.procedures.toSet(),
+ visitor.matchNamedNodes, visitor.checkNodes, 'procedures');
+ }
+
+ @override
+ bool checkLibrary_additionalExports(
+ EquivalenceVisitor visitor, Library node, Library other) {
+ return visitor.checkSets(
+ node.additionalExports.toSet(),
+ other.additionalExports.toSet(),
+ visitor.matchReferences,
+ visitor.checkReferences,
+ 'additionalExports');
+ }
+
+ @override
+ bool checkVariableDeclaration_binaryOffsetNoTag(EquivalenceVisitor visitor,
+ VariableDeclaration node, VariableDeclaration other) {
+ return true;
+ }
+
+ /// Allow assuming references like
+ /// "_Class&Superclass&Mixin::@methods::method4" and
+ /// "Mixin::@methods::method4" are equal (an interfaceTargetReference change
+ /// that often occur on recompile in regards to mixins).
+ ///
+ /// Copied from incremental_dart2js_load_from_dill_test.dart
+ bool _isMixinOrCloneReference(EquivalenceVisitor visitor, Reference? a,
+ Reference? b, String propertyName) {
+ if (a != null && b != null) {
+ ReferenceName thisName = ReferenceName.fromReference(a)!;
+ ReferenceName otherName = ReferenceName.fromReference(b)!;
+ if (thisName.isMember &&
+ otherName.isMember &&
+ thisName.memberName == otherName.memberName) {
+ String? thisClassName = thisName.declarationName;
+ String? otherClassName = otherName.declarationName;
+ if (thisClassName != null &&
+ otherClassName != null &&
+ thisClassName.contains('&${otherClassName}')) {
+ visitor.assumeReferences(a, b);
+ }
+ }
+ }
+ return visitor.checkReferences(a, b, propertyName);
+ }
+
+ @override
+ bool checkInstanceInvocation_interfaceTargetReference(
+ EquivalenceVisitor visitor,
+ InstanceInvocation node,
+ InstanceInvocation other) {
+ return _isMixinOrCloneReference(visitor, node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+
+ @override
+ bool checkInstanceSet_interfaceTargetReference(
+ EquivalenceVisitor visitor, InstanceSet node, InstanceSet other) {
+ return _isMixinOrCloneReference(visitor, node.interfaceTargetReference,
+ other.interfaceTargetReference, 'interfaceTargetReference');
+ }
+}
+
class FuzzAstVisitorSorterChunk {
final FuzzOriginalType originalType;
final String data;
diff --git a/pkg/front_end/test/incremental_suite.dart b/pkg/front_end/test/incremental_suite.dart
index d4399ff..e96910b 100644
--- a/pkg/front_end/test/incremental_suite.dart
+++ b/pkg/front_end/test/incremental_suite.dart
@@ -99,6 +99,8 @@
import "incremental_utils.dart" as util;
+import 'testing_utils.dart' show checkEnvironment;
+
import 'utils/io_utils.dart' show computeRepoDir;
void main([List<String> arguments = const []]) =>
@@ -240,12 +242,22 @@
final Expectation NNBDModeMismatch = staticExpectationSet["NNBDModeMismatch"];
Future<Context> createContext(Chain suite, Map<String, String> environment) {
+ const Set<String> knownEnvironmentKeys = {
+ "updateExpectations",
+ "addDebugBreaks",
+ "skipTests",
+ };
+ checkEnvironment(environment, knownEnvironmentKeys);
+
// Disable colors to ensure that expectation files are the same across
// platforms and independent of stdin/stderr.
colors.enableColors = false;
+ Set<String> skipTests = environment["skipTests"]?.split(",").toSet() ?? {};
return new Future.value(new Context(
- environment["updateExpectations"] == "true",
- environment["addDebugBreaks"] == "true"));
+ environment["updateExpectations"] == "true",
+ environment["addDebugBreaks"] == "true",
+ skipTests,
+ ));
}
class Context extends ChainContext {
@@ -261,7 +273,23 @@
/// iteration (or 'world run') when doing a "new world test".
final bool breakBetween;
- Context(this.updateExpectations, this.breakBetween);
+ final Set<String> skipTests;
+
+ Context(this.updateExpectations, this.breakBetween, this.skipTests);
+
+ @override
+ Stream<TestDescription> list(Chain suite) {
+ if (skipTests.isEmpty) return super.list(suite);
+ return filterSkipped(super.list(suite));
+ }
+
+ Stream<TestDescription> filterSkipped(Stream<TestDescription> all) async* {
+ await for (TestDescription testDescription in all) {
+ if (!skipTests.contains(testDescription.shortName)) {
+ yield testDescription;
+ }
+ }
+ }
@override
Future<void> cleanUp(TestDescription description, Result result) async {
@@ -878,6 +906,13 @@
}
}
+ util.postProcessComponent(component!);
+ String actualSerialized = componentToStringSdkFiltered(component!);
+ print("*****\n\ncomponent:\n"
+ "${actualSerialized}\n\n\n");
+ result = checkExpectFile(data, worldNum, "", context, actualSerialized);
+ if (result != null) return result;
+
if (world["compareToPrevious"] == true && newestWholeComponent != null) {
EquivalenceResult result = checkEquivalence(
newestWholeComponent!, component!,
@@ -890,9 +925,6 @@
newestWholeComponentData = util.postProcess(component!);
newestWholeComponent = component;
- String actualSerialized = componentToStringSdkFiltered(component!);
- print("*****\n\ncomponent:\n"
- "${actualSerialized}\n\n\n");
if (world["uriToSourcesDoesntInclude"] != null) {
for (String filename in world["uriToSourcesDoesntInclude"]) {
@@ -927,8 +959,6 @@
}
}
- result = checkExpectFile(data, worldNum, "", context, actualSerialized);
- if (result != null) return result;
if (world["skipClassHierarchyTest"] != true) {
result = checkClassHierarchy(compilerResult, data, worldNum, context);
if (result != null) return result;
diff --git a/pkg/front_end/test/incremental_utils.dart b/pkg/front_end/test/incremental_utils.dart
index 49c7663..7ad424c 100644
--- a/pkg/front_end/test/incremental_utils.dart
+++ b/pkg/front_end/test/incremental_utils.dart
@@ -21,6 +21,11 @@
Reference;
List<int> postProcess(Component c) {
+ postProcessComponent(c);
+ return serializeComponent(c);
+}
+
+void postProcessComponent(Component c) {
c.libraries.sort((l1, l2) {
return "${l1.fileUri}".compareTo("${l2.fileUri}");
});
@@ -34,8 +39,6 @@
});
library.problemsAsJson?.sort();
}
-
- return serializeComponent(c);
}
void throwOnEmptyMixinBodies(Component component) {
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 5590566..103c5d1 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -248,6 +248,7 @@
configured
connectivity
consideration
+considering
constness
constraining
consult
@@ -1441,6 +1442,7 @@
unshadowed
unsortable
unsound
+unsubstituted
untouched
unwrapper
unwraps
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 38d1b02..869c4d1 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -222,6 +222,7 @@
draw
dry
dsemi
+dskip
dumping
dumps
dupe
@@ -340,6 +341,7 @@
implementor
implementors
imprecision
+improvement
inclosure
inconsistencies
increasing
diff --git a/pkg/front_end/test/vm_service_for_leak_detection.dart b/pkg/front_end/test/vm_service_for_leak_detection.dart
index 44b38c4..0ff1658 100644
--- a/pkg/front_end/test/vm_service_for_leak_detection.dart
+++ b/pkg/front_end/test/vm_service_for_leak_detection.dart
@@ -55,6 +55,9 @@
"--enable-asserts",
Platform.script.resolve("incremental_suite.dart").toString(),
"-DaddDebugBreaks=true",
+ // import_package_by_file_uri by design imports the same file in two
+ // different ways, thus getting two copies of the same library.
+ "-DskipTests=import_package_by_file_uri"
]);
} else {
await heapHelper.start([
diff --git a/pkg/front_end/testcases/incremental.status b/pkg/front_end/testcases/incremental.status
index aaa2393..1afe42e 100644
--- a/pkg/front_end/testcases/incremental.status
+++ b/pkg/front_end/testcases/incremental.status
@@ -8,4 +8,11 @@
#strongmode_mixins_2: Crash
changing_modules_16: Crash
-late_lowering: EquivalenceError
\ No newline at end of file
+late_lowering: EquivalenceError
+constant_fileoffset_and_typedef: EquivalenceError
+no_change_but_changed_type: EquivalenceError
+no_such_method_forwarder: EquivalenceError
+no_change_but_changed_type_02: EquivalenceError
+changing_nullability_on_recompile: EquivalenceError
+initializer_not_copied: EquivalenceError
+changed_error: EquivalenceError
diff --git a/pkg/front_end/testcases/incremental/changed_error.yaml b/pkg/front_end/testcases/incremental/changed_error.yaml
new file mode 100644
index 0000000..19c4d71
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changed_error.yaml
@@ -0,0 +1,36 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# 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.
+
+# Recompiling with no change shouldn't change anything.
+# http://dartbug.com/48897
+
+type: newworld
+worlds:
+ - entry: main.dart
+ errors: true
+ sources:
+ main.dart: |
+ // @dart=2.12
+
+ import "lib.dart";
+
+ main() {
+ Bar<int> x = new Bar<int>();
+ print(x);
+ }
+ lib.dart: |
+ // @dart=2.12
+ class Foo<X> {}
+ typedef Bar<X> = Foo<X>;
+
+ expectedLibraryCount: 2
+
+ - entry: main.dart
+ errors: true
+ worldType: updated
+ compareToPrevious: true
+ expectInitializeFromDill: false
+ invalidate:
+ - main.dart
+ expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/changed_error.yaml.world.1.expect b/pkg/front_end/testcases/incremental/changed_error.yaml.world.1.expect
new file mode 100644
index 0000000..3694fc5
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changed_error.yaml.world.1.expect
@@ -0,0 +1,33 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib.dart:3:16: Error: Can't create typedef from non-function type.
+// typedef Bar<X> = Foo<X>;
+// ^
+//
+
+ typedef Bar<unrelated X extends dart.core::Object? = dynamic> = invalid-type;
+ class Foo<X extends dart.core::Object? = dynamic> extends dart.core::Object {
+ synthetic constructor •() → lib::Foo<lib::Foo::X%>
+ : super dart.core::Object::•()
+ ;
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:6:20: Error: Can't create typedef from non-function type.
+// Bar<int> x = new Bar<int>();
+// ^^^
+//
+
+ import "org-dartlang-test:///lib.dart";
+
+ static method main() → dynamic {
+ invalid-type x = invalid-expression "org-dartlang-test:///main.dart:6:20: Error: Can't create typedef from non-function type.\n Bar<int> x = new Bar<int>();\n ^^^";
+ dart.core::print(x);
+ }
+}
diff --git a/pkg/front_end/testcases/incremental/changed_error.yaml.world.2.expect b/pkg/front_end/testcases/incremental/changed_error.yaml.world.2.expect
new file mode 100644
index 0000000..1c4c0ee
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changed_error.yaml.world.2.expect
@@ -0,0 +1,33 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib.dart:3:16: Error: Can't create typedef from non-function type.
+// typedef Bar<X> = Foo<X>;
+// ^
+//
+
+ typedef Bar<unrelated X extends dart.core::Object? = dynamic> = invalid-type;
+ class Foo<X extends dart.core::Object? = dynamic> extends dart.core::Object {
+ synthetic constructor •() → lib::Foo<lib::Foo::X%>
+ : super dart.core::Object::•()
+ ;
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+//
+// Problems in library:
+//
+// org-dartlang-test:///main.dart:6:20: Error: Couldn't find constructor 'Bar'.
+// Bar<int> x = new Bar<int>();
+// ^^^
+//
+
+ import "org-dartlang-test:///lib.dart";
+
+ static method main() → dynamic {
+ invalid-type x = invalid-expression "org-dartlang-test:///main.dart:6:20: Error: Couldn't find constructor 'Bar'.\n Bar<int> x = new Bar<int>();\n ^^^";
+ dart.core::print(x);
+ }
+}
diff --git a/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml
new file mode 100644
index 0000000..2cb29e2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml
@@ -0,0 +1,35 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# 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.
+
+# Recompiling with no change shouldn't change anything.
+# http://dartbug.com/48894
+
+type: newworld
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ // @dart=2.5
+
+ import 'lib.dart';
+
+ class LegacyClass extends Class implements Interface {}
+ lib.dart: |
+ abstract class Interface {
+ int method5c([int a = 0, int? b]);
+ int method7b({int a: 0, int? b});
+ }
+ class Class {
+ int method5c([int a = 0, int? b]) => 0;
+ int method7b({int a = 0, int? b}) => 0;
+ }
+ expectedLibraryCount: 2
+
+ - entry: main.dart
+ worldType: updated
+ compareToPrevious: true
+ expectInitializeFromDill: false
+ invalidate:
+ - main.dart
+ expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.1.expect b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.1.expect
new file mode 100644
index 0000000..7832042
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.1.expect
@@ -0,0 +1,46 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+ abstract class Interface extends dart.core::Object {
+ synthetic constructor •() → lib::Interface
+ : super dart.core::Object::•()
+ ;
+ abstract method method5c([dart.core::int a = #C1, dart.core::int? b = #C2]) → dart.core::int;
+ abstract method method7b({dart.core::int a = #C1, dart.core::int? b = #C2}) → dart.core::int;
+ }
+ class Class extends dart.core::Object {
+ synthetic constructor •() → lib::Class
+ : super dart.core::Object::•()
+ ;
+ method method5c([dart.core::int a = #C1, dart.core::int? b = #C2]) → dart.core::int
+ return 0;
+ method method7b({dart.core::int a = #C1, dart.core::int? b = #C2}) → dart.core::int
+ return 0;
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib.dart";
+
+ class LegacyClass extends lib::Class implements lib::Interface {
+ synthetic constructor •() → main::LegacyClass*
+ : super lib::Class::•()
+ ;
+ abstract member-signature method method5c([dart.core::int* a = #C1, dart.core::int* b = #C2]) → dart.core::int*; -> lib::Class::method5c
+ abstract member-signature method method7b({dart.core::int* a = #C1, dart.core::int* b = #C2}) → dart.core::int*; -> lib::Class::method7b
+ abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+ abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+ abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+ abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+ }
+}
+constants {
+ #C1 = 0
+ #C2 = null
+}
diff --git a/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.2.expect b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.2.expect
new file mode 100644
index 0000000..7832042
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changing_nullability_on_recompile.yaml.world.2.expect
@@ -0,0 +1,46 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+ abstract class Interface extends dart.core::Object {
+ synthetic constructor •() → lib::Interface
+ : super dart.core::Object::•()
+ ;
+ abstract method method5c([dart.core::int a = #C1, dart.core::int? b = #C2]) → dart.core::int;
+ abstract method method7b({dart.core::int a = #C1, dart.core::int? b = #C2}) → dart.core::int;
+ }
+ class Class extends dart.core::Object {
+ synthetic constructor •() → lib::Class
+ : super dart.core::Object::•()
+ ;
+ method method5c([dart.core::int a = #C1, dart.core::int? b = #C2]) → dart.core::int
+ return 0;
+ method method7b({dart.core::int a = #C1, dart.core::int? b = #C2}) → dart.core::int
+ return 0;
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib.dart";
+
+ class LegacyClass extends lib::Class implements lib::Interface {
+ synthetic constructor •() → main::LegacyClass*
+ : super lib::Class::•()
+ ;
+ abstract member-signature method method5c([dart.core::int* a = #C1, dart.core::int* b = #C2]) → dart.core::int*; -> lib::Class::method5c
+ abstract member-signature method method7b({dart.core::int* a = #C1, dart.core::int* b = #C2}) → dart.core::int*; -> lib::Class::method7b
+ abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+ abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+ abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+ abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+ abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+ }
+}
+constants {
+ #C1 = 0
+ #C2 = null
+}
diff --git a/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml
new file mode 100644
index 0000000..3e91d8d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml
@@ -0,0 +1,33 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# 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.
+
+# Offset should be correct and not change when nothing changes. A type literal
+# constants FunctionType really shouldn't point to a TypedefType (and if it does
+# it shouldn't change when recompiling with no change).
+# http://dartbug.com/48890
+
+type: newworld
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ import "lib1.dart";
+ import "lib2.dart";
+ lib1.dart: |
+ // Stuff here to change the offset.
+ const genericFunctionTypeLiteral1 = td1;
+ typedef td1 = T Function<T>(T);
+ lib2.dart: |
+ const genericFunctionTypeLiteral2 = td2;
+ typedef td2 = T Function<T>(T);
+ typedef td3 = T1 Function<T1, T2>(T2);
+ expectedLibraryCount: 3
+
+ - entry: main.dart
+ worldType: updated
+ compareToPrevious: true
+ expectInitializeFromDill: false
+ invalidate:
+ - lib2.dart
+ expectedLibraryCount: 3
diff --git a/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.1.expect b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.1.expect
new file mode 100644
index 0000000..4c9cfb2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.1.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib1.dart" as lib1 {
+
+ typedef td1 = <T extends dart.core::Object? = dynamic>(T%) → T%;
+ static const field dart.core::Type genericFunctionTypeLiteral1 = #C1;
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+ typedef td2 = <T extends dart.core::Object? = dynamic>(T%) → T%;
+ typedef td3 = <T1 extends dart.core::Object? = dynamic, T2 extends dart.core::Object? = dynamic>(T2%) → T1%;
+ static const field dart.core::Type genericFunctionTypeLiteral2 = #C1;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib1.dart";
+ import "org-dartlang-test:///lib2.dart";
+
+}
+constants {
+ #C1 = TypeLiteralConstant(<T extends dart.core::Object? = dynamic>(T*) →* T*)
+}
diff --git a/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.2.expect b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.2.expect
new file mode 100644
index 0000000..4c9cfb2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/constant_fileoffset_and_typedef.yaml.world.2.expect
@@ -0,0 +1,21 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib1.dart" as lib1 {
+
+ typedef td1 = <T extends dart.core::Object? = dynamic>(T%) → T%;
+ static const field dart.core::Type genericFunctionTypeLiteral1 = #C1;
+}
+library from "org-dartlang-test:///lib2.dart" as lib2 {
+
+ typedef td2 = <T extends dart.core::Object? = dynamic>(T%) → T%;
+ typedef td3 = <T1 extends dart.core::Object? = dynamic, T2 extends dart.core::Object? = dynamic>(T2%) → T1%;
+ static const field dart.core::Type genericFunctionTypeLiteral2 = #C1;
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib1.dart";
+ import "org-dartlang-test:///lib2.dart";
+
+}
+constants {
+ #C1 = TypeLiteralConstant(<T extends dart.core::Object? = dynamic>(T*) →* T*)
+}
diff --git a/pkg/front_end/testcases/incremental/initializer_not_copied.yaml b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml
new file mode 100644
index 0000000..f6b8c6b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml
@@ -0,0 +1,46 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# 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.
+
+# Recompiling with no change shouldn't change the initializer.
+# In fact, this woukd (currently) print `[null]` when compiled once,
+# but `[a1]` if recompiling main.dart first.
+# http://dartbug.com/48895
+
+type: newworld
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ // @dart=2.9
+ import 'lib.dart';
+ class C extends C3 implements C4 {
+ void noSuchMethod(Invocation invocation) {
+ print(invocation.positionalArguments);
+ }
+ }
+ main() {
+ C c = new C();
+ c.m();
+ }
+ lib.dart: |
+ abstract class C1 {
+ m();
+ }
+ abstract class C2 {
+ m([String a = "a1"]);
+ }
+ abstract class C3 implements C1, C2 {}
+ abstract class C4 {
+ m([covariant String a = "a2"]);
+ }
+
+ expectedLibraryCount: 2
+
+ - entry: main.dart
+ worldType: updated
+ compareToPrevious: true
+ expectInitializeFromDill: false
+ invalidate:
+ - main.dart
+ expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.1.expect b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.1.expect
new file mode 100644
index 0000000..dc9903b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.1.expect
@@ -0,0 +1,63 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+ abstract class C1 extends dart.core::Object {
+ synthetic constructor •() → lib::C1
+ : super dart.core::Object::•()
+ ;
+ abstract method m() → dynamic;
+ }
+ abstract class C2 extends dart.core::Object {
+ synthetic constructor •() → lib::C2
+ : super dart.core::Object::•()
+ ;
+ abstract method m([dart.core::String a = #C1]) → dynamic;
+ }
+ abstract class C3 extends dart.core::Object implements lib::C1, lib::C2 {
+ synthetic constructor •() → lib::C3
+ : super dart.core::Object::•()
+ ;
+ abstract member-signature method m([dart.core::String a = #C1]) → dynamic; -> lib::C2::m
+ }
+ abstract class C4 extends dart.core::Object {
+ synthetic constructor •() → lib::C4
+ : super dart.core::Object::•()
+ ;
+ abstract method m([covariant-by-declaration dart.core::String a = #C2]) → dynamic;
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib.dart";
+
+ class C extends lib::C3 implements lib::C4 {
+ synthetic constructor •() → main::C*
+ : super lib::C3::•()
+ ;
+ method noSuchMethod(dart.core::Invocation* invocation) → void {
+ dart.core::print(invocation.{dart.core::Invocation::positionalArguments}{dart.core::List<dynamic>*});
+ }
+ abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+ abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+ abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+ abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+ no-such-method-forwarder method m([covariant-by-declaration dart.core::String* a]) → dynamic
+ return this.{main::C::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C3, 0, #C4, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(a)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C5))){(dart.core::Invocation*) →* void} as{TypeError,ForDynamic} dynamic;
+ }
+ static method main() → dynamic {
+ main::C* c = new main::C::•();
+ c.{main::C::m}(){([dart.core::String*]) →* dynamic};
+ }
+}
+constants {
+ #C1 = "a1"
+ #C2 = "a2"
+ #C3 = #m
+ #C4 = <dart.core::Type*>[]
+ #C5 = <dart.core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.2.expect b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.2.expect
new file mode 100644
index 0000000..60cba58
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/initializer_not_copied.yaml.world.2.expect
@@ -0,0 +1,63 @@
+main = main::main;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+ abstract class C1 extends dart.core::Object {
+ synthetic constructor •() → lib::C1
+ : super dart.core::Object::•()
+ ;
+ abstract method m() → dynamic;
+ }
+ abstract class C2 extends dart.core::Object {
+ synthetic constructor •() → lib::C2
+ : super dart.core::Object::•()
+ ;
+ abstract method m([dart.core::String a = #C1]) → dynamic;
+ }
+ abstract class C3 extends dart.core::Object implements lib::C1, lib::C2 {
+ synthetic constructor •() → lib::C3
+ : super dart.core::Object::•()
+ ;
+ abstract member-signature method m([dart.core::String a = #C1]) → dynamic; -> lib::C2::m
+ }
+ abstract class C4 extends dart.core::Object {
+ synthetic constructor •() → lib::C4
+ : super dart.core::Object::•()
+ ;
+ abstract method m([covariant-by-declaration dart.core::String a = #C2]) → dynamic;
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib.dart";
+
+ class C extends lib::C3 implements lib::C4 {
+ synthetic constructor •() → main::C*
+ : super lib::C3::•()
+ ;
+ method noSuchMethod(dart.core::Invocation* invocation) → void {
+ dart.core::print(invocation.{dart.core::Invocation::positionalArguments}{dart.core::List<dynamic>*});
+ }
+ abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
+ abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
+ abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
+ abstract member-signature method _simpleInstanceOfTrue(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfTrue
+ abstract member-signature method _simpleInstanceOfFalse(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOfFalse
+ abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+ abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+ abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+ abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+ no-such-method-forwarder method m([covariant-by-declaration dart.core::String* a = #C1]) → dynamic
+ return this.{main::C::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C3, 0, #C4, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(a)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C5))){(dart.core::Invocation*) →* void} as{TypeError,ForDynamic} dynamic;
+ }
+ static method main() → dynamic {
+ main::C* c = new main::C::•();
+ c.{main::C::m}(){([dart.core::String*]) →* dynamic};
+ }
+}
+constants {
+ #C1 = "a1"
+ #C2 = "a2"
+ #C3 = #m
+ #C4 = <dart.core::Type*>[]
+ #C5 = <dart.core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/incremental/late_lowering.yaml.world.2.expect b/pkg/front_end/testcases/incremental/late_lowering.yaml.world.2.expect
new file mode 100644
index 0000000..3537fb6
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/late_lowering.yaml.world.2.expect
@@ -0,0 +1,24 @@
+main = main::main;
+library from "org-dartlang-test:///main.dart" as main {
+
+ part part.dart;
+ class _Class extends dart.core::Object { // from org-dartlang-test:///part.dart
+ field dart.core::int? _#_Class#_privateField = null;
+ field dart.core::bool _#_Class#_privateField#isSet = false;
+ synthetic constructor •() → main::_Class
+ : super dart.core::Object::•()
+ ;
+ get _privateField() → dart.core::int {
+ if(!this.{main::_Class::_#_Class#_privateField#isSet}{dart.core::bool}) {
+ this.{main::_Class::_#_Class#_privateField} = 1;
+ this.{main::_Class::_#_Class#_privateField#isSet} = true;
+ }
+ return let final dart.core::int? #t1 = this.{main::_Class::_#_Class#_privateField}{dart.core::int?} in #t1{dart.core::int};
+ }
+ set _privateField(dart.core::int library org-dartlang-test:///main.dart::_privateField#param) → void {
+ this.{main::_Class::_#_Class#_privateField#isSet} = true;
+ this.{main::_Class::_#_Class#_privateField} = library org-dartlang-test:///main.dart::_privateField#param;
+ }
+ }
+ static method main() → dynamic {}
+}
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml
new file mode 100644
index 0000000..d31202c
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml
@@ -0,0 +1,30 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# 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.
+
+# Recompiling with no change shouldn't change anything.
+# http://dartbug.com/48891
+
+type: newworld
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ import 'lib.dart';
+ class Class2 with TestMixin<String> {}
+ lib.dart: |
+ mixin TestMixin<T> {
+ Future<T> test(Future<T> fetch) async {
+ final response = await fetch;
+ return response as T;
+ }
+ }
+ expectedLibraryCount: 2
+
+ - entry: main.dart
+ worldType: updated
+ compareToPrevious: true
+ expectInitializeFromDill: false
+ invalidate:
+ - main.dart
+ expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.1.expect
new file mode 100644
index 0000000..99d00d7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.1.expect
@@ -0,0 +1,81 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+ abstract class TestMixin<T extends dart.core::Object? = dynamic> extends dart.core::Object /*isMixinDeclaration*/ {
+ method test(covariant-by-class dart.async::Future<lib::TestMixin::T%> fetch) → dart.async::Future<lib::TestMixin::T%> /* futureValueType= lib::TestMixin::T% */ /* originally async */ {
+ final dart.async::_Future<lib::TestMixin::T%> :async_future = new dart.async::_Future::•<lib::TestMixin::T%>();
+ dart.core::bool* :is_sync = false;
+ FutureOr<lib::TestMixin::T%>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → 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_or_exception, dynamic :stack_trace) → dynamic yielding
+ try {
+ #L1:
+ {
+ [yield] let dynamic #t1 = dart.async::_awaitHelper(fetch, :async_op_then, :async_op_error) in null;
+ final lib::TestMixin::T% response = dart._internal::unsafeCast<lib::TestMixin::T%>(:result_or_exception);
+ :return_value = response;
+ break #L1;
+ }
+ dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
+ dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+ :async_op(null, null){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+ }
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib.dart";
+
+ abstract class _Class2&Object&TestMixin extends dart.core::Object implements lib::TestMixin<dart.core::String> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
+ const synthetic constructor •() → main::_Class2&Object&TestMixin
+ : super dart.core::Object::•()
+ ;
+ method /* from org-dartlang-test:///lib.dart */ test(covariant-by-class dart.async::Future<dart.core::String> fetch) → dart.async::Future<dart.core::String> /* futureValueType= dart.core::String */ /* originally async */ {
+ final dart.async::_Future<dart.core::String> :async_future = new dart.async::_Future::•<dart.core::String>();
+ dart.core::bool* :is_sync = false;
+ dart.core::String? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → 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_or_exception, dynamic :stack_trace) → dynamic yielding
+ try {
+ #L2:
+ {
+ [yield] let dynamic #t2 = dart.async::_awaitHelper(fetch, :async_op_then, :async_op_error) in null;
+ final dart.core::String response = dart._internal::unsafeCast<dart.core::String>(:result_or_exception);
+ :return_value = response;
+ break #L2;
+ }
+ dart.async::_completeWithNoFutureOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
+ dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+ :async_op(null, null){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+ }
+ }
+ class Class2 extends main::_Class2&Object&TestMixin {
+ synthetic constructor •() → main::Class2
+ : super main::_Class2&Object&TestMixin::•()
+ ;
+ }
+}
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.2.expect
new file mode 100644
index 0000000..ba9e36d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type.yaml.world.2.expect
@@ -0,0 +1,81 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+ abstract class TestMixin<T extends dart.core::Object? = dynamic> extends dart.core::Object /*isMixinDeclaration*/ {
+ method test(covariant-by-class dart.async::Future<lib::TestMixin::T%> fetch) → dart.async::Future<lib::TestMixin::T%> /* futureValueType= lib::TestMixin::T% */ /* originally async */ {
+ final dart.async::_Future<lib::TestMixin::T%> :async_future = new dart.async::_Future::•<lib::TestMixin::T%>();
+ dart.core::bool* :is_sync = false;
+ FutureOr<lib::TestMixin::T%>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → 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_or_exception, dynamic :stack_trace) → dynamic yielding
+ try {
+ #L1:
+ {
+ [yield] let dynamic #t1 = dart.async::_awaitHelper(fetch, :async_op_then, :async_op_error) in null;
+ final lib::TestMixin::T% response = dart._internal::unsafeCast<lib::TestMixin::T%>(:result_or_exception);
+ :return_value = response;
+ break #L1;
+ }
+ dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
+ dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+ :async_op(null, null){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+ }
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib.dart";
+
+ abstract class _Class2&Object&TestMixin extends dart.core::Object implements lib::TestMixin<dart.core::String> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ {
+ const synthetic constructor •() → main::_Class2&Object&TestMixin
+ : super dart.core::Object::•()
+ ;
+ method /* from org-dartlang-test:///lib.dart */ test(covariant-by-class dart.async::Future<dart.core::String> fetch) → dart.async::Future<dart.core::String> /* futureValueType= dart.core::String */ /* originally async */ {
+ final dart.async::_Future<dart.core::String> :async_future = new dart.async::_Future::•<dart.core::String>();
+ dart.core::bool* :is_sync = false;
+ FutureOr<dart.core::String>? :return_value;
+ (dynamic) → dynamic :async_op_then;
+ (dart.core::Object, dart.core::StackTrace) → 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_or_exception, dynamic :stack_trace) → dynamic yielding
+ try {
+ #L2:
+ {
+ [yield] let dynamic #t2 = dart.async::_awaitHelper(fetch, :async_op_then, :async_op_error) in null;
+ final dart.core::String response = dart._internal::unsafeCast<dart.core::String>(:result_or_exception);
+ :return_value = response;
+ break #L2;
+ }
+ dart.async::_completeOnAsyncReturn(:async_future, :return_value, :is_sync);
+ return;
+ }
+ on dynamic catch(dynamic exception, dart.core::StackTrace stack_trace) {
+ dart.async::_completeOnAsyncError(:async_future, exception, stack_trace, :is_sync);
+ }
+ :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+ :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+ :async_op(null, null){() → dynamic};
+ :is_sync = true;
+ return :async_future;
+ }
+ }
+ class Class2 extends main::_Class2&Object&TestMixin {
+ synthetic constructor •() → main::Class2
+ : super main::_Class2&Object&TestMixin::•()
+ ;
+ }
+}
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml
new file mode 100644
index 0000000..549dbd7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml
@@ -0,0 +1,30 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# 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.
+
+# Recompiling with no change shouldn't change anything.
+# http://dartbug.com/48893
+
+type: newworld
+forceLateLoweringForTesting: true
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ import 'lib.dart';
+ class B implements A {
+ int x = 3;
+ }
+ lib.dart: |
+ abstract class A {
+ late int x;
+ }
+ expectedLibraryCount: 2
+
+ - entry: main.dart
+ worldType: updated
+ compareToPrevious: true
+ expectInitializeFromDill: false
+ invalidate:
+ - main.dart
+ expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.1.expect
new file mode 100644
index 0000000..586c7b0
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.1.expect
@@ -0,0 +1,45 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+ abstract class A extends dart.core::Object {
+ field dart.core::int? _#A#x = null;
+ field dart.core::bool _#A#x#isSet = false;
+ synthetic constructor •() → lib::A
+ : super dart.core::Object::•()
+ ;
+ get x() → dart.core::int
+ return this.{lib::A::_#A#x#isSet}{dart.core::bool} ?{dart.core::int} let final dart.core::int? #t1 = this.{lib::A::_#A#x}{dart.core::int?} in #t1{dart.core::int} : throw new dart._internal::LateError::fieldNI("x");
+ set x(dart.core::int x#param) → void {
+ this.{lib::A::_#A#x#isSet} = true;
+ this.{lib::A::_#A#x} = x#param;
+ }
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib.dart";
+
+ class B extends dart.core::Object implements lib::A {
+ field dart.core::int x = 3;
+ synthetic constructor •() → main::B
+ : super dart.core::Object::•()
+ ;
+ no-such-method-forwarder get /* from org-dartlang-test:///lib.dart */ _#A#x#isSet() → dynamic
+ return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} dynamic;
+ no-such-method-forwarder get /* from org-dartlang-test:///lib.dart */ _#A#x() → dart.core::int?
+ return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C5, 1, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} dart.core::int?;
+ no-such-method-forwarder set /* from org-dartlang-test:///lib.dart */ _#A#x#isSet(dynamic value) → void
+ return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(value)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic};
+ no-such-method-forwarder set /* from org-dartlang-test:///lib.dart */ _#A#x(dart.core::int? value) → void
+ return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C7, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(value)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic};
+ }
+}
+constants {
+ #C1 = #org-dartlang-test:///main.dart::_#A#x#isSet
+ #C2 = <dart.core::Type*>[]
+ #C3 = <dynamic>[]
+ #C4 = <dart.core::Symbol*, dynamic>{)
+ #C5 = #org-dartlang-test:///main.dart::_#A#x
+ #C6 = #org-dartlang-test:///main.dart::_#A#x#isSet=
+ #C7 = #org-dartlang-test:///main.dart::_#A#x=
+}
diff --git a/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.2.expect
new file mode 100644
index 0000000..2ac1aeb
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_change_but_changed_type_02.yaml.world.2.expect
@@ -0,0 +1,45 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+ abstract class A extends dart.core::Object {
+ field dart.core::int? _#A#x = null;
+ field dart.core::bool _#A#x#isSet = false;
+ synthetic constructor •() → lib::A
+ : super dart.core::Object::•()
+ ;
+ get x() → dart.core::int
+ return this.{lib::A::_#A#x#isSet}{dart.core::bool} ?{dart.core::int} let final dart.core::int? #t1 = this.{lib::A::_#A#x}{dart.core::int?} in #t1{dart.core::int} : throw new dart._internal::LateError::fieldNI("x");
+ set x(dart.core::int x#param) → void {
+ this.{lib::A::_#A#x#isSet} = true;
+ this.{lib::A::_#A#x} = x#param;
+ }
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib.dart";
+
+ class B extends dart.core::Object implements lib::A {
+ field dart.core::int x = 3;
+ synthetic constructor •() → main::B
+ : super dart.core::Object::•()
+ ;
+ no-such-method-forwarder get /* from org-dartlang-test:///lib.dart */ _#A#x#isSet() → dart.core::bool
+ return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} dart.core::bool;
+ no-such-method-forwarder get /* from org-dartlang-test:///lib.dart */ _#A#x() → dart.core::int?
+ return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C5, 1, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic} as{TypeError,ForDynamic,ForNonNullableByDefault} dart.core::int?;
+ no-such-method-forwarder set /* from org-dartlang-test:///lib.dart */ _#A#x#isSet(dart.core::bool value) → void
+ return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C6, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(value)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic};
+ no-such-method-forwarder set /* from org-dartlang-test:///lib.dart */ _#A#x(dart.core::int? value) → void
+ return this.{dart.core::Object::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C7, 2, #C2, dart.core::List::unmodifiable<dynamic>(dart.core::_GrowableList::_literal1<dynamic>(value)), dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → dynamic};
+ }
+}
+constants {
+ #C1 = #org-dartlang-test:///main.dart::_#A#x#isSet
+ #C2 = <dart.core::Type*>[]
+ #C3 = <dynamic>[]
+ #C4 = <dart.core::Symbol*, dynamic>{)
+ #C5 = #org-dartlang-test:///main.dart::_#A#x
+ #C6 = #org-dartlang-test:///main.dart::_#A#x#isSet=
+ #C7 = #org-dartlang-test:///main.dart::_#A#x=
+}
diff --git a/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml
new file mode 100644
index 0000000..eb1b359
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml
@@ -0,0 +1,35 @@
+# Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+# 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.
+
+# Recompiling shouldn't change the InstanceInvocation.interfaceTargetReference.
+# http://dartbug.com/48892
+
+type: newworld
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ import "lib1.dart";
+ main() {
+ Y y = new Y();
+ y.foo();
+ }
+ lib1.dart: |
+ class X {
+ void foo() => print("foo");
+ }
+ class Y implements X {
+ void noSuchMethod(Invocation _) {
+ print("Hello from noSuchMethod");
+ }
+ }
+ expectedLibraryCount: 2
+
+ - entry: main.dart
+ worldType: updated
+ compareToPrevious: true
+ expectInitializeFromDill: false
+ invalidate:
+ - main.dart
+ expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.1.expect
new file mode 100644
index 0000000..f9a6cfb
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.1.expect
@@ -0,0 +1,36 @@
+main = main::main;
+library from "org-dartlang-test:///lib1.dart" as lib1 {
+
+ class X extends dart.core::Object {
+ synthetic constructor •() → lib1::X
+ : super dart.core::Object::•()
+ ;
+ method foo() → void
+ return dart.core::print("foo");
+ }
+ class Y extends dart.core::Object implements lib1::X {
+ synthetic constructor •() → lib1::Y
+ : super dart.core::Object::•()
+ ;
+ method noSuchMethod(dart.core::Invocation _) → void {
+ dart.core::print("Hello from noSuchMethod");
+ }
+ no-such-method-forwarder method foo() → void
+ return this.{lib1::Y::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → void};
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib1.dart";
+
+ static method main() → dynamic {
+ lib1::Y y = new lib1::Y::•();
+ y.{lib1::X::foo}(){() → void};
+ }
+}
+constants {
+ #C1 = #foo
+ #C2 = <dart.core::Type*>[]
+ #C3 = <dynamic>[]
+ #C4 = <dart.core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.2.expect
new file mode 100644
index 0000000..b99b734
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/no_such_method_forwarder.yaml.world.2.expect
@@ -0,0 +1,36 @@
+main = main::main;
+library from "org-dartlang-test:///lib1.dart" as lib1 {
+
+ class X extends dart.core::Object {
+ synthetic constructor •() → lib1::X
+ : super dart.core::Object::•()
+ ;
+ method foo() → void
+ return dart.core::print("foo");
+ }
+ class Y extends dart.core::Object implements lib1::X {
+ synthetic constructor •() → lib1::Y
+ : super dart.core::Object::•()
+ ;
+ method noSuchMethod(dart.core::Invocation _) → void {
+ dart.core::print("Hello from noSuchMethod");
+ }
+ no-such-method-forwarder method foo() → void
+ return this.{lib1::Y::noSuchMethod}(new dart.core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, dart.core::Map::unmodifiable<dart.core::Symbol*, dynamic>(#C4))){(dart.core::Invocation) → void};
+ }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+ import "org-dartlang-test:///lib1.dart";
+
+ static method main() → dynamic {
+ lib1::Y y = new lib1::Y::•();
+ y.{lib1::Y::foo}(){() → void};
+ }
+}
+constants {
+ #C1 = #foo
+ #C2 = <dart.core::Type*>[]
+ #C3 = <dynamic>[]
+ #C4 = <dart.core::Symbol*, dynamic>{)
+}
diff --git a/pkg/front_end/testcases/inference_update_1/folder.options b/pkg/front_end/testcases/inference_update_1/folder.options
new file mode 100644
index 0000000..722e700
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/folder.options
@@ -0,0 +1 @@
+--enable-experiment=inference-update-1
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart
new file mode 100644
index 0000000..454d46f
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for 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 that when the feature is enabled, if an invocation argument is a
+// closure, write captures made by that closure do not take effect until after
+// the invocation. This is a minor improvement to flow analysis that falls
+// naturally out of the fact that closures are analyzed last (so that their
+// types can depend on the types of other arguments).
+
+withUnnamedArguments(int? i, void Function(void Function(), Object?) f) {
+ if (i != null) {
+ f(() {
+ i = null;
+ }, i);
+ i;
+ }
+}
+
+withNamedArguments(
+ int? i, void Function({required void Function() g, Object? x}) f) {
+ if (i != null) {
+ f(
+ g: () {
+ i = null;
+ },
+ x: i);
+ i;
+ }
+}
+
+withIdentical_lhs(int? i) {
+ if (i != null) {
+ i;
+ identical(() {
+ i = null;
+ }, i);
+ i;
+ }
+}
+
+withIdentical_rhs(int? i) {
+ if (i != null) {
+ identical(i, () {
+ i = null;
+ });
+ i;
+ }
+}
+
+class B {
+ B(Object? x, void Function() g, Object? y);
+ B.redirectingConstructorInvocation(int? i)
+ : this(i!, () {
+ i = null;
+ }, i);
+}
+
+class C extends B {
+ C.superConstructorInvocation(int? i)
+ : super(i!, () {
+ i = null;
+ }, i);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline.expect
new file mode 100644
index 0000000..b846752
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+withUnnamedArguments(int? i, void Function(void Function(), Object?) f) {}
+withNamedArguments(
+ int? i, void Function({required void Function() g, Object? x}) f) {}
+withIdentical_lhs(int? i) {}
+withIdentical_rhs(int? i) {}
+
+class B {
+ B(Object? x, void Function() g, Object? y);
+ B.redirectingConstructorInvocation(int? i)
+ : this(i!, () {
+ i = null;
+ }, i);
+}
+
+class C extends B {
+ C.superConstructorInvocation(int? i)
+ : super(i!, () {
+ i = null;
+ }, i);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f4cf2ee
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class B {
+ B(Object? x, void Function() g, Object? y);
+ B.redirectingConstructorInvocation(int? i)
+ : this(i!, () {
+ i = null;
+ }, i);
+}
+
+class C extends B {
+ C.superConstructorInvocation(int? i)
+ : super(i!, () {
+ i = null;
+ }, i);
+}
+
+main() {}
+withIdentical_lhs(int? i) {}
+withIdentical_rhs(int? i) {}
+withNamedArguments(
+ int? i, void Function({required void Function() g, Object? x}) f) {}
+withUnnamedArguments(int? i, void Function(void Function(), Object?) f) {}
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.expect
new file mode 100644
index 0000000..7e1a0ea
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+ constructor •(core::Object? x, () → void g, core::Object? y) → self::B
+ : super core::Object::•()
+ ;
+ constructor redirectingConstructorInvocation(core::int? i) → self::B
+ : this self::B::•(i!, () → void {
+ i = null;
+ }, i{core::int})
+ ;
+}
+class C extends self::B {
+ constructor superConstructorInvocation(core::int? i) → self::C
+ : super self::B::•(i!, () → void {
+ i = null;
+ }, i{core::int})
+ ;
+}
+static method withUnnamedArguments(core::int? i, (() → void, core::Object?) → void f) → dynamic {
+ if(!(i == null)) {
+ f(() → void {
+ i = null;
+ }, i{core::int}){(() → void, core::Object?) → void};
+ i;
+ }
+}
+static method withNamedArguments(core::int? i, ({required g: () → void, x: core::Object?}) → void f) → dynamic {
+ if(!(i == null)) {
+ f(g: () → void {
+ i = null;
+ }, x: i{core::int}){({required g: () → void, x: core::Object?}) → void};
+ i;
+ }
+}
+static method withIdentical_lhs(core::int? i) → dynamic {
+ if(!(i == null)) {
+ i{core::int};
+ core::identical(() → Null {
+ i = null;
+ }, i{core::int});
+ i;
+ }
+}
+static method withIdentical_rhs(core::int? i) → dynamic {
+ if(!(i == null)) {
+ core::identical(i{core::int}, () → Null {
+ i = null;
+ });
+ i;
+ }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.modular.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.modular.expect
new file mode 100644
index 0000000..7e1a0ea
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.modular.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+ constructor •(core::Object? x, () → void g, core::Object? y) → self::B
+ : super core::Object::•()
+ ;
+ constructor redirectingConstructorInvocation(core::int? i) → self::B
+ : this self::B::•(i!, () → void {
+ i = null;
+ }, i{core::int})
+ ;
+}
+class C extends self::B {
+ constructor superConstructorInvocation(core::int? i) → self::C
+ : super self::B::•(i!, () → void {
+ i = null;
+ }, i{core::int})
+ ;
+}
+static method withUnnamedArguments(core::int? i, (() → void, core::Object?) → void f) → dynamic {
+ if(!(i == null)) {
+ f(() → void {
+ i = null;
+ }, i{core::int}){(() → void, core::Object?) → void};
+ i;
+ }
+}
+static method withNamedArguments(core::int? i, ({required g: () → void, x: core::Object?}) → void f) → dynamic {
+ if(!(i == null)) {
+ f(g: () → void {
+ i = null;
+ }, x: i{core::int}){({required g: () → void, x: core::Object?}) → void};
+ i;
+ }
+}
+static method withIdentical_lhs(core::int? i) → dynamic {
+ if(!(i == null)) {
+ i{core::int};
+ core::identical(() → Null {
+ i = null;
+ }, i{core::int});
+ i;
+ }
+}
+static method withIdentical_rhs(core::int? i) → dynamic {
+ if(!(i == null)) {
+ core::identical(i{core::int}, () → Null {
+ i = null;
+ });
+ i;
+ }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.outline.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.outline.expect
new file mode 100644
index 0000000..f98b778
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.outline.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+ constructor •(core::Object? x, () → void g, core::Object? y) → self::B
+ ;
+ constructor redirectingConstructorInvocation(core::int? i) → self::B
+ ;
+}
+class C extends self::B {
+ constructor superConstructorInvocation(core::int? i) → self::C
+ ;
+}
+static method withUnnamedArguments(core::int? i, (() → void, core::Object?) → void f) → dynamic
+ ;
+static method withNamedArguments(core::int? i, ({required g: () → void, x: core::Object?}) → void f) → dynamic
+ ;
+static method withIdentical_lhs(core::int? i) → dynamic
+ ;
+static method withIdentical_rhs(core::int? i) → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.transformed.expect b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.transformed.expect
new file mode 100644
index 0000000..7e1a0ea
--- /dev/null
+++ b/pkg/front_end/testcases/inference_update_1/write_capture_deferral.dart.weak.transformed.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class B extends core::Object {
+ constructor •(core::Object? x, () → void g, core::Object? y) → self::B
+ : super core::Object::•()
+ ;
+ constructor redirectingConstructorInvocation(core::int? i) → self::B
+ : this self::B::•(i!, () → void {
+ i = null;
+ }, i{core::int})
+ ;
+}
+class C extends self::B {
+ constructor superConstructorInvocation(core::int? i) → self::C
+ : super self::B::•(i!, () → void {
+ i = null;
+ }, i{core::int})
+ ;
+}
+static method withUnnamedArguments(core::int? i, (() → void, core::Object?) → void f) → dynamic {
+ if(!(i == null)) {
+ f(() → void {
+ i = null;
+ }, i{core::int}){(() → void, core::Object?) → void};
+ i;
+ }
+}
+static method withNamedArguments(core::int? i, ({required g: () → void, x: core::Object?}) → void f) → dynamic {
+ if(!(i == null)) {
+ f(g: () → void {
+ i = null;
+ }, x: i{core::int}){({required g: () → void, x: core::Object?}) → void};
+ i;
+ }
+}
+static method withIdentical_lhs(core::int? i) → dynamic {
+ if(!(i == null)) {
+ i{core::int};
+ core::identical(() → Null {
+ i = null;
+ }, i{core::int});
+ i;
+ }
+}
+static method withIdentical_rhs(core::int? i) → dynamic {
+ if(!(i == null)) {
+ core::identical(i{core::int}, () → Null {
+ i = null;
+ });
+ i;
+ }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart b/pkg/front_end/testcases/regress/issue_36669.dart
index 48a19bb..64295d2 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart
+++ b/pkg/front_end/testcases/regress/issue_36669.dart
@@ -2,10 +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.9
-class NoUnnamedConstuctor {
- NoUnnamedConstuctor._();
+class NoUnnamedConstructor {
+ NoUnnamedConstructor._();
}
class MixMeIn {}
-class Foo extends NoUnnamedConstuctor with MixMeIn {}
+class Foo extends NoUnnamedConstructor with MixMeIn {}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline.expect b/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline.expect
index 90f2098..04ff88d 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline.expect
@@ -1,8 +1,8 @@
// @dart = 2.9
-class NoUnnamedConstuctor {
- NoUnnamedConstuctor._();
+class NoUnnamedConstructor {
+ NoUnnamedConstructor._();
}
class MixMeIn {}
-class Foo extends NoUnnamedConstuctor with MixMeIn {}
+class Foo extends NoUnnamedConstructor with MixMeIn {}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline_modelled.expect
index ef3c45e..6fa6b0d 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.textual_outline_modelled.expect
@@ -1,8 +1,8 @@
// @dart = 2.9
-class Foo extends NoUnnamedConstuctor with MixMeIn {}
+class Foo extends NoUnnamedConstructor with MixMeIn {}
class MixMeIn {}
-class NoUnnamedConstuctor {
- NoUnnamedConstuctor._();
+class NoUnnamedConstructor {
+ NoUnnamedConstructor._();
}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.weak.expect b/pkg/front_end/testcases/regress/issue_36669.dart.weak.expect
index 0c77dc9..2eec808 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.weak.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.weak.expect
@@ -2,15 +2,15 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstuctor with MixMeIn', has no unnamed constructor that takes no arguments.
-// class Foo extends NoUnnamedConstuctor with MixMeIn {}
+// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstructor with MixMeIn', has no unnamed constructor that takes no arguments.
+// class Foo extends NoUnnamedConstructor with MixMeIn {}
// ^
//
import self as self;
import "dart:core" as core;
-class NoUnnamedConstuctor extends core::Object {
- constructor _() → self::NoUnnamedConstuctor*
+class NoUnnamedConstructor extends core::Object {
+ constructor _() → self::NoUnnamedConstructor*
: super core::Object::•()
;
abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -39,12 +39,12 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn /*isAnonymousMixin*/ {
- synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
- : super self::NoUnnamedConstuctor::_()
+abstract class _Foo&NoUnnamedConstructor&MixMeIn = self::NoUnnamedConstructor with self::MixMeIn /*isAnonymousMixin*/ {
+ synthetic constructor _() → self::_Foo&NoUnnamedConstructor&MixMeIn*
+ : super self::NoUnnamedConstructor::_()
;
}
-class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+class Foo extends self::_Foo&NoUnnamedConstructor&MixMeIn {
synthetic constructor •() → self::Foo*
: invalid-initializer
;
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.weak.modular.expect b/pkg/front_end/testcases/regress/issue_36669.dart.weak.modular.expect
index 0c77dc9..2eec808 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.weak.modular.expect
@@ -2,15 +2,15 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstuctor with MixMeIn', has no unnamed constructor that takes no arguments.
-// class Foo extends NoUnnamedConstuctor with MixMeIn {}
+// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstructor with MixMeIn', has no unnamed constructor that takes no arguments.
+// class Foo extends NoUnnamedConstructor with MixMeIn {}
// ^
//
import self as self;
import "dart:core" as core;
-class NoUnnamedConstuctor extends core::Object {
- constructor _() → self::NoUnnamedConstuctor*
+class NoUnnamedConstructor extends core::Object {
+ constructor _() → self::NoUnnamedConstructor*
: super core::Object::•()
;
abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -39,12 +39,12 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn /*isAnonymousMixin*/ {
- synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
- : super self::NoUnnamedConstuctor::_()
+abstract class _Foo&NoUnnamedConstructor&MixMeIn = self::NoUnnamedConstructor with self::MixMeIn /*isAnonymousMixin*/ {
+ synthetic constructor _() → self::_Foo&NoUnnamedConstructor&MixMeIn*
+ : super self::NoUnnamedConstructor::_()
;
}
-class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+class Foo extends self::_Foo&NoUnnamedConstructor&MixMeIn {
synthetic constructor •() → self::Foo*
: invalid-initializer
;
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.weak.outline.expect b/pkg/front_end/testcases/regress/issue_36669.dart.weak.outline.expect
index 1f49167..2799c79 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.weak.outline.expect
@@ -2,8 +2,8 @@
import self as self;
import "dart:core" as core;
-class NoUnnamedConstuctor extends core::Object {
- constructor _() → self::NoUnnamedConstuctor*
+class NoUnnamedConstructor extends core::Object {
+ constructor _() → self::NoUnnamedConstructor*
;
abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
@@ -30,12 +30,12 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn = self::NoUnnamedConstuctor with self::MixMeIn /*isAnonymousMixin*/ {
- synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
- : super self::NoUnnamedConstuctor::_()
+abstract class _Foo&NoUnnamedConstructor&MixMeIn = self::NoUnnamedConstructor with self::MixMeIn /*isAnonymousMixin*/ {
+ synthetic constructor _() → self::_Foo&NoUnnamedConstructor&MixMeIn*
+ : super self::NoUnnamedConstructor::_()
;
}
-class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+class Foo extends self::_Foo&NoUnnamedConstructor&MixMeIn {
synthetic constructor •() → self::Foo*
;
}
diff --git a/pkg/front_end/testcases/regress/issue_36669.dart.weak.transformed.expect b/pkg/front_end/testcases/regress/issue_36669.dart.weak.transformed.expect
index 2edcce4..b37611c 100644
--- a/pkg/front_end/testcases/regress/issue_36669.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36669.dart.weak.transformed.expect
@@ -2,15 +2,15 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstuctor with MixMeIn', has no unnamed constructor that takes no arguments.
-// class Foo extends NoUnnamedConstuctor with MixMeIn {}
+// pkg/front_end/testcases/regress/issue_36669.dart:11:7: Error: The superclass, 'NoUnnamedConstructor with MixMeIn', has no unnamed constructor that takes no arguments.
+// class Foo extends NoUnnamedConstructor with MixMeIn {}
// ^
//
import self as self;
import "dart:core" as core;
-class NoUnnamedConstuctor extends core::Object {
- constructor _() → self::NoUnnamedConstuctor*
+class NoUnnamedConstructor extends core::Object {
+ constructor _() → self::NoUnnamedConstructor*
: super core::Object::•()
;
abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
@@ -39,12 +39,12 @@
abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
-abstract class _Foo&NoUnnamedConstuctor&MixMeIn extends self::NoUnnamedConstuctor implements self::MixMeIn /*isAnonymousMixin,isEliminatedMixin*/ {
- synthetic constructor _() → self::_Foo&NoUnnamedConstuctor&MixMeIn*
- : super self::NoUnnamedConstuctor::_()
+abstract class _Foo&NoUnnamedConstructor&MixMeIn extends self::NoUnnamedConstructor implements self::MixMeIn /*isAnonymousMixin,isEliminatedMixin*/ {
+ synthetic constructor _() → self::_Foo&NoUnnamedConstructor&MixMeIn*
+ : super self::NoUnnamedConstructor::_()
;
}
-class Foo extends self::_Foo&NoUnnamedConstuctor&MixMeIn {
+class Foo extends self::_Foo&NoUnnamedConstructor&MixMeIn {
synthetic constructor •() → self::Foo*
: invalid-initializer
;
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 762a17d..f805d8e 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -16,6 +16,13 @@
const_functions/const_functions_list: SemiFuzzCrash
generic_metadata/typedef_generic_types_in_arguments_and_bounds: SemiFuzzCrash
+dart2js/mixin_from_opt_in/main: SemiFuzzFailure # seems like the difference between normal and no-link version: it goes from InstanceInvocation to InvalidExpression
+dart2js/mixin_from_opt_in/main.no_link: SemiFuzzFailure # seems like the difference between normal and no-link version: it goes from InstanceInvocation to InvalidExpression
+late_lowering/private_members: SemiFuzzFailure # Reproduced in https://dart-review.googlesource.com/c/sdk/+/242285
+macros/multiple_imports: SemiFuzzFailure # probably augment imports that isn't split correctly.
+nnbd/constants: SemiFuzzFailure # Reproduced in https://dart-review.googlesource.com/c/sdk/+/242441
+nnbd/flutter_issue64155: SemiFuzzFailure # Reproduced in https://dart-review.googlesource.com/c/sdk/+/242443
+
# These tests have "privacy issues" and isn't compatiable with splitting files (fuzzing):
dart2js/mixin_default_values/main: semiFuzzFailureOnForceRebuildBodies # private method
dartdevc/factory_patch/main: semiFuzzFailureOnForceRebuildBodies # needs custom libraries.json (and platform?) not setup here
@@ -32,6 +39,7 @@
nnbd/nullable_extension: semiFuzzFailureOnForceRebuildBodies # unnamed extension
nnbd/nullable_setter: semiFuzzFailureOnForceRebuildBodies # unnamed extension
none/mixin_super: semiFuzzFailureOnForceRebuildBodies # has private name mixin
+dart2js/tear_off_patch/main: semiFuzzFailureOnForceRebuildBodies # needs custom libraries.json (and platform?) not setup here
constructor_tearoffs/call_instantiation: TypeCheckError
constructor_tearoffs/lowering/invalid_redirect: VerificationError
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 6097d2c..68ae6c1 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -10,6 +10,32 @@
no_such_method_forwarders/abstract_override_abstract_different_type: SemiFuzzFailure
no_such_method_forwarders/abstract_override_with_different_signature: SemiFuzzFailure
+dart2js/tear_off_patch/main: semiFuzzFailureOnForceRebuildBodies # needs custom libraries.json (and platform?) not setup here
+general/constants/with_unevaluated_agnostic/various_2: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242441
+general/flutter_issue64155: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242443
+general/no_such_method_forwarder: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242444
+general/tear_off_patch/main: semiFuzzFailureOnForceRebuildBodies # needs custom libraries.json (and platform?) not setup here
+general/with_dependencies/issue_43084/issue_43084: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242543
+late_lowering/issue41436b: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242445
+late_lowering/issue41436c/issue41436c: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242445
+late_lowering/late_override: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242445
+late_lowering/private_members: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242285
+macros/multiple_imports: SemiFuzzFailure # probably augment imports that isn't split correctly.
+nnbd_mixed/const_canonical_type: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242441
+nnbd_mixed/hierarchy/in_dill_out_in/in_out_in: SemiFuzzFailure # lots of stuff --- not digging in for now
+nnbd_mixed/hierarchy/in_out_dill_in/in_out_in: SemiFuzzFailure # lots of stuff --- not digging in for now
+nnbd_mixed/hierarchy/in_out_in: SemiFuzzFailure # lots of stuff --- not digging in for now
+nnbd_mixed/issue43988/main: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242540 and https://dart-review.googlesource.com/c/sdk/+/242446
+nnbd_mixed/issue43988/main.no_link: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242540 and https://dart-review.googlesource.com/c/sdk/+/242446
+nnbd_mixed/member_inheritance_from_opt_in: SemiFuzzFailure # https://dart-review.googlesource.com/c/sdk/+/242446
+nnbd/constants: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242441
+nnbd/flutter_issue64155: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242443
+no_such_method_forwarders/abstract_accessors_from_field_one_defined: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242444
+no_such_method_forwarders/abstract_accessors_from_field_with_substitution: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242444
+no_such_method_forwarders/abstract_accessors_from_field: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242444
+no_such_method_forwarders/default_argument_values: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242444
+variance/generic_covariance_sound_variance: SemiFuzzFailure # Looks similar to https://dart-review.googlesource.com/c/sdk/+/242444
+
dart2js/flutter_issue94561/main: SemiFuzzFailure
dart2js/flutter_issue94561/main.no_link: SemiFuzzFailure
dart2js/late_fields: SemiFuzzFailure
diff --git a/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart b/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
index df2501c..6df8f38 100644
--- a/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
+++ b/pkg/nnbd_migration/test/front_end/nnbd_migration_test_base.dart
@@ -233,8 +233,7 @@
instrumentation: instrumentationListener,
removeViaComments: removeViaComments,
warnOnWeakCode: warnOnWeakCode);
- Future<void> _forEachPath(
- void Function(ResolvedUnitResult) callback) async {
+ Future<void> forEachPath(void Function(ResolvedUnitResult) callback) async {
for (var testPath in testPaths) {
var result = await driver!.currentSession.getResolvedUnit(testPath!)
as ResolvedUnitResult;
@@ -242,10 +241,10 @@
}
}
- await _forEachPath(migration.prepareInput);
+ await forEachPath(migration.prepareInput);
expect(migration.unmigratedDependencies, isEmpty);
- await _forEachPath(migration.processInput);
- await _forEachPath(migration.finalizeInput);
+ await forEachPath(migration.processInput);
+ await forEachPath(migration.finalizeInput);
migration.finish();
// Build the migration info.
var info = instrumentationListener.data;
diff --git a/runtime/tests/vm/dart/regress_48323_1_test.dart b/runtime/tests/vm/dart/regress_48323_1_test.dart
new file mode 100644
index 0000000..d9c7595
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_48323_1_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for 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 https://github.com/dart-lang/sdk/issues/48323.
+// Verifies that class finalization doesn't crash when seeing
+// superclass with type arguments which were not finalized yet.
+
+abstract class GraphNode extends Comparable<dynamic> {
+ int compareTo(dynamic other) => 0;
+}
+
+abstract class StreamNode<T> extends GraphNode {}
+
+class TransformNode<S, T> extends StreamNode<T> {}
+
+main() {
+ print(TransformNode());
+}
diff --git a/runtime/tests/vm/dart_2/regress_48323_1_test.dart b/runtime/tests/vm/dart_2/regress_48323_1_test.dart
new file mode 100644
index 0000000..c71670b
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_48323_1_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for 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 https://github.com/dart-lang/sdk/issues/48323.
+// Verifies that class finalization doesn't crash when seeing
+// superclass with type arguments which were not finalized yet.
+
+// @dart = 2.9
+
+abstract class GraphNode extends Comparable<dynamic> {
+ int compareTo(dynamic other) => 0;
+}
+
+abstract class StreamNode<T> extends GraphNode {}
+
+class TransformNode<S, T> extends StreamNode<T> {}
+
+main() {
+ print(TransformNode());
+}
diff --git a/runtime/vm/app_snapshot.h b/runtime/vm/app_snapshot.h
index ce084c0..118ca9c 100644
--- a/runtime/vm/app_snapshot.h
+++ b/runtime/vm/app_snapshot.h
@@ -324,6 +324,9 @@
void Write(T value) {
BaseWriteStream::Raw<sizeof(T), T>::Write(stream_, value);
}
+ void WriteRefId(intptr_t value) {
+ stream_->WriteRefId(value);
+ }
void WriteUnsigned(intptr_t value) { stream_->WriteUnsigned(value); }
void WriteUnsigned64(uint64_t value) { stream_->WriteUnsigned(value); }
@@ -341,7 +344,7 @@
void WriteRootRef(ObjectPtr object, const char* name = nullptr) {
intptr_t id = RefId(object);
- WriteUnsigned(id);
+ WriteRefId(id);
if (profile_writer_ != nullptr) {
profile_writer_->AddRoot(GetProfileId(object), name);
}
@@ -359,7 +362,7 @@
void WriteElementRef(ObjectPtr object, intptr_t index) {
AttributeElementRef(object, index);
- WriteUnsigned(RefId(object));
+ WriteRefId(RefId(object));
}
void AttributePropertyRef(ObjectPtr object, const char* property) {
@@ -369,12 +372,12 @@
void WritePropertyRef(ObjectPtr object, const char* property) {
AttributePropertyRef(object, property);
- WriteUnsigned(RefId(object));
+ WriteRefId(RefId(object));
}
void WriteOffsetRef(ObjectPtr object, intptr_t offset) {
intptr_t id = RefId(object);
- WriteUnsigned(id);
+ WriteRefId(id);
if (profile_writer_ != nullptr) {
if (auto const property = offsets_table_->FieldNameForOffset(
object_currently_writing_.cid_, offset)) {
@@ -634,6 +637,7 @@
T Read() {
return ReadStream::Raw<sizeof(T), T>::Read(&stream_);
}
+ intptr_t ReadRefId() { return stream_.ReadRefId(); }
intptr_t ReadUnsigned() { return stream_.ReadUnsigned(); }
uint64_t ReadUnsigned64() { return stream_.ReadUnsigned<uint64_t>(); }
void ReadBytes(uint8_t* addr, intptr_t len) { stream_.ReadBytes(addr, len); }
@@ -673,7 +677,7 @@
static intptr_t CodeIndexToClusterIndex(const InstructionsTable& table,
intptr_t code_index);
- ObjectPtr ReadRef() { return Ref(ReadUnsigned()); }
+ ObjectPtr ReadRef() { return Ref(ReadRefId()); }
template <typename T, typename... P>
void ReadFromTo(T obj, P&&... params) {
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc
index fd70709..cc1c65b 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.cc
+++ b/runtime/vm/compiler/assembler/assembler_riscv.cc
@@ -3704,8 +3704,33 @@
lx(FP, Address(SP, 0 * target::kWordSize));
lx(RA, Address(SP, 1 * target::kWordSize));
addi(SP, SP, 2 * target::kWordSize);
+}
- // TODO(riscv): When we know the stack depth, we can avoid updating SP twice.
+void Assembler::LeaveDartFrame(intptr_t fp_sp_dist) {
+ intptr_t pp_offset =
+ target::frame_layout.saved_caller_pp_from_fp * target::kWordSize -
+ fp_sp_dist;
+ intptr_t fp_offset =
+ target::frame_layout.saved_caller_fp_from_fp * target::kWordSize -
+ fp_sp_dist;
+ intptr_t ra_offset =
+ target::frame_layout.saved_caller_pc_from_fp * target::kWordSize -
+ fp_sp_dist;
+ if (!IsITypeImm(pp_offset) || !IsITypeImm(fp_offset) ||
+ !IsITypeImm(ra_offset)) {
+ // Shorter to update SP twice than generate large immediates.
+ LeaveDartFrame();
+ return;
+ }
+
+ if (!FLAG_precompiled_mode) {
+ lx(PP, Address(SP, pp_offset));
+ subi(PP, PP, kHeapObjectTag);
+ }
+ set_constant_pool_allowed(false);
+ lx(FP, Address(SP, fp_offset));
+ lx(RA, Address(SP, ra_offset));
+ addi(SP, SP, -fp_sp_dist);
}
void Assembler::CallRuntime(const RuntimeEntry& entry,
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.h b/runtime/vm/compiler/assembler/assembler_riscv.h
index 44424ae..985ce81 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.h
+++ b/runtime/vm/compiler/assembler/assembler_riscv.h
@@ -1233,6 +1233,7 @@
void EnterDartFrame(intptr_t frame_size, Register new_pp = kNoRegister);
void EnterOsrFrame(intptr_t extra_size, Register new_pp = kNoRegister);
void LeaveDartFrame();
+ void LeaveDartFrame(intptr_t fp_sp_dist);
// For non-leaf runtime calls. For leaf runtime calls, use LeafRuntimeScope,
void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index eabdbb0..6f556e5 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -1584,7 +1584,8 @@
// Allocate a register that is not explictly blocked.
static Register AllocateFreeRegister(bool* blocked_registers) {
- for (intptr_t regno = 0; regno < kNumberOfCpuRegisters; regno++) {
+ for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+ intptr_t regno = (i + kRegisterAllocationBias) % kNumberOfCpuRegisters;
if (!blocked_registers[regno]) {
blocked_registers[regno] = true;
return static_cast<Register>(regno);
@@ -1615,22 +1616,6 @@
bool blocked_registers[kNumberOfCpuRegisters];
bool blocked_fpu_registers[kNumberOfFpuRegisters];
- // Connect input with peephole output for some special cases. All other
- // cases are handled by simply allocating registers and generating code.
- if (top_of_stack_ != nullptr) {
- const intptr_t p = locs->input_count() - 1;
- Location peephole = top_of_stack_->locs()->out(0);
- if ((instr->RequiredInputRepresentation(p) == kTagged) &&
- (locs->in(p).IsUnallocated() || locs->in(p).IsConstant())) {
- // If input is unallocated, match with an output register, if set. Also,
- // if input is a direct constant, but the peephole output is a register,
- // use that register to avoid wasting the already generated code.
- if (peephole.IsRegister()) {
- locs->set_in(p, Location::RegisterLocation(peephole.reg()));
- }
- }
- }
-
// Block all registers globally reserved by the assembler, etc and mark
// the rest as free.
for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
@@ -1671,6 +1656,23 @@
}
}
+ // Connect input with peephole output for some special cases. All other
+ // cases are handled by simply allocating registers and generating code.
+ if (top_of_stack_ != nullptr) {
+ const intptr_t p = locs->input_count() - 1;
+ Location peephole = top_of_stack_->locs()->out(0);
+ if ((instr->RequiredInputRepresentation(p) == kTagged) &&
+ (locs->in(p).IsUnallocated() || locs->in(p).IsConstant())) {
+ // If input is unallocated, match with an output register, if set. Also,
+ // if input is a direct constant, but the peephole output is a register,
+ // use that register to avoid wasting the already generated code.
+ if (peephole.IsRegister() && !blocked_registers[peephole.reg()]) {
+ locs->set_in(p, Location::RegisterLocation(peephole.reg()));
+ blocked_registers[peephole.reg()] = true;
+ }
+ }
+ }
+
if (locs->out(0).IsRegister()) {
// Fixed output registers are allowed to overlap with
// temps and inputs.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
index 8671e2e..46a6ba5 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_riscv.cc
@@ -346,14 +346,16 @@
}
__ Comment("Initialize spill slots");
+ const intptr_t fp_to_sp_delta =
+ num_locals + compiler::target::frame_layout.dart_fixed_frame_size;
for (intptr_t i = 0; i < num_locals; ++i) {
const intptr_t slot_index =
compiler::target::frame_layout.FrameSlotForVariableIndex(-i);
Register value_reg =
slot_index == args_desc_slot ? ARGS_DESC_REG : NULL_REG;
- __ StoreToOffset(value_reg, FP, slot_index * kWordSize);
- // TODO(riscv): Using an SP-relative address instead of an FP-relative
- // address would allow for compressed instructions.
+ // SP-relative addresses allow for compressed instructions.
+ __ StoreToOffset(value_reg, SP,
+ (slot_index + fp_to_sp_delta) * kWordSize);
}
}
diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc
index b24fdb4..a2d70f7 100644
--- a/runtime/vm/compiler/backend/il_riscv.cc
+++ b/runtime/vm/compiler/backend/il_riscv.cc
@@ -469,14 +469,14 @@
return;
}
-#if defined(DEBUG)
- compiler::Label stack_ok;
- __ Comment("Stack Check");
const intptr_t fp_sp_dist =
(compiler::target::frame_layout.first_local_from_fp + 1 -
compiler->StackSize()) *
kWordSize;
ASSERT(fp_sp_dist <= 0);
+#if defined(DEBUG)
+ compiler::Label stack_ok;
+ __ Comment("Stack Check");
__ sub(TMP, SP, FP);
__ CompareImmediate(TMP, fp_sp_dist);
__ BranchIf(EQ, &stack_ok, compiler::Assembler::kNearJump);
@@ -487,7 +487,7 @@
if (yield_index() != UntaggedPcDescriptors::kInvalidYieldIndex) {
compiler->EmitYieldPositionMetadata(source(), yield_index());
}
- __ LeaveDartFrame(); // Disallows constant pool use.
+ __ LeaveDartFrame(fp_sp_dist); // Disallows constant pool use.
__ ret();
// 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.
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index 266b485..de3c5b1 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -2185,7 +2185,8 @@
TRACE_ALLOC(THR_Print("found hint %s for v%" Pd ": free until %" Pd "\n",
hint.Name(), unallocated->vreg(), free_until));
} else {
- for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
+ for (intptr_t i = 0; i < NumberOfRegisters(); ++i) {
+ intptr_t reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
if (!blocked_registers_[reg] && (registers_[reg]->length() == 0)) {
candidate = reg;
free_until = kMaxPosition;
@@ -2196,7 +2197,8 @@
ASSERT(0 <= kMaxPosition);
if (free_until != kMaxPosition) {
- for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
+ for (intptr_t i = 0; i < NumberOfRegisters(); ++i) {
+ intptr_t reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
if (blocked_registers_[reg] || (reg == candidate)) continue;
const intptr_t intersection =
FirstIntersectionWithAllocated(reg, unallocated);
@@ -2258,7 +2260,8 @@
unallocated->vreg(),
extra_loop_info_[loop_info->id()]->start,
extra_loop_info_[loop_info->id()]->end));
- for (intptr_t reg = 0; reg < NumberOfRegisters(); ++reg) {
+ for (intptr_t i = 0; i < NumberOfRegisters(); ++i) {
+ intptr_t reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
if (blocked_registers_[reg] || (reg == candidate) ||
used_on_backedge[reg]) {
continue;
@@ -2371,7 +2374,8 @@
intptr_t free_until = 0;
intptr_t blocked_at = kMaxPosition;
- for (int reg = 0; reg < NumberOfRegisters(); ++reg) {
+ for (int i = 0; i < NumberOfRegisters(); ++i) {
+ int reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
if (blocked_registers_[reg]) continue;
if (UpdateFreeUntil(reg, unallocated, &free_until, &blocked_at)) {
candidate = reg;
@@ -2581,7 +2585,8 @@
}
void FlowGraphAllocator::AdvanceActiveIntervals(const intptr_t start) {
- for (intptr_t reg = 0; reg < NumberOfRegisters(); reg++) {
+ for (intptr_t i = 0; i < NumberOfRegisters(); ++i) {
+ intptr_t reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
if (registers_[reg]->is_empty()) continue;
intptr_t first_evicted = -1;
@@ -2704,7 +2709,8 @@
ASSERT(unallocated_.is_empty());
unallocated_.AddArray(unallocated);
- for (intptr_t reg = 0; reg < number_of_registers; reg++) {
+ for (intptr_t i = 0; i < NumberOfRegisters(); ++i) {
+ intptr_t reg = (i + kRegisterAllocationBias) % NumberOfRegisters();
blocked_registers_[reg] = blocked_registers[reg];
ASSERT(registers_[reg]->is_empty());
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 48fa007..e3dc87a 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -574,6 +574,8 @@
kAllCpuRegistersList & ~kReservedCpuRegisters;
constexpr int kNumberOfDartAvailableCpuRegs =
kNumberOfCpuRegisters - kNumberOfReservedCpuRegisters;
+// No reason to prefer certain registers on ARM.
+constexpr int kRegisterAllocationBias = 0;
const intptr_t kStoreBufferWrapperSize = 24;
// Registers available to Dart that are not preserved by runtime calls.
const RegList kDartVolatileCpuRegs =
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index b37fd6b..03fc499 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -431,6 +431,8 @@
kAllCpuRegistersList & ~kReservedCpuRegisters;
constexpr int kNumberOfDartAvailableCpuRegs =
kNumberOfCpuRegisters - kNumberOfReservedCpuRegisters;
+// No reason to prefer certain registers on ARM64.
+constexpr int kRegisterAllocationBias = 0;
// Registers available to Dart that are not preserved by runtime calls.
const RegList kDartVolatileCpuRegs =
kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index 5d77faa..ab67693 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -31,7 +31,7 @@
kNoRegister = -1, // Signals an illegal register.
};
-// Low and high bytes registers of the the first four general purpose registers.
+// Low and high bytes registers of the first four general purpose registers.
// The other four general purpose registers do not have byte registers.
enum ByteRegister {
AL = 0,
@@ -278,6 +278,8 @@
// CPU registers available to Dart allocator.
const RegList kDartAvailableCpuRegs =
kAllCpuRegistersList & ~kReservedCpuRegisters;
+// No reason to prefer certain registers on IA32.
+constexpr int kRegisterAllocationBias = 0;
const RegList kAbiPreservedCpuRegs = (1 << EDI) | (1 << ESI) | (1 << EBX);
diff --git a/runtime/vm/constants_riscv.h b/runtime/vm/constants_riscv.h
index 375abfb..707caf7 100644
--- a/runtime/vm/constants_riscv.h
+++ b/runtime/vm/constants_riscv.h
@@ -411,6 +411,8 @@
constexpr RegList kDartAvailableCpuRegs =
kAllCpuRegistersList & ~kReservedCpuRegisters;
constexpr int kNumberOfDartAvailableCpuRegs = 18;
+// Registers X8-15 (S0-1,A0-5) have more compressed instructions available.
+constexpr int kRegisterAllocationBias = 8;
// Registers available to Dart that are not preserved by runtime calls.
constexpr RegList kDartVolatileCpuRegs =
kDartAvailableCpuRegs & ~kAbiPreservedCpuRegs;
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 0c9652b..9b8e5c2 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -355,6 +355,8 @@
kAllCpuRegistersList & ~kReservedCpuRegisters;
constexpr int kNumberOfDartAvailableCpuRegs =
kNumberOfCpuRegisters - kNumberOfReservedCpuRegisters;
+// Low numbered registers sometimes require fewer prefixes.
+constexpr int kRegisterAllocationBias = 0;
constexpr int kStoreBufferWrapperSize = 13;
#if defined(DART_TARGET_OS_WINDOWS)
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index c0c642f..09ec2e7 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -98,6 +98,30 @@
return Read<T>(kEndUnsignedByteMarker);
}
+ intptr_t ReadRefId() {
+ const int8_t* cursor = reinterpret_cast<const int8_t*>(current_);
+ intptr_t result = 0;
+ intptr_t byte;
+ // clang-format off
+#define STAGE \
+ byte = *cursor++; /* ldrsb byte, [result], 1 */ \
+ result = byte + (result << 7); /* add result, byte, result lsl 7 */ \
+ if (byte < 0) goto done; /* tbnz byte, 63, done */
+ STAGE // 0-7
+ STAGE // 8-14
+ STAGE // 15-21
+ STAGE // 22-28
+#undef STAGE
+ ASSERT(byte < 0); // 256MB is enough for anyone...
+ // clang-format on
+ done:
+ current_ = reinterpret_cast<const uint8_t*>(cursor);
+ // With big-endian order and the has-more marker being 0, the correction
+ // factor to remove the last-byte marker is a constant, which can be folded
+ // in to subsequent load offsets.
+ return result + 128;
+ }
+
intptr_t Position() const { return current_ - buffer_; }
void SetPosition(intptr_t value) {
ASSERT((end_ - buffer_) >= value);
@@ -374,6 +398,21 @@
WriteByte(static_cast<uint8_t>(value + kEndUnsignedByteMarker));
}
+ void WriteRefId(intptr_t value) {
+ ASSERT(Utils::IsUint(28, value)); // 256MB is enough for anyone...
+ EnsureSpace(4);
+ if ((value >> 21) != 0) {
+ *current_++ = (value >> 21) & 127;
+ }
+ if ((value >> 14) != 0) {
+ *current_++ = (value >> 14) & 127;
+ }
+ if ((value >> 7) != 0) {
+ *current_++ = (value >> 7) & 127;
+ }
+ *current_++ = ((value >> 0) & 127) | 128;
+ }
+
void WriteBytes(const void* addr, intptr_t len) {
if (len != 0) {
EnsureSpace(len);
diff --git a/runtime/vm/frame_layout.h b/runtime/vm/frame_layout.h
index d410e93..e09a757 100644
--- a/runtime/vm/frame_layout.h
+++ b/runtime/vm/frame_layout.h
@@ -42,6 +42,12 @@
// The offset (in words) from FP to the saved pool (if applicable).
int saved_caller_pp_from_fp;
+ // The offset (in words) from FP to the saved FP.
+ int saved_caller_fp_from_fp;
+
+ // The offset (in words) from FP to the saved return address.
+ int saved_caller_pc_from_fp;
+
// The offset (in words) from FP to the code object (if applicable).
int code_from_fp;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 1ae59b4..bc8a1fe 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3364,8 +3364,11 @@
for (; i < num_overlapping_type_args; i++) {
sup_type_arg = sup_type_args.TypeAt(sup_type_args_length -
num_overlapping_type_args + i);
- ASSERT(!sup_type_arg.IsNull());
- if (!sup_type_arg.IsTypeParameter()) break;
+ // 'sup_type_arg' can be null if type arguments are currently being
+ // finalized in ClassFinalizer::ExpandAndFinalizeTypeArguments.
+ // Type arguments which are not filled yet do not correspond to
+ // the type parameters and cannot be reused.
+ if (sup_type_arg.IsNull() || !sup_type_arg.IsTypeParameter()) break;
// The only type parameters appearing in the type arguments of the super
// type are those declared by this class. Their finalized indices depend
// on the number of type arguments being computed here. Therefore, they
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index ca98fb9..295226f 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -118,7 +118,7 @@
}
// There is an idiom where static utility classes are given a private
- // constructor to prevent the the class from being instantiated. Ignore these
+ // constructor to prevent the class from being instantiated. Ignore these
// constructors so that they don't lower the coverage rate. See #47021.
SafepointReadRwLocker ml(thread_, thread_->isolate_group()->program_lock());
if (func.kind() == UntaggedFunction::kConstructor &&
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 0297144..7a43ea7 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -34,6 +34,8 @@
/*.first_local_from_fp = */ -1,
/*.dart_fixed_frame_size = */ -1,
/*.saved_caller_pp_from_fp = */ -1,
+ /*.saved_caller_fp_from_fp = */ -1,
+ /*.saved_caller_pc_from_fp = */ -1,
/*.code_from_fp = */ -1,
/*.exit_link_slot_from_entry_fp = */ -1,
};
@@ -46,6 +48,8 @@
/*.first_local_from_fp = */ kFirstLocalSlotFromFp,
/*.dart_fixed_frame_size = */ kDartFrameFixedSize,
/*.saved_caller_pp_from_fp = */ kSavedCallerPpSlotFromFp,
+ /*.saved_caller_fp_from_fp = */ kSavedCallerFpSlotFromFp,
+ /*.saved_caller_pc_from_fp = */ kSavedCallerPcSlotFromFp,
/*.code_from_fp = */ kPcMarkerSlotFromFp,
/*.exit_link_slot_from_entry_fp = */ kExitLinkSlotFromEntryFp,
};
@@ -60,7 +64,9 @@
/*.dart_fixed_frame_size =*/kDartFrameFixedSize -
2, // No saved CODE, PP slots.
/*.saved_caller_pp_from_fp = */ 0, // No saved PP slot.
- /*.code_from_fp = */ 0, // No saved CODE
+ /*.saved_caller_fp_from_fp = */ kSavedCallerFpSlotFromFp,
+ /*.saved_caller_pc_from_fp = */ kSavedCallerPcSlotFromFp,
+ /*.code_from_fp = */ 0, // No saved CODE
/*.exit_link_slot_from_entry_fp = */ kExitLinkSlotFromEntryFp,
};
diff --git a/sdk/lib/_internal/vm/lib/collection_patch.dart b/sdk/lib/_internal/vm/lib/collection_patch.dart
index 942dc83..0647441 100644
--- a/sdk/lib/_internal/vm/lib/collection_patch.dart
+++ b/sdk/lib/_internal/vm/lib/collection_patch.dart
@@ -239,6 +239,28 @@
_buckets = newBuckets;
}
+ @override
+ V update(K key, V update(V value), {V Function()? ifAbsent}) {
+ final hashCode = key.hashCode;
+ final buckets = _buckets;
+ final length = buckets.length;
+ final index = hashCode & (length - 1);
+ var entry = buckets[index];
+ while (entry != null) {
+ if (hashCode == entry.hashCode && entry.key == key) {
+ return entry.value = update(entry.value);
+ }
+ entry = entry.next;
+ }
+ if (ifAbsent != null) {
+ V newValue = ifAbsent();
+ _addEntry(buckets, index, length, key, newValue, hashCode);
+ return newValue;
+ } else {
+ throw ArgumentError.value(key, "key", "Key not in map.");
+ }
+ }
+
Set<K> _newKeySet() => new _HashSet<K>();
}
@@ -429,6 +451,28 @@
return null;
}
+ @override
+ V update(K key, V update(V value), {V Function()? ifAbsent}) {
+ final hashCode = identityHashCode(key);
+ final buckets = _buckets;
+ final length = buckets.length;
+ final index = hashCode & (length - 1);
+ var entry = buckets[index];
+ while (entry != null) {
+ if (hashCode == entry.hashCode && identical(entry.key, key)) {
+ return entry.value = update(entry.value);
+ }
+ entry = entry.next;
+ }
+ if (ifAbsent != null) {
+ V newValue = ifAbsent();
+ _addEntry(buckets, index, length, key, newValue, hashCode);
+ return newValue;
+ } else {
+ throw ArgumentError.value(key, "key", "Key not in map.");
+ }
+ }
+
Set<K> _newKeySet() => new _IdentityHashSet<K>();
}
diff --git a/sdk/lib/_internal/vm/lib/finalizer_patch.dart b/sdk/lib/_internal/vm/lib/finalizer_patch.dart
index 417344f..18a030d 100644
--- a/sdk/lib/_internal/vm/lib/finalizer_patch.dart
+++ b/sdk/lib/_internal/vm/lib/finalizer_patch.dart
@@ -24,7 +24,7 @@
///
/// This is fine as a non-atomic operation, because the GC only looks at
/// finalizer instances when it process their entries. By preventing inlining
- /// we ensure the the finalizer to have been fully initialized by the time
+ /// we ensure the finalizer to have been fully initialized by the time
/// any [attach] on it is called.
///
/// Alternatively, we could make it a recognized method and add a reachability
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index 43e377a..e17cc71 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -563,7 +563,7 @@
/// an existing zone which was created earlier using [Zone.fork].
///
/// Developers can create a new zone that overrides some of the functionality of
-/// an existing zone. For example, custom zones can replace of modify the
+/// an existing zone. For example, custom zones can replace or modify the
/// behavior of `print`, timers, microtasks or how uncaught errors are handled.
///
/// The [Zone] class is not subclassable, but users can provide custom zones by
diff --git a/sdk/lib/core/weak.dart b/sdk/lib/core/weak.dart
index 3c8f968..660a5eb 100644
--- a/sdk/lib/core/weak.dart
+++ b/sdk/lib/core/weak.dart
@@ -173,7 +173,7 @@
/// Attaches this finalizer to [value].
///
- /// When [value] is longer accessible to the program,
+ /// When [value] is no longer accessible to the program,
/// while still having an attachement to this finalizer,
/// the callback of this finalizer *may* be called
/// with [finalizationToken] as argument.
diff --git a/tests/language/implicit_creation/implicit_const_context_not_test.dart b/tests/language/implicit_creation/implicit_const_context_not_test.dart
index 7d69c0a..83d75ea 100644
--- a/tests/language/implicit_creation/implicit_const_context_not_test.dart
+++ b/tests/language/implicit_creation/implicit_const_context_not_test.dart
@@ -25,7 +25,7 @@
const C.c2() : v = const C();
const C.c3() : v = const C(C());
- // Expression in redirecting generative const constuctor.
+ // Expression in redirecting generative const constructor.
const C.r1() : this(C()); //# 3: compile-time error
const C.r2() : this(const C());
const C.r3() : this(const C(C()));
diff --git a/tests/language/inference_update_1/write_capture_deferral_disabled_test.dart b/tests/language/inference_update_1/write_capture_deferral_disabled_test.dart
index 1083524..80c63a8 100644
--- a/tests/language/inference_update_1/write_capture_deferral_disabled_test.dart
+++ b/tests/language/inference_update_1/write_capture_deferral_disabled_test.dart
@@ -52,4 +52,19 @@
}
}
+class B {
+ B(Object? x, void Function() g, Object? y);
+ B.redirectingConstructorInvocation(int? i)
+ : this(i!, () {
+ i = null;
+ }, i..expectStaticType<Exactly<int?>>());
+}
+
+class C extends B {
+ C.superConstructorInvocation(int? i)
+ : super(i!, () {
+ i = null;
+ }, i..expectStaticType<Exactly<int?>>());
+}
+
main() {}
diff --git a/tests/language/inference_update_1/write_capture_deferral_enabled_test.dart b/tests/language/inference_update_1/write_capture_deferral_enabled_test.dart
index 3a93caa..1a9a79f6 100644
--- a/tests/language/inference_update_1/write_capture_deferral_enabled_test.dart
+++ b/tests/language/inference_update_1/write_capture_deferral_enabled_test.dart
@@ -52,4 +52,19 @@
}
}
+class B {
+ B(Object? x, void Function() g, Object? y);
+ B.redirectingConstructorInvocation(int? i)
+ : this(i!, () {
+ i = null;
+ }, i..expectStaticType<Exactly<int>>());
+}
+
+class C extends B {
+ C.superConstructorInvocation(int? i)
+ : super(i!, () {
+ i = null;
+ }, i..expectStaticType<Exactly<int>>());
+}
+
main() {}
diff --git a/tests/language_2/implicit_creation/implicit_const_context_not_test.dart b/tests/language_2/implicit_creation/implicit_const_context_not_test.dart
index 8f8d999..26f7240 100644
--- a/tests/language_2/implicit_creation/implicit_const_context_not_test.dart
+++ b/tests/language_2/implicit_creation/implicit_const_context_not_test.dart
@@ -27,7 +27,7 @@
const C.c2() : v = const C();
const C.c3() : v = const C(C());
- // Expression in redirecting generative const constuctor.
+ // Expression in redirecting generative const constructor.
const C.r1() : this(C()); //# 3: compile-time error
const C.r2() : this(const C());
const C.r3() : this(const C(C()));
diff --git a/tools/VERSION b/tools/VERSION
index 8165b14..d6b04d4 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 66
+PRERELEASE 67
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 417b548..df62eb3 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -49,6 +49,23 @@
platform('pkg/_fe_analyzer_shared/test/inheritance'),
];
+ // Validate that all the given directories exist.
+ var hasMissingDirectories = false;
+ for (var path in [
+ ...packageDirs,
+ ...cfePackageDirs,
+ ...feAnalyzerSharedPackageDirs
+ ]) {
+ if (!Directory(join(repoRoot, path)).existsSync()) {
+ stderr.writeln("Unable to locate directory: '$path'.");
+ hasMissingDirectories = true;
+ }
+ }
+
+ if (hasMissingDirectories) {
+ exit(1);
+ }
+
var packages = <Package>[
...makePackageConfigs(packageDirs),
...makeCfePackageConfigs(cfePackageDirs),