Version 2.1.0-dev.3.0
Merge commit '8b5a2b0' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 02e5dcc..758e334 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,12 @@
+## 2.1.0-dev.3.0
+
+### Core library changes
+
+* `dart:async`
+ * Update `Stream.fromIterable` to send a done event after the error when the
+ iterator's `moveNext` throws, and handle if the `current` getter throws.
+ Issue [33431](http://dartbug.com/33431).
+
## 2.1.0-dev.2.0
### Tool Changes
diff --git a/DEPS b/DEPS
index 32c23b4..8f5c4c4 100644
--- a/DEPS
+++ b/DEPS
@@ -95,7 +95,7 @@
"intl_tag": "0.15.6",
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_tag": "2.0.9",
- "linter_tag": "0.1.59",
+ "linter_tag": "0.1.60",
"logging_tag": "0.11.3+2",
"markdown_tag": "2.0.2",
"matcher_tag": "0.12.3",
@@ -157,7 +157,7 @@
"packages": [
{
"package": "dart/dart-sdk/${{platform}}",
- "version": "version:2.0.0-dev.69.5",
+ "version": "version:2.1.0-dev.2.0",
},
],
"dep_type": "cipd",
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex
index 8e19bd2..051d913 100644
--- a/docs/language/dartLangSpec.tex
+++ b/docs/language/dartLangSpec.tex
@@ -25,6 +25,8 @@
% constructor invocation.
% - Specify that type arguments passed in a redirecting factory constructor
% declaration must be taken into account during static checks.
+% - Disallow any expression statement starting with `{`, not just
+% those that are map literals.
%
% 2.0
% - Don't allow functions as assert test values.
@@ -7826,11 +7828,8 @@
\LMLabel{expressionStatements}
\LMHash{}
-An {\em expression statement} consists of an expression other than a non-constant map literal (\ref{maps}) that has no explicit type arguments.
-
-\rationale{
-The restriction on maps is designed to resolve an ambiguity in the grammar, when a statement begins with \{.
-}
+An {\em expression statement} consists of an expression that does not
+begin with a \{ character.
\begin{grammar}
{\bf expressionStatement:}expression? `{\escapegrammar ;}'
@@ -7838,11 +7837,24 @@
\end{grammar}
\LMHash{}
-Execution of an expression statement \code{$e$;} proceeds by evaluating $e$.
+The expression of an expression statement is not allowed to begin with a \{.
+\commentary{
+This means that if some source text could otherwise be parsed as an expression
+followed by a \;, then this grammar production does not apply
+when the expression starts with a \{.
+}
+\rationale{
+The restriction resolves an ambiguity while parsing where a
+\{ can start either a block (\ref{blocks}) or a map literal (\ref{maps}).
+By disallowing the latter from starting an expression statement,
+the parser does not need to look further ahead
+before deciding that it is parsing a block statement.
+}
\LMHash{}
-It is a compile-time error if a non-constant map literal that has no explicit type arguments appears in a place where a statement is expected.
-
+Execution of an expression statement \code{$e$;} proceeds by evaluating $e$.
+If the expression evaluates to a value, then the value is ignored
+and the execution completes normally.
\subsection{Local Variable Declaration}
\LMLabel{localVariableDeclaration}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index 7a560c3..654c128 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -62,7 +62,16 @@
}
}
if (parent is Annotation) {
- return parent.constructorName ?? parent.name;
+ SimpleIdentifier name = parent.constructorName;
+ if (name == null) {
+ Identifier parentName = parent.name;
+ if (parentName is SimpleIdentifier) {
+ return parentName;
+ } else if (parentName is PrefixedIdentifier) {
+ return parentName.identifier;
+ }
+ }
+ return name;
}
}
return null;
diff --git a/pkg/analysis_server/test/integration/edit/get_postfix_completion_test.dart b/pkg/analysis_server/test/integration/edit/get_postfix_completion_test.dart
index 8e34a3b..d7c5fd3 100644
--- a/pkg/analysis_server/test/integration/edit/get_postfix_completion_test.dart
+++ b/pkg/analysis_server/test/integration/edit/get_postfix_completion_test.dart
@@ -18,6 +18,7 @@
@reflectiveTest
class GetPostfixCompletionTest extends AbstractAnalysisServerIntegrationTest {
+ @TestTimeout(const Timeout.factor(2))
test_postfix_completion() async {
String pathname = sourcePath('test.dart');
String text = r'''
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 8271e2b..abb74ac 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
@@ -152,6 +152,21 @@
namedArgumentsWithTypes: {'one': 'int', 'two': 'String'});
}
+ test_Annotation_importedConstructor_prefixed() async {
+ addSource('/libA.dart', '''
+class A {
+ const A({int value});
+}
+''');
+ addTestSource('''
+import "${convertPathForImport("/libA.dart")}" as p;
+@p.A(^)
+main() {}
+''');
+ await computeSuggestions();
+ assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {'value': 'int'});
+ }
+
test_Annotation_local_constructor_named_param() async {
addTestSource('''
class A { const A({int one, String two: 'defaultValue'}); }
@@ -1046,14 +1061,4 @@
class ArgListContributorTest_UseCFE extends ArgListContributorTest {
@override
bool get useCFE => true;
-
- @failingTest
- @override
- test_ArgumentList_local_constructor_named_param_4() =>
- super.test_ArgumentList_local_constructor_named_param_4();
-
- @failingTest
- @override
- test_ArgumentList_local_constructor_named_param_5() =>
- super.test_ArgumentList_local_constructor_named_param_5();
}
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 18e4340..84c538a 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -448,6 +448,7 @@
/**
* An empty list of AST nodes.
*/
+ @deprecated
static const List<AstNode> EMPTY_LIST = const <AstNode>[];
/**
@@ -2597,6 +2598,7 @@
/**
* An empty list of expressions.
*/
+ @deprecated
static const List<Expression> EMPTY_LIST = const <Expression>[];
/**
@@ -5206,7 +5208,7 @@
/**
* Return the on clause for the mixin, or `null` if the mixin does not have
- * any super-class constraints.
+ * any superclass constraints.
*/
OnClause get onClause;
@@ -5608,7 +5610,7 @@
Token get onKeyword;
/**
- * Return the list of the classes are super-class constraints for the mixin.
+ * Return the list of the classes are superclass constraints for the mixin.
*/
NodeList<TypeName> get superclassConstraints;
}
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 34ee3c9..7e2ca4c 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -48,7 +48,9 @@
import 'package:analyzer/src/task/dart.dart';
/**
- * An element that represents a class.
+ * An element that represents a class or a mixin. The class can be defined by
+ * either a class declaration (with a class body), a mixin application (without
+ * a class body), a mixin declaration, or an enum declaration.
*
* Clients may not extend, implement or mix-in this class.
*/
@@ -57,6 +59,7 @@
/**
* An empty list of class elements.
*/
+ @deprecated
static const List<ClassElement> EMPTY_LIST = const <ClassElement>[];
/**
@@ -67,12 +70,15 @@
/**
* Return a list containing all the supertypes defined for this class and its
- * supertypes. This includes superclasses, mixins and interfaces.
+ * supertypes. This includes superclasses, mixins, interfaces and superclass
+ * constraints.
*/
List<InterfaceType> get allSupertypes;
/**
* Return a list containing all of the constructors declared in this class.
+ * The list will be empty if there are no constructors defined for this class,
+ * as is the case when this element represents an enum or a mixin.
*/
List<ConstructorElement> get constructors;
@@ -88,8 +94,10 @@
bool get hasNonFinalField;
/**
- * Return `true` if this class has reference to super (so, for example, cannot
- * be used as a mixin).
+ * Return `true` if this class has at least one reference to `super` (and
+ * hence cannot be used as a mixin), or `false` if this element represents a
+ * mixin, even if the mixin has a reference to `super`, because it is allowed
+ * to be used as a mixin.
*/
bool get hasReferenceToSuper;
@@ -112,8 +120,9 @@
/**
* Return `true` if this class is abstract. A class is abstract if it has an
- * explicit `abstract` modifier. Note, that this definition of <i>abstract</i>
- * is different from <i>has unimplemented members</i>.
+ * explicit `abstract` modifier or if it is implicitly abstract, such as a
+ * class defined by a mixin declaration. Note, that this definition of
+ * <i>abstract</i> is different from <i>has unimplemented members</i>.
*/
bool get isAbstract;
@@ -123,6 +132,11 @@
bool get isEnum;
/**
+ * Return `true` if this class is defined by a mixin declaration.
+ */
+ bool get isMixin;
+
+ /**
* Return `true` if this class is a mixin application. A class is a mixin
* application if it was declared using the syntax "class A = B with C;".
*/
@@ -141,7 +155,9 @@
/**
* Return `true` if this class can validly be used as a mixin when defining
- * another class. The behavior of this method is defined by the Dart Language
+ * another class. For classes defined by a mixin declaration, the result is
+ * always `true`. For classes defined by a class declaration or a mixin
+ * application, the behavior of this method is defined by the Dart Language
* Specification in section 9:
* <blockquote>
* It is a compile-time error if a declared or derived mixin refers to super.
@@ -170,8 +186,24 @@
List<InterfaceType> get mixins;
/**
- * Return the superclass of this class, or `null` if the class represents the
- * class 'Object'. All other classes will have a non-`null` superclass. If the
+ * Return a list containing all of the superclass constraints defined for this
+ * class. The list will be empty if this class does not represent a mixin
+ * declaration. If this class _does_ represent a mixin declaration but the
+ * declaration does not have an on clause, then the list will contain the type
+ * for the class `Object`.
+ *
+ * <b>Note:</b> Because the element model represents the state of the code, it
+ * is possible for it to be semantically invalid. In particular, it is not
+ * safe to assume that the inheritance structure of a class does not contain a
+ * cycle. Clients that traverse the inheritance structure must explicitly
+ * guard against infinite loops.
+ */
+ List<InterfaceType> get superclassConstraints;
+
+ /**
+ * Return the superclass of this class, or `null` if either the class
+ * represents the class 'Object' or if the class represents a mixin
+ * declaration. All other classes will have a non-`null` superclass. If the
* superclass was not explicitly declared then the implicit superclass
* 'Object' will be returned.
*
@@ -187,11 +219,12 @@
InterfaceType get type;
/**
- * Return the unnamed constructor declared in this class, or `null` if this
- * class does not declare an unnamed constructor but does declare named
- * constructors. The returned constructor will be synthetic if this class does
- * not declare any constructors, in which case it will represent the default
- * constructor for the class.
+ * Return the unnamed constructor declared in this class, or `null` if either
+ * this class does not declare an unnamed constructor but does declare named
+ * constructors or if this class represents a mixin declaration. The returned
+ * constructor will be synthetic if this class does not declare any
+ * constructors, in which case it will represent the default constructor for
+ * the class.
*/
ConstructorElement get unnamedConstructor;
@@ -415,6 +448,7 @@
/**
* An empty list of compilation unit elements.
*/
+ @deprecated
static const List<CompilationUnitElement> EMPTY_LIST =
const <CompilationUnitElement>[];
@@ -497,6 +531,7 @@
/**
* An empty list of constructor elements.
*/
+ @deprecated
static const List<ConstructorElement> EMPTY_LIST =
const <ConstructorElement>[];
@@ -650,6 +685,11 @@
bool get hasRequired;
/**
+ * Return `true` if this element has an annotation of the form '@sealed'.
+ */
+ bool get hasSealed;
+
+ /**
* Return `true` if this element has an annotation of the form
* `@visibleForTemplate`.
*/
@@ -867,6 +907,7 @@
/**
* An empty list of annotations.
*/
+ @deprecated
static const List<ElementAnnotation> EMPTY_LIST = const <ElementAnnotation>[];
/**
@@ -955,6 +996,12 @@
bool get isRequired;
/**
+ * Return `true` if this annotation marks the associated class as being
+ * sealed.
+ */
+ bool get isSealed;
+
+ /**
* Return `true` if this annotation marks the associated member as being
* visible for template files.
*/
@@ -1199,6 +1246,7 @@
/**
* An empty list of executable elements.
*/
+ @deprecated
static const List<ExecutableElement> EMPTY_LIST = const <ExecutableElement>[];
/**
@@ -1264,6 +1312,7 @@
/**
* An empty list of export elements.
*/
+ @deprecated
static const List<ExportElement> EMPTY_LIST = const <ExportElement>[];
/**
@@ -1289,6 +1338,7 @@
/**
* An empty list of field elements.
*/
+ @deprecated
static const List<FieldElement> EMPTY_LIST = const <FieldElement>[];
/**
@@ -1329,6 +1379,7 @@
/**
* An empty list of function elements.
*/
+ @deprecated
static const List<FunctionElement> EMPTY_LIST = const <FunctionElement>[];
/**
@@ -1373,6 +1424,7 @@
/**
* An empty array of type alias elements.
*/
+ @deprecated
static List<FunctionTypeAliasElement> EMPTY_LIST =
new List<FunctionTypeAliasElement>(0);
@@ -1463,6 +1515,7 @@
/**
* An empty list of import elements.
*/
+ @deprecated
static const List<ImportElement> EMPTY_LIST = const <ImportElement>[];
/**
@@ -1510,6 +1563,7 @@
/**
* An empty list of label elements.
*/
+ @deprecated
static const List<LabelElement> EMPTY_LIST = const <LabelElement>[];
@override
@@ -1525,6 +1579,7 @@
/**
* An empty list of library elements.
*/
+ @deprecated
static const List<LibraryElement> EMPTY_LIST = const <LibraryElement>[];
/**
@@ -1694,6 +1749,7 @@
/**
* An empty list of field elements.
*/
+ @deprecated
static const List<LocalVariableElement> EMPTY_LIST =
const <LocalVariableElement>[];
}
@@ -1707,6 +1763,7 @@
/**
* An empty list of method elements.
*/
+ @deprecated
static const List<MethodElement> EMPTY_LIST = const <MethodElement>[];
@override
@@ -1768,6 +1825,7 @@
/**
* An empty list of namespace combinators.
*/
+ @deprecated
static const List<NamespaceCombinator> EMPTY_LIST =
const <NamespaceCombinator>[];
}
@@ -1782,6 +1840,7 @@
/**
* An empty list of parameter elements.
*/
+ @deprecated
static const List<ParameterElement> EMPTY_LIST = const <ParameterElement>[];
/**
@@ -1874,6 +1933,7 @@
/**
* An empty list of prefix elements.
*/
+ @deprecated
static const List<PrefixElement> EMPTY_LIST = const <PrefixElement>[];
@override
@@ -1909,6 +1969,7 @@
/**
* An empty list of property accessor elements.
*/
+ @deprecated
static const List<PropertyAccessorElement> EMPTY_LIST =
const <PropertyAccessorElement>[];
@@ -1967,6 +2028,7 @@
/**
* An empty list of elements.
*/
+ @deprecated
static const List<PropertyInducingElement> EMPTY_LIST =
const <PropertyInducingElement>[];
@@ -2030,6 +2092,7 @@
/**
* An empty list of top-level variable elements.
*/
+ @deprecated
static const List<TopLevelVariableElement> EMPTY_LIST =
const <TopLevelVariableElement>[];
@@ -2058,6 +2121,7 @@
/**
* An empty list of type parameter elements.
*/
+ @deprecated
static const List<TypeParameterElement> EMPTY_LIST =
const <TypeParameterElement>[];
@@ -2136,6 +2200,7 @@
/**
* An empty list of variable elements.
*/
+ @deprecated
static const List<VariableElement> EMPTY_LIST = const <VariableElement>[];
/**
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index 7467480..5aa5c3f 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -34,6 +34,7 @@
/**
* An empty list of types.
*/
+ @deprecated
static const List<DartType> EMPTY_LIST = const <DartType>[];
/**
@@ -351,6 +352,7 @@
/**
* An empty list of types.
*/
+ @deprecated
static const List<InterfaceType> EMPTY_LIST = const <InterfaceType>[];
/**
@@ -717,6 +719,7 @@
/**
* An empty list of type parameter types.
*/
+ @deprecated
static const List<TypeParameterType> EMPTY_LIST = const <TypeParameterType>[];
/**
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 4cfcde6..5662d2f 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -305,6 +305,7 @@
HintCode.INVALID_METHOD_OVERRIDE_TYPE_PARAMETERS,
HintCode.INVALID_METHOD_OVERRIDE_TYPE_PARAMETER_BOUND,
HintCode.INVALID_REQUIRED_PARAM,
+ HintCode.INVALID_SEALED_ANNOTATION,
HintCode.INVALID_USE_OF_PROTECTED_MEMBER,
HintCode.INVALID_USE_OF_VISIBLE_FOR_TEMPLATE_MEMBER,
HintCode.INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER,
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index 40a2d9e..a1834e2 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -949,7 +949,7 @@
List<TargetedResult> flushToSize() {
// If still under the cap, done.
if (currentSize <= maxSize) {
- return TargetedResult.EMPTY_LIST;
+ return const <TargetedResult>[];
}
// Flush results until we are under the cap.
List<TargetedResult> resultsToFlush = <TargetedResult>[];
@@ -1122,7 +1122,7 @@
*/
List<Source> getSourcesWithFullName(String path) {
List<Source> sources = pathToSource[path];
- return sources ?? Source.EMPTY_LIST;
+ return sources ?? const <Source>[];
}
/**
@@ -1537,7 +1537,7 @@
@override
List<TargetedResult> resultStored(TargetedResult newResult, newValue) {
- return TargetedResult.EMPTY_LIST;
+ return const <TargetedResult>[];
}
@override
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 9472a8d..c1e0f20 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -334,13 +334,13 @@
@override
void set analysisPriorityOrder(List<Source> sources) {
if (sources == null || sources.isEmpty) {
- _priorityOrder = Source.EMPTY_LIST;
+ _priorityOrder = const <Source>[];
} else {
while (sources.remove(null)) {
// Nothing else to do.
}
if (sources.isEmpty) {
- _priorityOrder = Source.EMPTY_LIST;
+ _priorityOrder = const <Source>[];
} else {
_priorityOrder = sources;
}
@@ -897,7 +897,7 @@
@override
List<Source> getHtmlFilesReferencing(Source source) {
if (!AnalysisEngine.isDartFileName(source.shortName)) {
- return Source.EMPTY_LIST;
+ return const <Source>[];
}
List<Source> htmlSources = <Source>[];
List<Source> librarySources = getLibrariesContaining(source);
@@ -911,7 +911,7 @@
}
}
if (htmlSources.isEmpty) {
- return Source.EMPTY_LIST;
+ return const <Source>[];
}
return htmlSources;
}
@@ -951,7 +951,7 @@
}
}
if (dependentLibraries.isEmpty) {
- return Source.EMPTY_LIST;
+ return const <Source>[];
}
return dependentLibraries;
}
@@ -962,7 +962,7 @@
if (entry != null) {
return entry.getValue(REFERENCED_LIBRARIES);
}
- return Source.EMPTY_LIST;
+ return const <Source>[];
}
@override
@@ -1059,7 +1059,7 @@
// Don't compare with old contents because the cache has already been
// updated, and we know at this point that it changed.
_sourceChanged(source, compareWithOld: false);
- entry.setValue(CONTENT, newContents, TargetedResult.EMPTY_LIST);
+ entry.setValue(CONTENT, newContents, const <TargetedResult>[]);
} else {
entry.modificationTime = _contentCache.getModificationStamp(source);
}
@@ -1071,7 +1071,7 @@
newContents = fileContents.data;
entry.modificationTime = fileContents.modificationTime;
if (newContents == originalContents) {
- entry.setValue(CONTENT, newContents, TargetedResult.EMPTY_LIST);
+ entry.setValue(CONTENT, newContents, const <TargetedResult>[]);
changed = false;
}
} catch (e) {}
@@ -1196,7 +1196,7 @@
//
CacheEntry entry = getCacheEntry(librarySource);
setValue(ResultDescriptor result, value) {
- entry.setValue(result, value, TargetedResult.EMPTY_LIST);
+ entry.setValue(result, value, const <TargetedResult>[]);
}
setValue(BUILD_DIRECTIVES_ERRORS, AnalysisError.NO_ERRORS);
@@ -1206,11 +1206,11 @@
// CONSTRUCTORS
// CONSTRUCTORS_ERRORS
entry.setState(CONTENT, CacheState.FLUSHED);
- setValue(EXPORTED_LIBRARIES, Source.EMPTY_LIST);
+ setValue(EXPORTED_LIBRARIES, const <Source>[]);
// EXPORT_SOURCE_CLOSURE
- setValue(IMPORTED_LIBRARIES, Source.EMPTY_LIST);
+ setValue(IMPORTED_LIBRARIES, const <Source>[]);
// IMPORT_SOURCE_CLOSURE
- setValue(INCLUDED_PARTS, Source.EMPTY_LIST);
+ setValue(INCLUDED_PARTS, const <Source>[]);
setValue(IS_LAUNCHABLE, false);
setValue(LIBRARY_ELEMENT, library);
setValue(LIBRARY_ELEMENT1, library);
@@ -1262,7 +1262,7 @@
});
CacheEntry entry = getCacheEntry(AnalysisContextTarget.request);
- entry.setValue(TYPE_PROVIDER, typeProvider, TargetedResult.EMPTY_LIST);
+ entry.setValue(TYPE_PROVIDER, typeProvider, const <TargetedResult>[]);
}
@override
@@ -1420,7 +1420,7 @@
CacheEntry entry = _cache.get(source);
if (entry != null) {
entry.modificationTime = _contentCache.getModificationStamp(source);
- entry.setValue(CONTENT, contents, TargetedResult.EMPTY_LIST);
+ entry.setValue(CONTENT, contents, const <TargetedResult>[]);
}
}
} else if (originalContents != null) {
@@ -1501,7 +1501,7 @@
if (nullIfEmpty) {
return null;
}
- return ChangeNoticeImpl.EMPTY_LIST;
+ return const <ChangeNoticeImpl>[];
}
List<ChangeNotice> notices = new List.from(_pendingNotices.values);
_pendingNotices.clear();
@@ -1529,7 +1529,7 @@
}
}
if (sources.isEmpty) {
- return Source.EMPTY_LIST;
+ return const <Source>[];
}
return sources;
}
@@ -1801,8 +1801,8 @@
entry.setState(SOURCE_KIND, CacheState.INVALID);
}
for (WorkManager workManager in workManagers) {
- workManager.applyChange(
- Source.EMPTY_LIST, <Source>[source], Source.EMPTY_LIST);
+ workManager
+ .applyChange(const <Source>[], <Source>[source], const <Source>[]);
}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart b/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart
index 578c149..2d056ef 100644
--- a/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/frontend_resolution.dart
@@ -443,12 +443,16 @@
@override
void store(int offset, bool isSynthetic,
- {int importIndex, Node reference, DartType type}) {
+ {int importIndex,
+ bool isNamespaceCombinatorReference = false,
+ Node reference,
+ DartType type}) {
// if (fileUri.toString().endsWith('test.dart')) {
// print('[store][offset: $offset][reference: $reference][type: $type]');
// }
var encodedLocation = 2 * offset + (isSynthetic ? 1 : 0);
resolution.kernelData[encodedLocation] = new ResolutionData(
+ isNamespaceCombinatorReference: isNamespaceCombinatorReference,
isOutline: true,
prefixInfo: importIndex,
reference: reference,
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 487f11f..d5a934b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -741,6 +741,9 @@
if (directive.metadata.isNotEmpty) {
applier.applyToAnnotations(directive);
}
+ if (directive is NamespaceDirective) {
+ directive.combinators.accept(applier);
+ }
}
for (var declaration in unit.declarations) {
if (declaration is ClassDeclaration) {
@@ -1133,8 +1136,9 @@
@override
Element translateReference(kernel.Node referencedNode,
- {bool isWriteReference = false,
+ {bool isNamespaceCombinatorReference = false,
bool isTypeReference = false,
+ bool isWriteReference = false,
kernel.DartType inferredType,
kernel.DartType receiverType}) {
if (referencedNode == null) {
@@ -1169,6 +1173,9 @@
throw new UnimplementedError(
'TODO(paulberry): ${referencedNode.runtimeType}');
}
+ if (isNamespaceCombinatorReference) {
+ return element;
+ }
if (element is PropertyInducingElement) {
PropertyInducingElement property = element;
element = isWriteReference ? property.setter : property.getter;
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index cd0aa53..d014ecd 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -1084,6 +1084,15 @@
}
/**
+ * Check whether the values of the [first] and [second] nodes are [equal].
+ * Subclasses can override to throw.
+ */
+ bool failIfNotEqual(
+ AstNode first, Object firstValue, AstNode second, Object secondValue) {
+ return firstValue == secondValue;
+ }
+
+ /**
* Check whether [second] is null. Subclasses can override to throw.
*/
bool failIfNotNull(Object first, Object second) {
@@ -1186,7 +1195,7 @@
@override
bool visitAssertInitializer(AssertInitializer node) {
- AssertStatement other = _other as AssertStatement;
+ AssertInitializer other = _other as AssertInitializer;
return isEqualTokens(node.assertKeyword, other.assertKeyword) &&
isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
isEqualNodes(node.condition, other.condition) &&
@@ -1248,7 +1257,7 @@
bool visitBooleanLiteral(BooleanLiteral node) {
BooleanLiteral other = _other as BooleanLiteral;
return isEqualTokens(node.literal, other.literal) &&
- node.value == other.value;
+ failIfNotEqual(node, node.value, other, other.value);
}
@override
@@ -1448,7 +1457,7 @@
bool visitDoubleLiteral(DoubleLiteral node) {
DoubleLiteral other = _other as DoubleLiteral;
return isEqualTokens(node.literal, other.literal) &&
- node.value == other.value;
+ failIfNotEqual(node, node.value, other, other.value);
}
@override
@@ -1723,7 +1732,7 @@
bool visitIntegerLiteral(IntegerLiteral node) {
IntegerLiteral other = _other as IntegerLiteral;
return isEqualTokens(node.literal, other.literal) &&
- (node.value == other.value);
+ failIfNotEqual(node, node.value, other, other.value);
}
@override
@@ -1738,7 +1747,7 @@
bool visitInterpolationString(InterpolationString node) {
InterpolationString other = _other as InterpolationString;
return isEqualTokens(node.contents, other.contents) &&
- node.value == other.value;
+ failIfNotEqual(node, node.value, other, other.value);
}
@override
@@ -2006,7 +2015,7 @@
bool visitSimpleStringLiteral(SimpleStringLiteral node) {
SimpleStringLiteral other = _other as SimpleStringLiteral;
return isEqualTokens(node.literal, other.literal) &&
- (node.value == other.value);
+ failIfNotEqual(node, node.value, other, other.value);
}
@override
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index b9ac011e..15dc365 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -167,6 +167,7 @@
/**
* An empty list of objects.
*/
+ @deprecated
static const List<DartObjectImpl> EMPTY_LIST = const <DartObjectImpl>[];
@override
@@ -374,21 +375,19 @@
*/
DartObjectImpl equalEqual(
TypeProvider typeProvider, DartObjectImpl rightOperand) {
- if (type != rightOperand.type) {
- String typeName = type.name;
- if (!(typeName == "bool" ||
- typeName == "double" ||
- typeName == "int" ||
- typeName == "num" ||
- typeName == "String" ||
- typeName == "Null" ||
- type.isDynamic)) {
- throw new EvaluationException(
- CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
- }
+ if (isNull || rightOperand.isNull) {
+ return new DartObjectImpl(
+ typeProvider.boolType,
+ isNull && rightOperand.isNull
+ ? BoolState.TRUE_STATE
+ : BoolState.FALSE_STATE);
}
- return new DartObjectImpl(
- typeProvider.boolType, _state.equalEqual(rightOperand._state));
+ if (isBoolNumStringOrNull) {
+ return new DartObjectImpl(
+ typeProvider.boolType, _state.equalEqual(rightOperand._state));
+ }
+ throw new EvaluationException(
+ CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
}
@override
@@ -573,18 +572,7 @@
*/
DartObjectImpl notEqual(
TypeProvider typeProvider, DartObjectImpl rightOperand) {
- if (type != rightOperand.type) {
- String typeName = type.name;
- if (typeName != "bool" &&
- typeName != "double" &&
- typeName != "int" &&
- typeName != "num" &&
- typeName != "String") {
- return new DartObjectImpl(typeProvider.boolType, BoolState.TRUE_STATE);
- }
- }
- return new DartObjectImpl(typeProvider.boolType,
- _state.equalEqual(rightOperand._state).logicalNot());
+ return equalEqual(typeProvider, rightOperand).logicalNot(typeProvider);
}
/**
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 8bd4925..236e332 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -1011,7 +1011,7 @@
List<ElementAnnotation> _getElementAnnotations(
NodeList<Annotation> metadata) {
if (metadata.isEmpty) {
- return ElementAnnotation.EMPTY_LIST;
+ return const <ElementAnnotation>[];
}
return metadata.map((Annotation a) => a.elementAnnotation).toList();
}
@@ -1551,7 +1551,7 @@
List<ElementAnnotation> _createElementAnnotations(
NodeList<Annotation> annotations) {
if (annotations.isEmpty) {
- return ElementAnnotation.EMPTY_LIST;
+ return const <ElementAnnotation>[];
}
return annotations.map((Annotation a) {
ElementAnnotationImpl elementAnnotation =
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index e99cc46..73e23a7 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -121,12 +121,18 @@
}
@override
- bool get isEnum;
+ bool get isEnum => false;
+
+ @override
+ bool get isMixin => false;
@override
ElementKind get kind => ElementKind.CLASS;
@override
+ List<InterfaceType> get superclassConstraints => const <InterfaceType>[];
+
+ @override
T accept<T>(ElementVisitor<T> visitor) => visitor.visitClassElement(this);
@override
@@ -837,9 +843,6 @@
}
@override
- bool get isEnum => false;
-
- @override
bool get isMixinApplication {
if (_kernel != null) {
return _kernel.mixedInType != null;
@@ -1648,7 +1651,7 @@
..addAll(_explicitTopLevelVariables.implicitAccessors);
}
}
- return _accessors ?? PropertyAccessorElement.EMPTY_LIST;
+ return _accessors ?? const <PropertyAccessorElement>[];
}
/**
@@ -1826,7 +1829,7 @@
_variables = variables;
}
}
- return _variables ?? TopLevelVariableElement.EMPTY_LIST;
+ return _variables ?? const <TopLevelVariableElement>[];
}
/**
@@ -2949,6 +2952,11 @@
*/
static String _REQUIRED_VARIABLE_NAME = "required";
+ /**
+ * The name of the top-level variable used to mark a class as being sealed.
+ */
+ static String _SEALED_VARIABLE_NAME = "sealed";
+
/// The name of the top-level variable used to mark a method as being
/// visible for templates.
static String _VISIBLE_FOR_TEMPLATE_VARIABLE_NAME = "visibleForTemplate";
@@ -3084,6 +3092,12 @@
element.library?.name == _META_LIB_NAME;
@override
+ bool get isSealed =>
+ element is PropertyAccessorElement &&
+ element.name == _SEALED_VARIABLE_NAME &&
+ element.library?.name == _META_LIB_NAME;
+
+ @override
bool get isVisibleForTemplate =>
element is PropertyAccessorElement &&
element.name == _VISIBLE_FOR_TEMPLATE_VARIABLE_NAME &&
@@ -3306,6 +3320,10 @@
metadata.any((ElementAnnotation annotation) => annotation.isRequired);
@override
+ bool get hasSealed =>
+ metadata.any((ElementAnnotation annotation) => annotation.isSealed);
+
+ @override
bool get hasVisibleForTemplate => metadata
.any((ElementAnnotation annotation) => annotation.isVisibleForTemplate);
@@ -6410,7 +6428,7 @@
* A list containing all of the compilation units that are included in this
* library using a `part` directive.
*/
- List<CompilationUnitElement> _parts = CompilationUnitElement.EMPTY_LIST;
+ List<CompilationUnitElement> _parts = const <CompilationUnitElement>[];
/**
* The element representing the synthetic function `loadLibrary` that is
@@ -6723,7 +6741,7 @@
resynthesizerContext.linkedLibrary.importDependencies);
}
}
- return _imports ?? ImportElement.EMPTY_LIST;
+ return _imports ?? const <ImportElement>[];
}
/**
@@ -7461,6 +7479,73 @@
}
/**
+ * A [ClassElementImpl] representing a mixin declaration.
+ */
+class MixinElementImpl extends ClassElementImpl {
+ // TODO(brianwilkerson) Consider creating an abstract superclass of
+ // ClassElementImpl that contains the portions of the API that this class
+ // needs, and make this class extend the new class.
+
+ /**
+ * A list containing all of the superclass constraints that are defined for
+ * the mixin.
+ */
+ List<InterfaceType> _superclassConstraints;
+
+ /**
+ * 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.
+ */
+ MixinElementImpl(String name, int offset) : super(name, offset);
+
+ /**
+ * Initialize using the given kernel.
+ */
+ MixinElementImpl.forKernel(
+ CompilationUnitElementImpl enclosingUnit, kernel.Class kernel)
+ : super.forKernel(enclosingUnit, kernel);
+
+ /**
+ * Initialize a newly created class element to have the given [name].
+ */
+ MixinElementImpl.forNode(Identifier name) : super.forNode(name);
+
+ /**
+ * Initialize using the given serialized information.
+ */
+ MixinElementImpl.forSerialized(
+ UnlinkedClass unlinkedClass, CompilationUnitElementImpl enclosingUnit)
+ : super.forSerialized(unlinkedClass, enclosingUnit);
+
+ @override
+ bool get isMixin => true;
+
+ @override
+ List<InterfaceType> get superclassConstraints {
+ if (_superclassConstraints == null) {
+ if (_kernel != null) {
+ throw new UnimplementedError();
+ }
+ if (_unlinkedClass != null) {
+ throw new UnimplementedError();
+ }
+ }
+ return _superclassConstraints ?? const <InterfaceType>[];
+ }
+
+ void set superclassConstraints(List<InterfaceType> superclassConstraints) {
+ _assertNotResynthesized(_unlinkedClass);
+ // Note: if we are using kernel or the analysis driver, the set of
+ // superclass constraints has already been computed, and it's more accurate.
+ // So we only store superclass constraints if we are using the old task
+ // model.
+ if (_unlinkedClass == null && _kernel == null) {
+ _superclassConstraints = superclassConstraints;
+ }
+ }
+}
+
+/**
* The constants for all of the modifiers defined by the Dart language and for a
* few additional flags that are useful.
*
@@ -7705,6 +7790,9 @@
bool get hasRequired => false;
@override
+ bool get hasSealed => false;
+
+ @override
bool get hasVisibleForTemplate => false;
@override
@@ -7898,7 +7986,7 @@
* A list the array of executable elements that were used to compose this
* element.
*/
- List<ExecutableElement> _elements = MethodElement.EMPTY_LIST;
+ List<ExecutableElement> _elements = const <MethodElement>[];
MultiplyInheritedMethodElementImpl(Identifier name) : super.forNode(name) {
isSynthetic = true;
@@ -7923,7 +8011,7 @@
* A list the array of executable elements that were used to compose this
* element.
*/
- List<ExecutableElement> _elements = PropertyAccessorElement.EMPTY_LIST;
+ List<ExecutableElement> _elements = const <PropertyAccessorElement>[];
MultiplyInheritedPropertyAccessorElementImpl(Identifier name)
: super.forNode(name) {
@@ -8921,7 +9009,7 @@
String get identifier => "_${super.identifier}";
@override
- List<LibraryElement> get importedLibraries => LibraryElement.EMPTY_LIST;
+ List<LibraryElement> get importedLibraries => const <LibraryElement>[];
@override
ElementKind get kind => ElementKind.PREFIX;
diff --git a/pkg/analyzer/lib/src/dart/element/handle.dart b/pkg/analyzer/lib/src/dart/element/handle.dart
index 6710524..331832d 100644
--- a/pkg/analyzer/lib/src/dart/element/handle.dart
+++ b/pkg/analyzer/lib/src/dart/element/handle.dart
@@ -56,6 +56,9 @@
bool get hasRequired => actualElement.hasRequired;
@override
+ bool get hasSealed => actualElement.hasSealed;
+
+ @override
bool get hasStaticMember => actualElement.hasStaticMember;
@override
@@ -71,6 +74,9 @@
bool get isJS => actualElement.hasJS;
@override
+ bool get isMixin => actualElement.isMixin;
+
+ @override
bool get isMixinApplication => actualElement.isMixinApplication;
@override
@@ -95,6 +101,10 @@
List<InterfaceType> get mixins => actualElement.mixins;
@override
+ List<InterfaceType> get superclassConstraints =>
+ actualElement.superclassConstraints;
+
+ @override
InterfaceType get supertype => actualElement.supertype;
@override
@@ -381,6 +391,9 @@
bool get hasRequired => actualElement.hasRequired;
@override
+ bool get hasSealed => actualElement.hasSealed;
+
+ @override
bool get hasVisibleForTemplate => actualElement.hasVisibleForTemplate;
@override
@@ -1032,7 +1045,7 @@
super.enclosingElement as LibraryElement;
@override
- List<LibraryElement> get importedLibraries => LibraryElement.EMPTY_LIST;
+ List<LibraryElement> get importedLibraries => const <LibraryElement>[];
@override
ElementKind get kind => ElementKind.PREFIX;
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 0599412..5692687 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -419,6 +419,9 @@
bool get hasRequired => _baseElement.hasRequired;
@override
+ bool get hasSealed => _baseElement.hasSealed;
+
+ @override
bool get hasVisibleForTemplate => _baseElement.hasVisibleForTemplate;
@override
@@ -706,7 +709,7 @@
if (type is FunctionType) {
return type.parameters;
}
- return ParameterElement.EMPTY_LIST;
+ return const <ParameterElement>[];
}
@override
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 5b6cbfa..e13eeac 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -103,14 +103,14 @@
CircularFunctionTypeImpl() : super._circular();
@override
- List<ParameterElement> get baseParameters => ParameterElement.EMPTY_LIST;
+ List<ParameterElement> get baseParameters => const <ParameterElement>[];
@override
DartType get baseReturnType => DynamicTypeImpl.instance;
@override
List<TypeParameterElement> get boundTypeParameters =>
- TypeParameterElement.EMPTY_LIST;
+ const <TypeParameterElement>[];
@override
FunctionTypedElement get element => null;
@@ -123,51 +123,51 @@
@override
List<FunctionTypeAliasElement> get newPrune =>
- FunctionTypeAliasElement.EMPTY_LIST;
+ const <FunctionTypeAliasElement>[];
@override
List<String> get normalParameterNames => <String>[];
@override
- List<DartType> get normalParameterTypes => DartType.EMPTY_LIST;
+ List<DartType> get normalParameterTypes => const <DartType>[];
@override
List<String> get optionalParameterNames => <String>[];
@override
- List<DartType> get optionalParameterTypes => DartType.EMPTY_LIST;
+ List<DartType> get optionalParameterTypes => const <DartType>[];
@override
- List<ParameterElement> get parameters => ParameterElement.EMPTY_LIST;
+ List<ParameterElement> get parameters => const <ParameterElement>[];
@override
List<FunctionTypeAliasElement> get prunedTypedefs =>
- FunctionTypeAliasElement.EMPTY_LIST;
+ const <FunctionTypeAliasElement>[];
@override
DartType get returnType => DynamicTypeImpl.instance;
@override
- List<DartType> get typeArguments => DartType.EMPTY_LIST;
+ List<DartType> get typeArguments => const <DartType>[];
@override
- List<TypeParameterElement> get typeFormals => TypeParameterElement.EMPTY_LIST;
+ List<TypeParameterElement> get typeFormals => const <TypeParameterElement>[];
@override
List<TypeParameterElement> get typeParameters =>
- TypeParameterElement.EMPTY_LIST;
+ const <TypeParameterElement>[];
@override
bool get _isInstantiated => false;
@override
- List<ParameterElement> get _parameters => ParameterElement.EMPTY_LIST;
+ List<ParameterElement> get _parameters => const <ParameterElement>[];
@override
DartType get _returnType => DynamicTypeImpl.instance;
@override
- List<DartType> get _typeArguments => DartType.EMPTY_LIST;
+ List<DartType> get _typeArguments => const <DartType>[];
@override
void set _typeArguments(List<DartType> arguments) {
@@ -176,7 +176,7 @@
@override
List<TypeParameterElement> get _typeParameters =>
- TypeParameterElement.EMPTY_LIST;
+ const <TypeParameterElement>[];
@override
void set _typeParameters(List<TypeParameterElement> parameters) {
@@ -799,7 +799,7 @@
void _freeVariablesInFunctionType(
FunctionType type, Set<TypeParameterType> free) {
// Make some fresh variables to avoid capture.
- List<DartType> typeArgs = DartType.EMPTY_LIST;
+ List<DartType> typeArgs = const <DartType>[];
if (type.typeFormals.isNotEmpty) {
typeArgs = new List<DartType>.from(type.typeFormals.map((e) =>
new TypeParameterTypeImpl(new TypeParameterElementImpl(e.name, -1))));
@@ -851,7 +851,7 @@
// For now though, this is a pretty quick operation.
if (g.typeFormals.isEmpty) {
assert(g == f);
- return DartType.EMPTY_LIST;
+ return const <DartType>[];
}
assert(f.typeFormals.isEmpty);
assert(g.typeFormals.length <= f.typeArguments.length);
@@ -1149,7 +1149,7 @@
/**
* A list containing the actual types of the type arguments.
*/
- List<DartType> _typeArguments = DartType.EMPTY_LIST;
+ List<DartType> _typeArguments = const <DartType>[];
/**
* If not `null` and [_typeArguments] is `null`, the actual type arguments
@@ -2756,7 +2756,7 @@
List<TypeParameterElement> typeParameters) {
int count = typeParameters.length;
if (count == 0) {
- return TypeParameterType.EMPTY_LIST;
+ return const <TypeParameterType>[];
}
List<TypeParameterType> types = new List<TypeParameterType>(count);
for (int i = 0; i < count; i++) {
@@ -3061,7 +3061,7 @@
// make it generic, which will allow it to return List<DartType> instead
// of List<TypeParameterType>.
if (typeParameters.isEmpty) {
- _typeArguments = DartType.EMPTY_LIST;
+ _typeArguments = const <DartType>[];
} else {
_typeArguments = new List<DartType>.from(
typeParameters.map((t) => t.type),
@@ -3074,12 +3074,12 @@
@override
List<TypeParameterElement> get typeFormals {
if (_isInstantiated || element == null) {
- return TypeParameterElement.EMPTY_LIST;
+ return const <TypeParameterElement>[];
}
List<TypeParameterElement> baseTypeFormals = element.typeParameters;
int formalCount = baseTypeFormals.length;
if (formalCount == 0) {
- return TypeParameterElement.EMPTY_LIST;
+ return const <TypeParameterElement>[];
}
// Create type formals with specialized bounds.
diff --git a/pkg/analyzer/lib/src/dart/element/wrapped.dart b/pkg/analyzer/lib/src/dart/element/wrapped.dart
index 88291aa..cd3d985 100644
--- a/pkg/analyzer/lib/src/dart/element/wrapped.dart
+++ b/pkg/analyzer/lib/src/dart/element/wrapped.dart
@@ -76,6 +76,9 @@
bool get hasRequired => wrappedUnit.hasRequired;
@override
+ bool get hasSealed => wrappedUnit.hasSealed;
+
+ @override
bool get hasVisibleForTemplate => wrappedUnit.hasVisibleForTemplate;
@override
@@ -252,6 +255,9 @@
bool get hasRequired => wrappedImport.hasRequired;
@override
+ bool get hasSealed => wrappedImport.hasSealed;
+
+ @override
bool get hasVisibleForTemplate => wrappedImport.hasVisibleForTemplate;
@override
@@ -446,6 +452,9 @@
bool get hasRequired => wrappedLib.hasRequired;
@override
+ bool get hasSealed => wrappedLib.hasSealed;
+
+ @override
bool get hasVisibleForTemplate => wrappedLib.hasVisibleForTemplate;
@override
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 97341b4..73b516c 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -297,6 +297,19 @@
correction: "Remove @required.");
/**
+ * This hint is generated anywhere where `@sealed` annotates something other
+ * than a class or mixin.
+ *
+ * Parameters:
+ * 0: the name of the member
+ */
+ static const HintCode INVALID_SEALED_ANNOTATION = const HintCode(
+ 'INVALID_SEALED_ANNOTATION',
+ "The member '{0}' is annotated with @sealed but only classes and mixins "
+ "can be annotated with it.",
+ correction: "Remove @sealed.");
+
+ /**
* This hint is generated anywhere where a member annotated with `@protected`
* is used outside an instance member of a subclass.
*
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 2fde37f..72568c0 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -7,6 +7,11 @@
import 'package:analyzer/dart/ast/standard_ast_factory.dart' as standard;
import 'package:analyzer/dart/ast/token.dart' show Token, TokenType;
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/ast/ast.dart'
+ show
+ ClassDeclarationImpl,
+ ClassOrMixinDeclarationImpl,
+ MixinDeclarationImpl;
import 'package:analyzer/src/fasta/error_converter.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:front_end/src/fasta/parser.dart'
@@ -69,7 +74,10 @@
bool parseGenericMethodComments = false;
/// The class currently being parsed, or `null` if no class is being parsed.
- ClassDeclaration classDeclaration;
+ ClassDeclarationImpl classDeclaration;
+
+ /// The mixin currently being parsed, or `null` if no mixin is being parsed.
+ MixinDeclarationImpl mixinDeclaration;
/// If true, this is building a full AST. Otherwise, only create method
/// bodies.
@@ -215,7 +223,8 @@
for (int i = 1; i < parts.length - 1; i++) {
var part = parts[i];
if (part is Token) {
- elements.add(ast.interpolationString(part, part.lexeme));
+ elements.add(ast.interpolationString(
+ part, unescape(part.lexeme, quote, part, this)));
} else if (part is InterpolationExpression) {
elements.add(part);
} else {
@@ -1745,13 +1754,15 @@
assert(optional('}', rightBracket));
debugEvent("ClassOrMixinBody");
- classDeclaration.leftBracket = leftBracket;
- classDeclaration.rightBracket = rightBracket;
+ ClassOrMixinDeclarationImpl declaration =
+ classDeclaration ?? mixinDeclaration;
+ declaration.leftBracket = leftBracket;
+ declaration.rightBracket = rightBracket;
}
@override
void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
- assert(classDeclaration == null);
+ assert(classDeclaration == null && mixinDeclaration == null);
push(new _Modifiers()..abstractKeyword = abstractToken);
}
@@ -1796,7 +1807,7 @@
void handleClassHeader(Token begin, Token classKeyword, Token nativeToken) {
assert(optional('class', classKeyword));
assert(optionalOrNull('native', nativeToken));
- assert(classDeclaration == null);
+ assert(classDeclaration == null && mixinDeclaration == null);
debugEvent("ClassHeader");
NativeClause nativeClause;
@@ -1828,6 +1839,7 @@
<ClassMember>[],
null, // rightBracket
);
+
classDeclaration.nativeClause = nativeClause;
declarations.add(classDeclaration);
}
@@ -1869,6 +1881,58 @@
}
@override
+ void beginMixinDeclaration(Token mixinKeyword, Token name) {
+ assert(classDeclaration == null && mixinDeclaration == null);
+ }
+
+ @override
+ void handleMixinOn(Token onKeyword, int typeCount) {
+ assert(optionalOrNull('on', onKeyword));
+ debugEvent("MixinOn");
+
+ if (onKeyword != null) {
+ List<TypeName> types = popTypedList(typeCount);
+ push(ast.onClause(onKeyword, types));
+ } else {
+ push(NullValue.IdentifierList);
+ }
+ }
+
+ @override
+ void handleMixinHeader(Token mixinKeyword) {
+ assert(optional('mixin', mixinKeyword));
+ assert(classDeclaration == null && mixinDeclaration == null);
+ debugEvent("MixinHeader");
+
+ ImplementsClause implementsClause = pop(NullValue.IdentifierList);
+ OnClause onClause = pop(NullValue.IdentifierList);
+ TypeParameterList typeParameters = pop();
+ SimpleIdentifier name = pop();
+ List<Annotation> metadata = pop();
+ Comment comment = _findComment(metadata, mixinKeyword);
+
+ mixinDeclaration = ast.mixinDeclaration(
+ comment,
+ metadata,
+ mixinKeyword,
+ name,
+ typeParameters,
+ onClause,
+ implementsClause,
+ null, // leftBracket
+ <ClassMember>[],
+ null, // rightBracket
+ );
+ declarations.add(mixinDeclaration);
+ }
+
+ @override
+ void endMixinDeclaration(Token token) {
+ debugEvent("MixinDeclaration");
+ mixinDeclaration = null;
+ }
+
+ @override
void beginNamedMixinApplication(
Token begin, Token abstractToken, Token name) {
push(new _Modifiers()..abstractKeyword = abstractToken);
@@ -2096,20 +2160,21 @@
ast.simpleIdentifier(typeName.identifier.token, isDeclaration: true);
}
- classDeclaration.members.add(ast.constructorDeclaration(
- comment,
- metadata,
- modifiers?.externalKeyword,
- modifiers?.finalConstOrVarKeyword,
- factoryKeyword,
- ast.simpleIdentifier(returnType.token),
- period,
- name,
- parameters,
- separator,
- null,
- redirectedConstructor,
- body));
+ (classDeclaration ?? mixinDeclaration).members.add(
+ ast.constructorDeclaration(
+ comment,
+ metadata,
+ modifiers?.externalKeyword,
+ modifiers?.finalConstOrVarKeyword,
+ factoryKeyword,
+ ast.simpleIdentifier(returnType.token),
+ period,
+ name,
+ parameters,
+ separator,
+ null,
+ redirectedConstructor,
+ body));
}
void endFieldInitializer(Token assignment, Token token) {
@@ -2312,6 +2377,9 @@
leftParen, <FormalParameter>[], null, null, rightParen);
}
+ ClassOrMixinDeclarationImpl declaration =
+ classDeclaration ?? mixinDeclaration;
+
void constructor(
SimpleIdentifier prefixOrName, Token period, SimpleIdentifier name) {
if (typeParameters != null) {
@@ -2332,7 +2400,7 @@
handleRecoverableError(messageConstructorWithReturnType,
returnType.beginToken, returnType.beginToken);
}
- classDeclaration.members.add(ast.constructorDeclaration(
+ ConstructorDeclaration constructor = ast.constructorDeclaration(
comment,
metadata,
modifiers?.externalKeyword,
@@ -2345,7 +2413,11 @@
separator,
initializers,
redirectedConstructor,
- body));
+ body);
+ declaration.members.add(constructor);
+ if (mixinDeclaration != null) {
+ // TODO (danrubel): Report an error if this is a mixin declaration.
+ }
}
void method(Token operatorKeyword, SimpleIdentifier name) {
@@ -2357,7 +2429,7 @@
messageConstMethod, modifiers.constKeyword, modifiers.constKeyword);
}
checkFieldFormalParameters(parameters);
- classDeclaration.members.add(ast.methodDeclaration(
+ declaration.members.add(ast.methodDeclaration(
comment,
metadata,
modifiers?.externalKeyword,
@@ -2372,7 +2444,7 @@
}
if (name is SimpleIdentifier) {
- if (name.name == classDeclaration.name.name && getOrSet == null) {
+ if (name.name == declaration.name.name && getOrSet == null) {
constructor(name, null, null);
} else if (initializers.isNotEmpty) {
constructor(name, null, null);
@@ -2504,7 +2576,7 @@
Token covariantKeyword = modifiers?.covariantKeyword;
List<Annotation> metadata = pop();
Comment comment = _findComment(metadata, beginToken);
- classDeclaration.members.add(ast.fieldDeclaration2(
+ (classDeclaration ?? mixinDeclaration).members.add(ast.fieldDeclaration2(
comment: comment,
metadata: metadata,
covariantKeyword: covariantKeyword,
@@ -2517,9 +2589,15 @@
AstNode finishFields() {
debugEvent("finishFields");
- return classDeclaration != null
- ? classDeclaration.members.removeAt(classDeclaration.members.length - 1)
- : declarations.removeLast();
+ if (classDeclaration != null) {
+ return classDeclaration.members
+ .removeAt(classDeclaration.members.length - 1);
+ } else if (mixinDeclaration != null) {
+ return mixinDeclaration.members
+ .removeAt(mixinDeclaration.members.length - 1);
+ } else {
+ return declarations.removeLast();
+ }
}
@override
diff --git a/pkg/analyzer/lib/src/fasta/resolution_applier.dart b/pkg/analyzer/lib/src/fasta/resolution_applier.dart
index 6a416b6..3c913ce 100644
--- a/pkg/analyzer/lib/src/fasta/resolution_applier.dart
+++ b/pkg/analyzer/lib/src/fasta/resolution_applier.dart
@@ -919,8 +919,9 @@
return _translatePrefixInfo(data.prefixInfo);
}
return _typeContext.translateReference(data.reference,
- isWriteReference: data.isWriteReference,
+ isNamespaceCombinatorReference: data.isNamespaceCombinatorReference,
isTypeReference: data.isTypeReference,
+ isWriteReference: data.isWriteReference,
inferredType: data.inferredType,
receiverType: data.receiverType);
}
@@ -977,8 +978,9 @@
/// Return the analyzer [Element] for the given kernel node.
Element translateReference(kernel.Node referencedNode,
- {bool isWriteReference = false,
+ {bool isNamespaceCombinatorReference = false,
bool isTypeReference = false,
+ bool isWriteReference = false,
kernel.DartType inferredType,
kernel.DartType receiverType});
diff --git a/pkg/analyzer/lib/src/fasta/resolution_storer.dart b/pkg/analyzer/lib/src/fasta/resolution_storer.dart
index 81ff987..04e1c84 100644
--- a/pkg/analyzer/lib/src/fasta/resolution_storer.dart
+++ b/pkg/analyzer/lib/src/fasta/resolution_storer.dart
@@ -18,6 +18,7 @@
final DartType invokeType;
final bool isExplicitCall;
final bool isImplicitCall;
+ final bool isNamespaceCombinatorReference;
final bool isOutline;
final bool isPrefixReference;
final bool isTypeReference;
@@ -36,6 +37,7 @@
this.invokeType,
this.isExplicitCall = false,
this.isImplicitCall = false,
+ this.isNamespaceCombinatorReference = false,
this.isOutline = false,
this.isPrefixReference = false,
this.isTypeReference = false,
@@ -573,12 +575,14 @@
void propertyAssign(
ExpressionJudgment judgment,
int location,
+ bool isSyntheticLhs,
DartType receiverType,
Node writeMember,
DartType writeContext,
Node combiner,
DartType inferredType) {
_store(location,
+ isSynthetic: isSyntheticLhs,
isWriteReference: true,
reference: writeMember,
writeContext: writeContext,
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index d34072c..8d1810d 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -93,6 +93,7 @@
/**
* An empty list of contexts.
*/
+ @deprecated
static const List<AnalysisContext> EMPTY_LIST = const <AnalysisContext>[];
/**
@@ -1468,14 +1469,9 @@
bool useCFE = false;
@override
- bool get previewDart2 => true;
-
- // A no-op setter.
- set previewDart2(bool value) {}
-
- @override
bool disableCacheFlushing = false;
+ // A no-op setter.
/**
* A flag indicating whether implicit casts are allowed in [strongMode]
* (they are always allowed in Dart 1.0 mode).
@@ -1656,6 +1652,11 @@
}
@override
+ bool get previewDart2 => true;
+
+ set previewDart2(bool value) {}
+
+ @override
Uint32List get signature {
if (_signature == null) {
ApiSignature buffer = new ApiSignature();
@@ -1984,6 +1985,7 @@
/**
* An empty list of change notices.
*/
+ @deprecated
static const List<ChangeNoticeImpl> EMPTY_LIST = const <ChangeNoticeImpl>[];
/**
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index e916ae7..b88db95 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -3897,8 +3897,10 @@
* assigned variable in a for-in statement.
*/
void _checkForInIterable(ForEachStatement node) {
+ DeclaredIdentifier loopVariable = node.loopVariable;
+
// Ignore malformed for statements.
- if (node.identifier == null && node.loopVariable == null) {
+ if (node.identifier == null && loopVariable == null) {
return;
}
@@ -3912,7 +3914,7 @@
}
// The type of the loop variable.
- SimpleIdentifier variable = node.identifier ?? node.loopVariable.identifier;
+ SimpleIdentifier variable = node.identifier ?? loopVariable.identifier;
DartType variableType = getStaticType(variable);
// TODO(mfairhurst) Check and guard against `for(void x in _)`?
@@ -3940,6 +3942,19 @@
}
}
+ if (loopVariable != null) {
+ if (loopVariable.isConst) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, loopVariable);
+ }
+ } else if (node.identifier != null) {
+ Element variableElement = node.identifier.staticElement;
+ if (variableElement is VariableElement && variableElement.isConst) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, node.identifier);
+ }
+ }
+
if (bestIterableType == null) {
_errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 49d1e51..124183c 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -1574,6 +1574,13 @@
// arguments should be constants
_validateConstantArguments(argumentList);
}
+ if (node.elementAnnotation?.isSealed == true &&
+ !(node.parent is ClassDeclaration ||
+ node.parent is ClassTypeAlias ||
+ node.parent is MixinDeclaration)) {
+ _errorReporter.reportErrorForNode(
+ HintCode.INVALID_SEALED_ANNOTATION, node.parent, [node.element.name]);
+ }
return null;
}
@@ -2728,7 +2735,7 @@
List<PropertyAccessorElement> get accessors {
if (_accessors == null) {
- return PropertyAccessorElement.EMPTY_LIST;
+ return const <PropertyAccessorElement>[];
}
List<PropertyAccessorElement> result = _accessors;
_accessors = null;
@@ -2737,7 +2744,7 @@
List<ConstructorElement> get constructors {
if (_constructors == null) {
- return ConstructorElement.EMPTY_LIST;
+ return const <ConstructorElement>[];
}
List<ConstructorElement> result = _constructors;
_constructors = null;
@@ -2746,7 +2753,7 @@
List<ClassElement> get enums {
if (_enums == null) {
- return ClassElement.EMPTY_LIST;
+ return const <ClassElement>[];
}
List<ClassElement> result = _enums;
_enums = null;
@@ -2755,7 +2762,7 @@
List<FieldElement> get fields {
if (_fields == null) {
- return FieldElement.EMPTY_LIST;
+ return const <FieldElement>[];
}
List<FieldElement> result = _fields;
_fields = null;
@@ -2764,7 +2771,7 @@
List<FieldElement> get fieldsWithoutFlushing {
if (_fields == null) {
- return FieldElement.EMPTY_LIST;
+ return const <FieldElement>[];
}
List<FieldElement> result = _fields;
return result;
@@ -2772,7 +2779,7 @@
List<FunctionElement> get functions {
if (_functions == null) {
- return FunctionElement.EMPTY_LIST;
+ return const <FunctionElement>[];
}
List<FunctionElement> result = _functions;
_functions = null;
@@ -2781,7 +2788,7 @@
List<LabelElement> get labels {
if (_labels == null) {
- return LabelElement.EMPTY_LIST;
+ return const <LabelElement>[];
}
List<LabelElement> result = _labels;
_labels = null;
@@ -2790,7 +2797,7 @@
List<LocalVariableElement> get localVariables {
if (_localVariables == null) {
- return LocalVariableElement.EMPTY_LIST;
+ return const <LocalVariableElement>[];
}
List<LocalVariableElement> result = _localVariables;
_localVariables = null;
@@ -2799,7 +2806,7 @@
List<MethodElement> get methods {
if (_methods == null) {
- return MethodElement.EMPTY_LIST;
+ return const <MethodElement>[];
}
List<MethodElement> result = _methods;
_methods = null;
@@ -2808,7 +2815,7 @@
List<ParameterElement> get parameters {
if (_parameters == null) {
- return ParameterElement.EMPTY_LIST;
+ return const <ParameterElement>[];
}
List<ParameterElement> result = _parameters;
_parameters = null;
@@ -2817,7 +2824,7 @@
List<TopLevelVariableElement> get topLevelVariables {
if (_topLevelVariables == null) {
- return TopLevelVariableElement.EMPTY_LIST;
+ return const <TopLevelVariableElement>[];
}
List<TopLevelVariableElement> result = _topLevelVariables;
_topLevelVariables = null;
@@ -2826,7 +2833,7 @@
List<FunctionTypeAliasElement> get typeAliases {
if (_typeAliases == null) {
- return FunctionTypeAliasElement.EMPTY_LIST;
+ return const <FunctionTypeAliasElement>[];
}
List<FunctionTypeAliasElement> result = _typeAliases;
_typeAliases = null;
@@ -2835,7 +2842,7 @@
List<TypeParameterElement> get typeParameters {
if (_typeParameters == null) {
- return TypeParameterElement.EMPTY_LIST;
+ return const <TypeParameterElement>[];
}
List<TypeParameterElement> result = _typeParameters;
_typeParameters = null;
@@ -2844,7 +2851,7 @@
List<ClassElement> get types {
if (_types == null) {
- return ClassElement.EMPTY_LIST;
+ return const <ClassElement>[];
}
List<ClassElement> result = _types;
_types = null;
@@ -6606,8 +6613,8 @@
ts is StrongTypeSystemImpl) {
return ts.inferGenericFunctionOrType<FunctionType>(
uninstantiatedType,
- ParameterElement.EMPTY_LIST,
- DartType.EMPTY_LIST,
+ const <ParameterElement>[],
+ const <DartType>[],
InferenceContext.getContext(inferenceNode),
downwards: true,
errorReporter: errorReporter,
@@ -8172,51 +8179,20 @@
}
DartType type = null;
if (element is ClassElement) {
+ _setElement(typeName, element);
type = element.type;
- // In non-strong mode `FutureOr<T>` is treated as `dynamic`
- if (!typeSystem.isStrong && type.isDartAsyncFutureOr) {
- type = dynamicType;
- _setElement(typeName, type.element);
- typeName.staticType = type;
- node.type = type;
- if (argumentList != null) {
- NodeList<TypeAnnotation> arguments = argumentList.arguments;
- if (arguments.length != 1) {
- reportErrorForNode(_getInvalidTypeParametersErrorCode(node), node,
- [typeName.name, 1, arguments.length]);
- }
- }
- return;
- }
+ } else if (element == DynamicElementImpl.instance) {
_setElement(typeName, element);
- } else if (element is TypeDefiningElement &&
- element.kind == ElementKind.DYNAMIC) {
-// if (argumentList != null) {
-// // Type parameters cannot have type arguments.
-// // TODO(mfairhurst) Report this error.
-// resolver.reportError(ResolverErrorCode.?, keyType);
-// }
- _setElement(typeName, element);
- typeName.staticType = element.type;
- node.type = element.type;
- return;
+ type = DynamicTypeImpl.instance;
} else if (element is FunctionTypeAliasElement) {
_setElement(typeName, element);
type = element.type;
} else if (element is TypeParameterElement) {
_setElement(typeName, element);
type = element.type;
-// if (argumentList != null) {
-// // Type parameters cannot have type arguments.
-// // TODO(brianwilkerson) Report this error.
-// // resolver.reportError(ResolverErrorCode.?, keyType);
-// }
} else if (element is MultiplyDefinedElement) {
List<Element> elements = element.conflictingElements;
type = _getTypeWhenMultiplyDefined(elements);
- if (type != null) {
- node.type = type;
- }
} else {
// The name does not represent a type.
RedirectingConstructorKind redirectingConstructorKind;
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 4d19bff..d6c07ff 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -185,8 +185,7 @@
}
static ExportElementImpl exportFor(LibraryElement exportedLibrary,
- [List<NamespaceCombinator> combinators =
- NamespaceCombinator.EMPTY_LIST]) {
+ [List<NamespaceCombinator> combinators = const <NamespaceCombinator>[]]) {
ExportElementImpl spec = new ExportElementImpl(-1);
spec.exportedLibrary = exportedLibrary;
spec.combinators = combinators;
@@ -407,8 +406,7 @@
static ImportElementImpl importFor(
LibraryElement importedLibrary, PrefixElement prefix,
- [List<NamespaceCombinator> combinators =
- NamespaceCombinator.EMPTY_LIST]) {
+ [List<NamespaceCombinator> combinators = const <NamespaceCombinator>[]]) {
ImportElementImpl spec = new ImportElementImpl(0);
spec.importedLibrary = importedLibrary;
spec.prefix = prefix;
@@ -436,7 +434,7 @@
[List<DartType> argumentTypes]) {
MethodElementImpl method = new MethodElementImpl(methodName, 0);
if (argumentTypes == null) {
- method.parameters = ParameterElement.EMPTY_LIST;
+ method.parameters = const <ParameterElement>[];
} else {
int count = argumentTypes.length;
List<ParameterElement> parameters = new List<ParameterElement>(count);
@@ -593,7 +591,7 @@
static List<TypeParameterElement> typeParameters(List<String> names) {
int count = names.length;
if (count == 0) {
- return TypeParameterElement.EMPTY_LIST;
+ return const <TypeParameterElement>[];
}
List<TypeParameterElementImpl> typeParameters =
new List<TypeParameterElementImpl>(count);
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 2960e79..2a7ac3e 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -2022,7 +2022,7 @@
} else if (type is InterfaceType) {
return type.typeParameters;
} else {
- return TypeParameterElement.EMPTY_LIST;
+ return const <TypeParameterElement>[];
}
}
diff --git a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
index 2d7db0f..18dc9b8 100644
--- a/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary/package_bundle_reader.dart
@@ -189,7 +189,7 @@
if (result == TYPE_PROVIDER) {
entry.setValue(result as ResultDescriptor<TypeProvider>,
- _resynthesizer.typeProvider, TargetedResult.EMPTY_LIST);
+ _resynthesizer.typeProvider, const <TargetedResult>[]);
return true;
}
@@ -202,7 +202,7 @@
if (lineStarts.isNotEmpty) {
LineInfo lineInfo = new LineInfo(lineStarts);
entry.setValue(result as ResultDescriptor<LineInfo>, lineInfo,
- TargetedResult.EMPTY_LIST);
+ const <TargetedResult>[]);
return true;
}
}
@@ -217,7 +217,7 @@
if (result == CONSTANT_EXPRESSION_RESOLVED &&
target is ConstantEvaluationTarget) {
entry.setValue(
- result as ResultDescriptor<bool>, true, TargetedResult.EMPTY_LIST);
+ result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
return true;
}
// Provide results for Source.
@@ -237,17 +237,17 @@
LibraryElement libraryElement =
resynthesizer.getLibraryElement(uriString);
entry.setValue(result as ResultDescriptor<LibraryElement>,
- libraryElement, TargetedResult.EMPTY_LIST);
+ libraryElement, const <TargetedResult>[]);
return true;
} else if (result == READY_LIBRARY_ELEMENT2 ||
result == READY_LIBRARY_ELEMENT6 ||
result == READY_LIBRARY_ELEMENT7) {
entry.setValue(
- result as ResultDescriptor<bool>, true, TargetedResult.EMPTY_LIST);
+ result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
return true;
} else if (result == MODIFICATION_TIME) {
entry.setValue(
- result as ResultDescriptor<int>, 0, TargetedResult.EMPTY_LIST);
+ result as ResultDescriptor<int>, 0, const <TargetedResult>[]);
return true;
} else if (result == SOURCE_KIND) {
UnlinkedUnit unlinked = _dataStore.unlinkedMap[uriString];
@@ -255,7 +255,7 @@
entry.setValue(
result as ResultDescriptor<SourceKind>,
unlinked.isPartOf ? SourceKind.PART : SourceKind.LIBRARY,
- TargetedResult.EMPTY_LIST);
+ const <TargetedResult>[]);
return true;
}
return false;
@@ -268,7 +268,7 @@
context.sourceFactory.resolveUri(target, libraryUriString))
.toList(growable: false);
entry.setValue(result as ResultDescriptor<List<Source>>,
- librarySources, TargetedResult.EMPTY_LIST);
+ librarySources, const <TargetedResult>[]);
return true;
}
return false;
@@ -286,7 +286,7 @@
result == CREATED_RESOLVED_UNIT10 ||
result == CREATED_RESOLVED_UNIT11) {
entry.setValue(
- result as ResultDescriptor<bool>, true, TargetedResult.EMPTY_LIST);
+ result as ResultDescriptor<bool>, true, const <TargetedResult>[]);
return true;
}
if (result == COMPILATION_UNIT_ELEMENT) {
@@ -296,14 +296,14 @@
new ElementLocationImpl.con3(<String>[libraryUri, unitUri]));
if (unit != null) {
entry.setValue(result as ResultDescriptor<CompilationUnitElement>,
- unit, TargetedResult.EMPTY_LIST);
+ unit, const <TargetedResult>[]);
return true;
}
}
} else if (target is VariableElement) {
if (result == INFERRED_STATIC_VARIABLE) {
entry.setValue(result as ResultDescriptor<VariableElement>, target,
- TargetedResult.EMPTY_LIST);
+ const <TargetedResult>[]);
return true;
}
}
diff --git a/pkg/analyzer/lib/src/task/api/dart.dart b/pkg/analyzer/lib/src/task/api/dart.dart
index 44ef9b8..d8f28ff 100644
--- a/pkg/analyzer/lib/src/task/api/dart.dart
+++ b/pkg/analyzer/lib/src/task/api/dart.dart
@@ -29,7 +29,7 @@
*/
final ListResultDescriptor<Source> EXPLICITLY_IMPORTED_LIBRARIES =
new ListResultDescriptor<Source>(
- 'EXPLICITLY_IMPORTED_LIBRARIES', Source.EMPTY_LIST);
+ 'EXPLICITLY_IMPORTED_LIBRARIES', const <Source>[]);
/**
* The sources of the libraries that are exported from a library.
@@ -40,7 +40,7 @@
* The result is only available for [Source]s representing a library.
*/
final ListResultDescriptor<Source> EXPORTED_LIBRARIES =
- new ListResultDescriptor<Source>('EXPORTED_LIBRARIES', Source.EMPTY_LIST);
+ new ListResultDescriptor<Source>('EXPORTED_LIBRARIES', const <Source>[]);
/**
* The sources of the libraries that are implicitly or explicitly imported into
@@ -52,7 +52,7 @@
* The result is only available for [Source]s representing a library.
*/
final ListResultDescriptor<Source> IMPORTED_LIBRARIES =
- new ListResultDescriptor<Source>('IMPORTED_LIBRARIES', Source.EMPTY_LIST);
+ new ListResultDescriptor<Source>('IMPORTED_LIBRARIES', const <Source>[]);
/**
* The sources of the parts that are included in a library.
@@ -63,7 +63,7 @@
* The result is only available for [Source]s representing a library.
*/
final ListResultDescriptor<Source> INCLUDED_PARTS =
- new ListResultDescriptor<Source>('INCLUDED_PARTS', Source.EMPTY_LIST);
+ new ListResultDescriptor<Source>('INCLUDED_PARTS', const <Source>[]);
/**
* A flag specifying whether a library is launchable.
@@ -129,7 +129,7 @@
* The result is only available for [Source]s representing a library.
*/
final ListResultDescriptor<Source> UNITS =
- new ListResultDescriptor<Source>('UNITS', Source.EMPTY_LIST);
+ new ListResultDescriptor<Source>('UNITS', const <Source>[]);
/**
* A specific compilation unit in a specific library.
@@ -140,6 +140,7 @@
* change if a single part is included in more than one library.
*/
class LibrarySpecificUnit implements AnalysisTarget {
+ @deprecated
static const List<LibrarySpecificUnit> EMPTY_LIST =
const <LibrarySpecificUnit>[];
diff --git a/pkg/analyzer/lib/src/task/api/html.dart b/pkg/analyzer/lib/src/task/api/html.dart
index 4005bcc..8a7cae8 100644
--- a/pkg/analyzer/lib/src/task/api/html.dart
+++ b/pkg/analyzer/lib/src/task/api/html.dart
@@ -24,4 +24,4 @@
* The sources of the Dart libraries referenced by an HTML file.
*/
final ListResultDescriptor<Source> REFERENCED_LIBRARIES =
- new ListResultDescriptor<Source>('REFERENCED_LIBRARIES', Source.EMPTY_LIST);
+ new ListResultDescriptor<Source>('REFERENCED_LIBRARIES', const <Source>[]);
diff --git a/pkg/analyzer/lib/src/task/api/model.dart b/pkg/analyzer/lib/src/task/api/model.dart
index 0ba6aec..703d8b8 100644
--- a/pkg/analyzer/lib/src/task/api/model.dart
+++ b/pkg/analyzer/lib/src/task/api/model.dart
@@ -510,6 +510,7 @@
/**
* An empty list of results.
*/
+ @deprecated
static final List<TargetedResult> EMPTY_LIST = const <TargetedResult>[];
/**
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index ca7b0eb..7ab1b66 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -190,7 +190,7 @@
* The result is only available for [Source]s representing a compilation unit.
*/
final ListResultDescriptor<Source> CONTAINING_LIBRARIES =
- new ListResultDescriptor<Source>('CONTAINING_LIBRARIES', Source.EMPTY_LIST);
+ new ListResultDescriptor<Source>('CONTAINING_LIBRARIES', const <Source>[]);
/**
* The flag specifying that [RESOLVED_UNIT] has been been computed for this
@@ -575,7 +575,7 @@
*/
final ListResultDescriptor<LibrarySpecificUnit> LIBRARY_SPECIFIC_UNITS =
new ListResultDescriptor<LibrarySpecificUnit>(
- 'LIBRARY_SPECIFIC_UNITS', LibrarySpecificUnit.EMPTY_LIST);
+ 'LIBRARY_SPECIFIC_UNITS', const <LibrarySpecificUnit>[]);
/**
* The analysis errors associated with a compilation unit in a specific library.
@@ -662,7 +662,7 @@
* The result is only available for [Source]s representing a library.
*/
final ListResultDescriptor<Source> REFERENCED_SOURCES =
- new ListResultDescriptor<Source>('REFERENCED_SOURCES', Source.EMPTY_LIST);
+ new ListResultDescriptor<Source>('REFERENCED_SOURCES', const <Source>[]);
/**
* The list of [ConstantEvaluationTarget]s on which error verification depends.
diff --git a/pkg/analyzer/lib/src/task/dart_work_manager.dart b/pkg/analyzer/lib/src/task/dart_work_manager.dart
index 5225f5e..2a27c15 100644
--- a/pkg/analyzer/lib/src/task/dart_work_manager.dart
+++ b/pkg/analyzer/lib/src/task/dart_work_manager.dart
@@ -202,7 +202,7 @@
}
List<Source> libraries = partLibrariesMap[part];
libraries ??= _getLibrariesContainingPartFromResultProvider(part);
- return libraries?.toList() ?? Source.EMPTY_LIST;
+ return libraries?.toList() ?? const <Source>[];
}
@override
diff --git a/pkg/analyzer/lib/src/task/html.dart b/pkg/analyzer/lib/src/task/html.dart
index 8de0347e..c72d99f 100644
--- a/pkg/analyzer/lib/src/task/html.dart
+++ b/pkg/analyzer/lib/src/task/html.dart
@@ -23,7 +23,7 @@
* The Dart scripts that are embedded in an HTML file.
*/
final ListResultDescriptor<DartScript> DART_SCRIPTS =
- new ListResultDescriptor<DartScript>('DART_SCRIPTS', DartScript.EMPTY_LIST);
+ new ListResultDescriptor<DartScript>('DART_SCRIPTS', const <DartScript>[]);
/**
* The errors found while parsing an HTML file.
@@ -39,7 +39,8 @@
/**
* An empty list of scripts.
*/
- static final List<DartScript> EMPTY_LIST = <DartScript>[];
+ @deprecated
+ static final List<DartScript> EMPTY_LIST = const <DartScript>[];
/**
* The source containing this script.
@@ -157,9 +158,9 @@
// Record outputs.
//
outputs[REFERENCED_LIBRARIES] =
- libraries.isEmpty ? Source.EMPTY_LIST : libraries;
+ libraries.isEmpty ? const <Source>[] : libraries;
outputs[DART_SCRIPTS] =
- inlineScripts.isEmpty ? DartScript.EMPTY_LIST : inlineScripts;
+ inlineScripts.isEmpty ? const <DartScript>[] : inlineScripts;
}
/**
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart
index 76f3f4e..2bb645b 100644
--- a/pkg/analyzer/test/generated/analysis_context_factory.dart
+++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -325,7 +325,7 @@
];
htmlUnit.functions = <FunctionElement>[
ElementFactory.functionElement3("query", elementElement.type,
- <ClassElement>[provider.stringType.element], ClassElement.EMPTY_LIST)
+ <ClassElement>[provider.stringType.element], const <ClassElement>[])
];
TopLevelVariableElementImpl document =
ElementFactory.topLevelVariableElement3(
@@ -347,14 +347,14 @@
"cos",
provider.doubleType,
<ClassElement>[provider.numType.element],
- ClassElement.EMPTY_LIST);
+ const <ClassElement>[]);
TopLevelVariableElement ln10Element =
ElementFactory.topLevelVariableElement3(
"LN10", true, false, provider.doubleType);
TypeParameterElement maxT =
ElementFactory.typeParameterWithType('T', provider.numType);
FunctionElementImpl maxElement = ElementFactory.functionElement3(
- "max", maxT.type, [maxT, maxT], ClassElement.EMPTY_LIST);
+ "max", maxT.type, [maxT, maxT], const <ClassElement>[]);
maxElement.typeParameters = [maxT];
maxElement.type = new FunctionTypeImpl(maxElement);
TopLevelVariableElement piElement = ElementFactory.topLevelVariableElement3(
@@ -373,12 +373,12 @@
"sin",
provider.doubleType,
<ClassElement>[provider.numType.element],
- ClassElement.EMPTY_LIST);
+ const <ClassElement>[]);
FunctionElement sqrtElement = ElementFactory.functionElement3(
"sqrt",
provider.doubleType,
<ClassElement>[provider.numType.element],
- ClassElement.EMPTY_LIST);
+ const <ClassElement>[]);
mathUnit.accessors = <PropertyAccessorElement>[
ln10Element.getter,
piElement.getter
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
index d6835c5..0cd7e62 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart
@@ -301,6 +301,12 @@
@override
@failingTest
+ test_forInWithConstVariable_forEach_identifier() async {
+ return super.test_forInWithConstVariable_forEach_identifier();
+ }
+
+ @override
+ @failingTest
test_genericFunctionTypeArgument_class() async {
await super.test_genericFunctionTypeArgument_class();
}
@@ -431,42 +437,12 @@
@override
@failingTest
- test_implementsRepeated() async {
- await super.test_implementsRepeated();
- }
-
- @override
- @failingTest
test_implementsRepeated_3times() async {
await super.test_implementsRepeated_3times();
}
@override
@failingTest
- test_implementsSuperClass() async {
- await super.test_implementsSuperClass();
- }
-
- @override
- @failingTest
- test_implementsSuperClass_Object() async {
- await super.test_implementsSuperClass_Object();
- }
-
- @override
- @failingTest
- test_implementsSuperClass_Object_typeAlias() async {
- await super.test_implementsSuperClass_Object_typeAlias();
- }
-
- @override
- @failingTest
- test_implementsSuperClass_typeAlias() async {
- await super.test_implementsSuperClass_typeAlias();
- }
-
- @override
- @failingTest
test_implicitThisReferenceInInitializer_field() async {
await super.test_implicitThisReferenceInInitializer_field();
}
@@ -1219,53 +1195,17 @@
@override
@failingTest
- test_superInInvalidContext_binaryExpression() async {
- await super.test_superInInvalidContext_binaryExpression();
- }
-
- @override
- @failingTest
test_superInInvalidContext_constructorFieldInitializer() async {
await super.test_superInInvalidContext_constructorFieldInitializer();
}
@override
@failingTest
- test_superInInvalidContext_factoryConstructor() async {
- await super.test_superInInvalidContext_factoryConstructor();
- }
-
- @override
- @failingTest
test_superInInvalidContext_instanceVariableInitializer() async {
await super.test_superInInvalidContext_instanceVariableInitializer();
}
@override
- @failingTest
- test_superInInvalidContext_staticMethod() async {
- await super.test_superInInvalidContext_staticMethod();
- }
-
- @override
- @failingTest
- test_superInInvalidContext_staticVariableInitializer() async {
- await super.test_superInInvalidContext_staticVariableInitializer();
- }
-
- @override
- @failingTest
- test_superInInvalidContext_topLevelFunction() async {
- await super.test_superInInvalidContext_topLevelFunction();
- }
-
- @override
- @failingTest
- test_superInInvalidContext_topLevelVariableInitializer() async {
- await super.test_superInInvalidContext_topLevelVariableInitializer();
- }
-
- @override
@failingTest // Deliberately only reports one of the expected errors.
test_superInRedirectingConstructor_superRedirection() async {
await super.test_superInRedirectingConstructor_superRedirection();
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 81013ce..d2202d1 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -2965,6 +2965,27 @@
verify([source]);
}
+ test_forInWithConstVariable_forEach_identifier() async {
+ Source source = addSource(r'''
+f() {
+ const x = 0;
+ for (x in [0, 1, 2]) {}
+}''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+ verify([source]);
+ }
+
+ test_forInWithConstVariable_forEach_loopVariable() async {
+ Source source = addSource(r'''
+f() {
+ for (const x in [0, 1, 2]) {}
+}''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+ verify([source]);
+ }
+
test_fromEnvironment_bool_badArgs() async {
Source source = addSource(r'''
var b1 = const bool.fromEnvironment(1);
@@ -7467,7 +7488,11 @@
test_superInInvalidContext_binaryExpression() async {
Source source = addSource("var v = super + 0;");
await computeAnalysisResult(source);
- assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+ assertErrors(
+ source,
+ useCFE
+ ? [CompileTimeErrorCode.SUPER_AS_EXPRESSION]
+ : [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
// no verify(), 'super.v' is not resolved
}
@@ -7497,7 +7522,11 @@
}
}''');
await computeAnalysisResult(source);
- assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+ assertErrors(
+ source,
+ useCFE
+ ? [CompileTimeErrorCode.SUPER_AS_EXPRESSION]
+ : [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
// no verify(), 'super.m' is not resolved
}
@@ -7523,7 +7552,11 @@
static n() { return super.m(); }
}''');
await computeAnalysisResult(source);
- assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+ assertErrors(
+ source,
+ useCFE
+ ? [CompileTimeErrorCode.SUPER_AS_EXPRESSION]
+ : [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
// no verify(), 'super.m' is not resolved
}
@@ -7536,7 +7569,11 @@
static int b = super.a;
}''');
await computeAnalysisResult(source);
- assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+ assertErrors(
+ source,
+ useCFE
+ ? [CompileTimeErrorCode.SUPER_AS_EXPRESSION]
+ : [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
// no verify(), 'super.a' is not resolved
}
@@ -7546,14 +7583,22 @@
super.f();
}''');
await computeAnalysisResult(source);
- assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+ assertErrors(
+ source,
+ useCFE
+ ? [CompileTimeErrorCode.SUPER_AS_EXPRESSION]
+ : [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
// no verify(), 'super.f' is not resolved
}
test_superInInvalidContext_topLevelVariableInitializer() async {
Source source = addSource("var v = super.y;");
await computeAnalysisResult(source);
- assertErrors(source, [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
+ assertErrors(
+ source,
+ useCFE
+ ? [CompileTimeErrorCode.SUPER_AS_EXPRESSION]
+ : [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT]);
// no verify(), 'super.y' is not resolved
}
diff --git a/pkg/analyzer/test/generated/engine_test.dart b/pkg/analyzer/test/generated/engine_test.dart
index 75c40b4..f1d150d 100644
--- a/pkg/analyzer/test/generated/engine_test.dart
+++ b/pkg/analyzer/test/generated/engine_test.dart
@@ -192,7 +192,7 @@
static void assertEvent(SourcesChangedEvent event,
{bool wereSourcesAdded: false,
- List<Source> changedSources: Source.EMPTY_LIST,
+ List<Source> changedSources: const <Source>[],
bool wereSourcesRemoved: false}) {
expect(event.wereSourcesAdded, wereSourcesAdded);
expect(event.changedSources, changedSources);
@@ -205,7 +205,7 @@
void assertEvent(
{bool wereSourcesAdded: false,
- List<Source> changedSources: Source.EMPTY_LIST,
+ List<Source> changedSources: const <Source>[],
bool wereSourcesRemovedOrDeleted: false}) {
if (actualEvents.isEmpty) {
fail('Expected event but found none');
diff --git a/pkg/analyzer/test/generated/hint_code_kernel_test.dart b/pkg/analyzer/test/generated/hint_code_kernel_test.dart
index 3e9f85c..073e8c5 100644
--- a/pkg/analyzer/test/generated/hint_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_kernel_test.dart
@@ -83,18 +83,6 @@
return super.test_deprecatedFunction_mixin2();
}
- @failingTest
- @override
- test_duplicateShownHiddenName_hidden() {
- return super.test_duplicateShownHiddenName_hidden();
- }
-
- @failingTest
- @override
- test_duplicateShownHiddenName_shown() {
- return super.test_duplicateShownHiddenName_shown();
- }
-
@override
@failingTest
test_invalidRequiredParam_on_named_parameter_with_default() async {
@@ -169,6 +157,13 @@
@failingTest
@override
+ // Failing due to https://github.com/dart-lang/sdk/issues/34249
+ test_invalidSealedAnnotation_onMixinApplication() async {
+ return super.test_invalidSealedAnnotation_onMixinApplication();
+ }
+
+ @failingTest
+ @override
test_strongMode_downCastCompositeHint() async {
return super.test_strongMode_downCastCompositeHint();
}
@@ -184,28 +179,4 @@
test_unusedImport_inComment_libraryDirective() async {
return super.test_unusedImport_inComment_libraryDirective();
}
-
- @failingTest
- @override
- test_unusedShownName() async {
- return super.test_unusedShownName();
- }
-
- @failingTest
- @override
- test_unusedShownName_as() async {
- return super.test_unusedShownName_as();
- }
-
- @failingTest
- @override
- test_unusedShownName_duplicates() async {
- return super.test_unusedShownName_duplicates();
- }
-
- @failingTest
- @override
- test_unusedShownName_topLevelVariable() async {
- return super.test_unusedShownName_topLevelVariable();
- }
}
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 7235f38..36f7faa 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -38,6 +38,7 @@
const _MustCallSuper mustCallSuper = const _MustCallSuper();
const _Protected protected = const _Protected();
const Required required = const Required();
+const _Sealed sealed = const _Sealed();
const _VisibleForTesting visibleForTesting = const _VisibleForTesting();
class Immutable {
@@ -63,6 +64,9 @@
final String reason;
const Required([this.reason]);
}
+class _Sealed {
+ const _Sealed();
+}
class _VisibleForTesting {
const _VisibleForTesting();
}
@@ -1654,6 +1658,55 @@
verify([source]);
}
+ test_invalidSealedAnnotation_onNonClass() async {
+ Source source = addNamedSource('/lib1.dart', r'''
+import 'package:meta/meta.dart';
+
+@sealed m({a = 1}) => null;
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [HintCode.INVALID_SEALED_ANNOTATION]);
+ verify([source]);
+ }
+
+ test_invalidSealedAnnotation_onClass() async {
+ Source source = addNamedSource('/lib1.dart', r'''
+import 'package:meta/meta.dart';
+
+@sealed class A {}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ test_invalidSealedAnnotation_onMixinApplication() async {
+ Source source = addNamedSource('/lib1.dart', r'''
+import 'package:meta/meta.dart';
+
+abstract class A {}
+
+abstract class B {}
+
+@sealed abstract class M = A with B;
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
+ @failingTest
+ test_invalidSealedAnnotation_onMixin() async {
+ Source source = addNamedSource('/lib1.dart', r'''
+import 'package:meta/meta.dart';
+
+@sealed mixin M {}
+''');
+ await computeAnalysisResult(source);
+ assertNoErrors(source);
+ verify([source]);
+ }
+
test_invalidUseOfProtectedMember_closure() async {
Source source = addNamedSource('/lib1.dart', r'''
import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart b/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
index 82c52fb..f4f1192 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
@@ -40,20 +40,6 @@
@override
@failingTest
- @AnalyzerProblem('https://github.com/dart-lang/sdk/issues/33636')
- test_ambiguousImport_showCombinator() async {
- return super.test_ambiguousImport_showCombinator();
- }
-
- @override
- @failingTest
- @FastaProblem('https://github.com/dart-lang/sdk/issues/33795')
- test_annotated_partOfDeclaration() async {
- return super.test_annotated_partOfDeclaration();
- }
-
- @override
- @failingTest
@FastaProblem('https://github.com/dart-lang/sdk/issues/31604')
test_commentReference_beforeConstructor() async {
return super.test_commentReference_beforeConstructor();
@@ -191,12 +177,6 @@
@override
@failingTest
- test_optionalNew_rewrite() {
- return super.test_optionalNew_rewrite();
- }
-
- @override
- @failingTest
test_undefinedIdentifier_synthetic_whenMethodName() async {
return super.test_undefinedIdentifier_synthetic_whenMethodName();
}
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index a2a00ea..58d3b70 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -1487,9 +1487,6 @@
test_constEvalTypeBoolNumString_equal() async {
Source source = addSource(r'''
-class A {
- const A();
-}
class B {
final v;
const B.a1(bool p) : v = p == true;
@@ -1509,6 +1506,8 @@
const B.c5(String p) : v = p == '';
const B.n1(num p) : v = p == null;
const B.n2(num p) : v = null == p;
+ const B.n3(Object p) : v = p == null;
+ const B.n4(Object p) : v = null == p;
}''');
await computeAnalysisResult(source);
assertNoErrors(source);
@@ -1516,9 +1515,6 @@
test_constEvalTypeBoolNumString_notEqual() async {
Source source = addSource(r'''
-class A {
- const A();
-}
class B {
final v;
const B.a1(bool p) : v = p != true;
@@ -1538,13 +1534,15 @@
const B.c5(String p) : v = p != '';
const B.n1(num p) : v = p != null;
const B.n2(num p) : v = null != p;
+ const B.n3(Object p) : v = p != null;
+ const B.n4(Object p) : v = null != p;
}''');
await computeAnalysisResult(source);
assertNoErrors(source);
verify([source]);
}
- test_constEvelTypeNum_String() async {
+ test_constEvAlTypeNum_String() async {
Source source = addSource(r'''
const String A = 'a';
const String B = A + 'b';
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index 40f2c23..d61baab 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -393,6 +393,12 @@
}
@override
+ void beginMixinDeclaration(Token mixinKeyword, Token name) {
+ super.beginMixinDeclaration(mixinKeyword, name);
+ begin('MixinDeclaration');
+ }
+
+ @override
void beginNamedFunctionExpression(Token token) {
super.beginNamedFunctionExpression(token);
begin('NamedFunctionExpression');
@@ -903,6 +909,12 @@
}
@override
+ void endMixinDeclaration(Token token) {
+ end('MixinDeclaration');
+ super.endMixinDeclaration(token);
+ }
+
+ @override
void endNamedFunctionExpression(Token endToken) {
end('NamedFunctionExpression');
super.endNamedFunctionExpression(endToken);
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index db49d52..118210a 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -1038,6 +1038,16 @@
StringLiteral literal = expression.expression;
expect(literal.stringValue, 'a');
}
+
+ @failingTest
+ @override
+ void test_parseCommentReferences_skipLink_direct_multiLine() =>
+ super.test_parseCommentReferences_skipLink_direct_multiLine();
+
+ @failingTest
+ @override
+ void test_parseCommentReferences_skipLink_reference_multiLine() =>
+ super.test_parseCommentReferences_skipLink_reference_multiLine();
}
/**
@@ -1140,4 +1150,197 @@
allowNativeClause = false;
test_parseClassDeclaration_native();
}
+
+ void test_parseMixinDeclaration_empty() {
+ createParser('mixin A {}');
+ _parserProxy.fastaParser.isMixinSupportEnabled = true;
+ MixinDeclaration declaration = parseFullCompilationUnitMember();
+ expect(declaration, isNotNull);
+ assertNoErrors();
+ expect(declaration.metadata, isEmpty);
+ expect(declaration.documentationComment, isNull);
+ expect(declaration.onClause, isNull);
+ expect(declaration.implementsClause, isNull);
+ expect(declaration.mixinKeyword, isNotNull);
+ expect(declaration.leftBracket, isNotNull);
+ expect(declaration.name.name, 'A');
+ expect(declaration.members, hasLength(0));
+ expect(declaration.rightBracket, isNotNull);
+ expect(declaration.typeParameters, isNull);
+ }
+
+ void test_parseMixinDeclaration_implements() {
+ createParser('mixin A implements B {}');
+ _parserProxy.fastaParser.isMixinSupportEnabled = true;
+ MixinDeclaration declaration = parseFullCompilationUnitMember();
+ expect(declaration, isNotNull);
+ assertNoErrors();
+ expect(declaration.metadata, isEmpty);
+ expect(declaration.documentationComment, isNull);
+ expect(declaration.onClause, isNull);
+ ImplementsClause implementsClause = declaration.implementsClause;
+ expect(implementsClause.implementsKeyword, isNotNull);
+ NodeList<TypeName> interfaces = implementsClause.interfaces;
+ expect(interfaces, hasLength(1));
+ expect(interfaces[0].name.name, 'B');
+ expect(interfaces[0].typeArguments, isNull);
+ expect(declaration.mixinKeyword, isNotNull);
+ expect(declaration.leftBracket, isNotNull);
+ expect(declaration.name.name, 'A');
+ expect(declaration.members, hasLength(0));
+ expect(declaration.rightBracket, isNotNull);
+ expect(declaration.typeParameters, isNull);
+ }
+
+ void test_parseMixinDeclaration_implements2() {
+ createParser('mixin A implements B<T>, C {}');
+ _parserProxy.fastaParser.isMixinSupportEnabled = true;
+ MixinDeclaration declaration = parseFullCompilationUnitMember();
+ expect(declaration, isNotNull);
+ assertNoErrors();
+ expect(declaration.metadata, isEmpty);
+ expect(declaration.documentationComment, isNull);
+ expect(declaration.onClause, isNull);
+ ImplementsClause implementsClause = declaration.implementsClause;
+ expect(implementsClause.implementsKeyword, isNotNull);
+ NodeList<TypeName> interfaces = implementsClause.interfaces;
+ expect(interfaces, hasLength(2));
+ expect(interfaces[0].name.name, 'B');
+ expect(interfaces[0].typeArguments.arguments, hasLength(1));
+ expect(interfaces[1].name.name, 'C');
+ expect(interfaces[1].typeArguments, isNull);
+ expect(declaration.mixinKeyword, isNotNull);
+ expect(declaration.leftBracket, isNotNull);
+ expect(declaration.name.name, 'A');
+ expect(declaration.members, hasLength(0));
+ expect(declaration.rightBracket, isNotNull);
+ expect(declaration.typeParameters, isNull);
+ }
+
+ void test_parseMixinDeclaration_metadata() {
+ createParser('@Z mixin A {}');
+ _parserProxy.fastaParser.isMixinSupportEnabled = true;
+ MixinDeclaration declaration = parseFullCompilationUnitMember();
+ expect(declaration, isNotNull);
+ assertNoErrors();
+ NodeList<Annotation> metadata = declaration.metadata;
+ expect(metadata, hasLength(1));
+ expect(metadata[0].name.name, 'Z');
+ expect(declaration.documentationComment, isNull);
+ expect(declaration.onClause, isNull);
+ expect(declaration.implementsClause, isNull);
+ expect(declaration.mixinKeyword, isNotNull);
+ expect(declaration.leftBracket, isNotNull);
+ expect(declaration.name.name, 'A');
+ expect(declaration.members, hasLength(0));
+ expect(declaration.rightBracket, isNotNull);
+ expect(declaration.typeParameters, isNull);
+ }
+
+ void test_parseMixinDeclaration_on() {
+ createParser('mixin A on B {}');
+ _parserProxy.fastaParser.isMixinSupportEnabled = true;
+ MixinDeclaration declaration = parseFullCompilationUnitMember();
+ expect(declaration, isNotNull);
+ assertNoErrors();
+ expect(declaration.metadata, isEmpty);
+ expect(declaration.documentationComment, isNull);
+ OnClause onClause = declaration.onClause;
+ expect(onClause.onKeyword, isNotNull);
+ NodeList<TypeName> constraints = onClause.superclassConstraints;
+ expect(constraints, hasLength(1));
+ expect(constraints[0].name.name, 'B');
+ expect(constraints[0].typeArguments, isNull);
+ expect(declaration.implementsClause, isNull);
+ expect(declaration.mixinKeyword, isNotNull);
+ expect(declaration.leftBracket, isNotNull);
+ expect(declaration.name.name, 'A');
+ expect(declaration.members, hasLength(0));
+ expect(declaration.rightBracket, isNotNull);
+ expect(declaration.typeParameters, isNull);
+ }
+
+ void test_parseMixinDeclaration_on2() {
+ createParser('mixin A on B, C<T> {}');
+ _parserProxy.fastaParser.isMixinSupportEnabled = true;
+ MixinDeclaration declaration = parseFullCompilationUnitMember();
+ expect(declaration, isNotNull);
+ assertNoErrors();
+ expect(declaration.metadata, isEmpty);
+ expect(declaration.documentationComment, isNull);
+ OnClause onClause = declaration.onClause;
+ expect(onClause.onKeyword, isNotNull);
+ NodeList<TypeName> constraints = onClause.superclassConstraints;
+ expect(constraints, hasLength(2));
+ expect(constraints[0].name.name, 'B');
+ expect(constraints[0].typeArguments, isNull);
+ expect(constraints[1].name.name, 'C');
+ expect(constraints[1].typeArguments.arguments, hasLength(1));
+ expect(declaration.implementsClause, isNull);
+ expect(declaration.mixinKeyword, isNotNull);
+ expect(declaration.leftBracket, isNotNull);
+ expect(declaration.name.name, 'A');
+ expect(declaration.members, hasLength(0));
+ expect(declaration.rightBracket, isNotNull);
+ expect(declaration.typeParameters, isNull);
+ }
+
+ void test_parseMixinDeclaration_onAndImplements() {
+ createParser('mixin A on B implements C {}');
+ _parserProxy.fastaParser.isMixinSupportEnabled = true;
+ MixinDeclaration declaration = parseFullCompilationUnitMember();
+ expect(declaration, isNotNull);
+ assertNoErrors();
+ expect(declaration.metadata, isEmpty);
+ expect(declaration.documentationComment, isNull);
+ OnClause onClause = declaration.onClause;
+ expect(onClause.onKeyword, isNotNull);
+ NodeList<TypeName> constraints = onClause.superclassConstraints;
+ expect(constraints, hasLength(1));
+ expect(constraints[0].name.name, 'B');
+ expect(constraints[0].typeArguments, isNull);
+ ImplementsClause implementsClause = declaration.implementsClause;
+ expect(implementsClause.implementsKeyword, isNotNull);
+ NodeList<TypeName> interfaces = implementsClause.interfaces;
+ expect(interfaces, hasLength(1));
+ expect(interfaces[0].name.name, 'C');
+ expect(interfaces[0].typeArguments, isNull);
+ expect(declaration.mixinKeyword, isNotNull);
+ expect(declaration.leftBracket, isNotNull);
+ expect(declaration.name.name, 'A');
+ expect(declaration.members, hasLength(0));
+ expect(declaration.rightBracket, isNotNull);
+ expect(declaration.typeParameters, isNull);
+ }
+
+ void test_parseMixinDeclaration_simple() {
+ createParser('''
+mixin A {
+ int f;
+ int get g => f;
+ set s(int v) {f = v;}
+ int add(int v) => f = f + v;
+}''');
+ _parserProxy.fastaParser.isMixinSupportEnabled = true;
+ MixinDeclaration declaration = parseFullCompilationUnitMember();
+ expect(declaration, isNotNull);
+ assertNoErrors();
+ expect(declaration.metadata, isEmpty);
+ expect(declaration.documentationComment, isNull);
+ expect(declaration.onClause, isNull);
+ expect(declaration.implementsClause, isNull);
+ expect(declaration.mixinKeyword, isNotNull);
+ expect(declaration.leftBracket, isNotNull);
+ expect(declaration.name.name, 'A');
+ expect(declaration.members, hasLength(4));
+ expect(declaration.rightBracket, isNotNull);
+ expect(declaration.typeParameters, isNull);
+ }
+
+ void test_parseMixinDeclaration_withDocumentationComment() {
+ createParser('/// Doc\nmixin M {}');
+ _parserProxy.fastaParser.isMixinSupportEnabled = true;
+ MixinDeclaration declaration = parseFullCompilationUnitMember();
+ expectCommentText(declaration.documentationComment, '/// Doc');
+ }
}
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 8a3a172..1a32e5f 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -13555,16 +13555,6 @@
expect(declaration.metadata, hasLength(2));
}
- void test_parseCommentAndMetadata_mm() {
- createParser('@A @B(x) class C {}');
- CompilationUnit unit = parser.parseCompilationUnit2();
- expectNotNullIfNoErrors(unit);
- assertNoErrors();
- ClassDeclaration declaration = unit.declarations[0];
- expect(declaration.documentationComment, isNull);
- expect(declaration.metadata, hasLength(2));
- }
-
void test_parseCommentAndMetadata_mix1() {
createParser(r'''
/**
@@ -13662,6 +13652,16 @@
expect(tokens[0].lexeme, contains('aaa'));
}
+ void test_parseCommentAndMetadata_mm() {
+ createParser('@A @B(x) class C {}');
+ CompilationUnit unit = parser.parseCompilationUnit2();
+ expectNotNullIfNoErrors(unit);
+ assertNoErrors();
+ ClassDeclaration declaration = unit.declarations[0];
+ expect(declaration.documentationComment, isNull);
+ expect(declaration.metadata, hasLength(2));
+ }
+
void test_parseCommentAndMetadata_none() {
createParser('class C {}');
CompilationUnit unit = parser.parseCompilationUnit2();
@@ -13686,75 +13686,6 @@
expect(declaration.metadata, isEmpty);
}
- void test_parseCommentReferences_33738() {
- CompilationUnit unit =
- parseCompilationUnit('/** [String] */ abstract class Foo {}');
- ClassDeclaration clazz = unit.declarations[0];
- Comment comment = clazz.documentationComment;
- expect(clazz.isAbstract, isTrue);
- List<CommentReference> references = comment.references;
- expect(references, hasLength(1));
- CommentReference reference = references[0];
- expect(reference, isNotNull);
- expect(reference.identifier, isNotNull);
- expect(reference.offset, 5);
- }
-
- void test_parseCommentReferences_beforeAnnotation() {
- CompilationUnit unit = parseCompilationUnit('''
-/// See [int] and [String]
-/// and [Object].
-@Annotation
-abstract class Foo {}
-''');
- ClassDeclaration clazz = unit.declarations[0];
- Comment comment = clazz.documentationComment;
- expect(clazz.isAbstract, isTrue);
- List<CommentReference> references = comment.references;
- expect(references, hasLength(3));
-
- expectReference(int index, String expectedText, int expectedOffset) {
- CommentReference reference = references[index];
- expect(reference.identifier.name, expectedText);
- expect(reference.offset, expectedOffset);
- }
-
- expectReference(0, 'int', 9);
- expectReference(1, 'String', 19);
- expectReference(2, 'Object', 36);
- }
-
- void test_parseCommentReferences_complex() {
- CompilationUnit unit = parseCompilationUnit('''
-/// This dartdoc comment [should] be ignored
-@Annotation
-/// This dartdoc comment is [included].
-// a non dartdoc comment [inbetween]
-/// See [int] and [String] but `not [a]`
-/// ```
-/// This [code] block should be ignored
-/// ```
-/// and [Object].
-abstract class Foo {}
-''');
- ClassDeclaration clazz = unit.declarations[0];
- Comment comment = clazz.documentationComment;
- expect(clazz.isAbstract, isTrue);
- List<CommentReference> references = comment.references;
- expect(references, hasLength(4));
-
- expectReference(int index, String expectedText, int expectedOffset) {
- CommentReference reference = references[index];
- expect(reference.identifier.name, expectedText);
- expect(reference.offset, expectedOffset);
- }
-
- expectReference(0, 'included', 86);
- expectReference(1, 'int', 143);
- expectReference(2, 'String', 153);
- expectReference(3, 'Object', 240);
- }
-
void test_parseCommentReference_new_prefixed() {
createParser('');
CommentReference reference = parseCommentReference('new a.b', 7);
@@ -13910,6 +13841,75 @@
expect(identifier.offset, 5);
}
+ void test_parseCommentReferences_33738() {
+ CompilationUnit unit =
+ parseCompilationUnit('/** [String] */ abstract class Foo {}');
+ ClassDeclaration clazz = unit.declarations[0];
+ Comment comment = clazz.documentationComment;
+ expect(clazz.isAbstract, isTrue);
+ List<CommentReference> references = comment.references;
+ expect(references, hasLength(1));
+ CommentReference reference = references[0];
+ expect(reference, isNotNull);
+ expect(reference.identifier, isNotNull);
+ expect(reference.offset, 5);
+ }
+
+ void test_parseCommentReferences_beforeAnnotation() {
+ CompilationUnit unit = parseCompilationUnit('''
+/// See [int] and [String]
+/// and [Object].
+@Annotation
+abstract class Foo {}
+''');
+ ClassDeclaration clazz = unit.declarations[0];
+ Comment comment = clazz.documentationComment;
+ expect(clazz.isAbstract, isTrue);
+ List<CommentReference> references = comment.references;
+ expect(references, hasLength(3));
+
+ expectReference(int index, String expectedText, int expectedOffset) {
+ CommentReference reference = references[index];
+ expect(reference.identifier.name, expectedText);
+ expect(reference.offset, expectedOffset);
+ }
+
+ expectReference(0, 'int', 9);
+ expectReference(1, 'String', 19);
+ expectReference(2, 'Object', 36);
+ }
+
+ void test_parseCommentReferences_complex() {
+ CompilationUnit unit = parseCompilationUnit('''
+/// This dartdoc comment [should] be ignored
+@Annotation
+/// This dartdoc comment is [included].
+// a non dartdoc comment [inbetween]
+/// See [int] and [String] but `not [a]`
+/// ```
+/// This [code] block should be ignored
+/// ```
+/// and [Object].
+abstract class Foo {}
+''');
+ ClassDeclaration clazz = unit.declarations[0];
+ Comment comment = clazz.documentationComment;
+ expect(clazz.isAbstract, isTrue);
+ List<CommentReference> references = comment.references;
+ expect(references, hasLength(4));
+
+ expectReference(int index, String expectedText, int expectedOffset) {
+ CommentReference reference = references[index];
+ expect(reference.identifier.name, expectedText);
+ expect(reference.offset, expectedOffset);
+ }
+
+ expectReference(0, 'included', 86);
+ expectReference(1, 'int', 143);
+ expectReference(2, 'String', 153);
+ expectReference(3, 'Object', 240);
+ }
+
void test_parseCommentReferences_multiLine() {
DocumentationCommentToken token = new DocumentationCommentToken(
TokenType.MULTI_LINE_COMMENT, "/** xxx [a] yyy [bb] zzz */", 3);
@@ -14136,10 +14136,17 @@
expect(reference.offset, 27);
}
- void test_parseCommentReferences_skipLinkDefinition() {
+ void test_parseCommentReferences_skipLink_direct_multiLine() {
List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
- new DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
- "/** [a]: http://www.google.com (Google) [b] zzz */", 3)
+ new DocumentationCommentToken(
+ TokenType.MULTI_LINE_COMMENT,
+ '''
+/**
+ * [a link split across multiple
+ * lines](http://www.google.com) [b] zzz
+ */
+''',
+ 3)
];
createParser('');
List<CommentReference> references = parser.parseCommentReferences(tokens);
@@ -14149,10 +14156,10 @@
CommentReference reference = references[0];
expect(reference, isNotNull);
expect(reference.identifier, isNotNull);
- expect(reference.offset, 44);
+ expect(reference.offset, 74);
}
- void test_parseCommentReferences_skipLinked() {
+ void test_parseCommentReferences_skipLink_direct_singleLine() {
List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
new DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
"/** [a](http://www.google.com) [b] zzz */", 3)
@@ -14168,7 +14175,30 @@
expect(reference.offset, 35);
}
- void test_parseCommentReferences_skipReferenceLink() {
+ void test_parseCommentReferences_skipLink_reference_multiLine() {
+ List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+ new DocumentationCommentToken(
+ TokenType.MULTI_LINE_COMMENT,
+ '''
+/**
+ * [a link split across multiple
+ * lines][c] [b] zzz
+ */
+''',
+ 3)
+ ];
+ createParser('');
+ List<CommentReference> references = parser.parseCommentReferences(tokens);
+ expectNotNullIfNoErrors(references);
+ assertNoErrors();
+ expect(references, hasLength(1));
+ CommentReference reference = references[0];
+ expect(reference, isNotNull);
+ expect(reference.identifier, isNotNull);
+ expect(reference.offset, 54);
+ }
+
+ void test_parseCommentReferences_skipLink_reference_singleLine() {
List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
new DocumentationCommentToken(
TokenType.MULTI_LINE_COMMENT, "/** [a][c] [b] zzz */", 3)
@@ -14184,6 +14214,22 @@
expect(reference.offset, 15);
}
+ void test_parseCommentReferences_skipLinkDefinition() {
+ List<DocumentationCommentToken> tokens = <DocumentationCommentToken>[
+ new DocumentationCommentToken(TokenType.MULTI_LINE_COMMENT,
+ "/** [a]: http://www.google.com (Google) [b] zzz */", 3)
+ ];
+ createParser('');
+ List<CommentReference> references = parser.parseCommentReferences(tokens);
+ expectNotNullIfNoErrors(references);
+ assertNoErrors();
+ expect(references, hasLength(1));
+ CommentReference reference = references[0];
+ expect(reference, isNotNull);
+ expect(reference.identifier, isNotNull);
+ expect(reference.offset, 44);
+ }
+
void test_parseConfiguration_noOperator_dottedIdentifier() {
createParser("if (a.b) 'c.dart'");
Configuration configuration = parser.parseConfiguration();
@@ -18100,24 +18146,6 @@
expect(alias.semicolon, isNotNull);
}
- void test_parseGenericTypeAlias_typeParameters_extends_gtGtEq() {
- // The scanner creates a single token for `>>=`
- // then the parser must split it into three separate tokens.
- createParser('typedef F<A,B,C extends D<E>>=Function(A a, B b, C c);');
- GenericTypeAlias alias = parseFullCompilationUnitMember();
- expect(alias, isNotNull);
- assertNoErrors();
- expect(alias.name, isNotNull);
- expect(alias.name.name, 'F');
- expect(alias.typeParameters.typeParameters, hasLength(3));
- TypeParameter typeParam = alias.typeParameters.typeParameters[2];
- NamedType type = typeParam.bound;
- expect(type.typeArguments.arguments, hasLength(1));
- expect(alias.equals, isNotNull);
- expect(alias.functionType, isNotNull);
- expect(alias.semicolon, isNotNull);
- }
-
void test_parseGenericTypeAlias_typeParameters_extends3() {
createParser(
'typedef F<A,B,C extends D<E,G,H>> = Function(A a, B b, C c);');
@@ -18153,6 +18181,24 @@
expect(alias.semicolon, isNotNull);
}
+ void test_parseGenericTypeAlias_typeParameters_extends_gtGtEq() {
+ // The scanner creates a single token for `>>=`
+ // then the parser must split it into three separate tokens.
+ createParser('typedef F<A,B,C extends D<E>>=Function(A a, B b, C c);');
+ GenericTypeAlias alias = parseFullCompilationUnitMember();
+ expect(alias, isNotNull);
+ assertNoErrors();
+ expect(alias.name, isNotNull);
+ expect(alias.name.name, 'F');
+ expect(alias.typeParameters.typeParameters, hasLength(3));
+ TypeParameter typeParam = alias.typeParameters.typeParameters[2];
+ NamedType type = typeParam.bound;
+ expect(type.typeArguments.arguments, hasLength(1));
+ expect(alias.equals, isNotNull);
+ expect(alias.functionType, isNotNull);
+ expect(alias.semicolon, isNotNull);
+ }
+
void test_parseImportDirective_configuration_multiple() {
createParser("import 'lib/lib.dart' if (a) 'b.dart' if (c) 'd.dart';");
ImportDirective directive = parseFullDirective();
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index e8b7f00..1898824 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -591,7 +591,7 @@
Source definingCompilationUnitSource = createNamedSource(fileName);
List<CompilationUnitElement> sourcedCompilationUnits;
if (typeNames == null) {
- sourcedCompilationUnits = CompilationUnitElement.EMPTY_LIST;
+ sourcedCompilationUnits = const <CompilationUnitElement>[];
} else {
int count = typeNames.length;
sourcedCompilationUnits = new List<CompilationUnitElement>(count);
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_kernel_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_kernel_test.dart
index 1434544..95b7019 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_kernel_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_kernel_test.dart
@@ -294,6 +294,12 @@
@override
@failingTest
+ test_wrongNumberOfTypeArguments_typeParameter() async {
+ await super.test_wrongNumberOfTypeArguments_typeParameter();
+ }
+
+ @override
+ @failingTest
test_yield_async_to_basic_type() async {
await super.test_yield_async_to_basic_type();
}
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index af2af48..21a69fe 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -2170,6 +2170,18 @@
]);
}
+ test_wrongNumberOfTypeArguments_class_tooFew() async {
+ await assertErrorsInCode(r'''
+class A<E, F> {}
+A<A> a = null;''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+ }
+
+ test_wrongNumberOfTypeArguments_class_tooMany() async {
+ await assertErrorsInCode(r'''
+class A<E> {}
+A<A, A> a = null;''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+ }
+
test_wrongNumberOfTypeArguments_classAlias() async {
await assertErrorsInCode(r'''
class A {}
@@ -2178,16 +2190,18 @@
[StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
}
- test_wrongNumberOfTypeArguments_tooFew() async {
+ test_wrongNumberOfTypeArguments_dynamic() async {
await assertErrorsInCode(r'''
-class A<E, F> {}
-A<A> a = null;''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+dynamic<int> v;
+''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
}
- test_wrongNumberOfTypeArguments_tooMany() async {
+ test_wrongNumberOfTypeArguments_typeParameter() async {
await assertErrorsInCode(r'''
-class A<E> {}
-A<A, A> a = null;''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
+class C<T> {
+ T<int> f;
+}
+''', [StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS]);
}
test_wrongNumberOfTypeArguments_typeTest_tooFew() async {
diff --git a/pkg/analyzer/test/src/context/cache_test.dart b/pkg/analyzer/test/src/context/cache_test.dart
index 279aef0..fbd0736 100644
--- a/pkg/analyzer/test/src/context/cache_test.dart
+++ b/pkg/analyzer/test/src/context/cache_test.dart
@@ -60,8 +60,8 @@
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
// put values
- entry.setValue(resultA, 'a', TargetedResult.EMPTY_LIST);
- entry.setValue(resultB, 'b', TargetedResult.EMPTY_LIST);
+ entry.setValue(resultA, 'a', const <TargetedResult>[]);
+ entry.setValue(resultB, 'b', const <TargetedResult>[]);
expect(cache.getState(target, resultA), CacheState.VALID);
expect(cache.getState(target, resultB), CacheState.VALID);
expect(cache.getValue(target, resultA), 'a');
@@ -184,7 +184,7 @@
ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
// set results, all of them are VALID
- entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+ entry1.setValue(result1, 111, const <TargetedResult>[]);
entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
entry3.setValue(result3, 333, []);
expect(entry1.getState(result1), CacheState.VALID);
@@ -208,7 +208,7 @@
ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
// set results, all of them are VALID
- entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+ entry.setValue(result1, 111, const <TargetedResult>[]);
entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
expect(entry.getState(result1), CacheState.VALID);
expect(entry.getState(result2), CacheState.VALID);
@@ -268,7 +268,7 @@
CacheEntry entry2 = new CacheEntry(target2);
cache.put(entry1);
cache.put(entry2);
- entry1.setValue(descriptor1, 1, TargetedResult.EMPTY_LIST);
+ entry1.setValue(descriptor1, 1, const <TargetedResult>[]);
entry2.setValue(descriptor2, 2, <TargetedResult>[result1]);
// target2 is listed as dependent in target1
expect(
@@ -307,7 +307,7 @@
CaughtException exception = new CaughtException(null, null);
entry.setErrorState(exception, <ResultDescriptor>[result]);
// set the same result to VALID
- entry.setValue(result, 1, TargetedResult.EMPTY_LIST);
+ entry.setValue(result, 1, const <TargetedResult>[]);
// fix the exception state
entry.fixExceptionState();
expect(entry.exception, isNull);
@@ -329,8 +329,8 @@
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
// put values
- entry.setValue(resultA, 'a', TargetedResult.EMPTY_LIST);
- entry.setValue(resultB, 'b', TargetedResult.EMPTY_LIST);
+ entry.setValue(resultA, 'a', const <TargetedResult>[]);
+ entry.setValue(resultB, 'b', const <TargetedResult>[]);
expect(entry.getState(resultA), CacheState.VALID);
expect(entry.getState(resultB), CacheState.VALID);
expect(entry.getValue(resultA), 'a');
@@ -373,18 +373,18 @@
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
{
- entry.setValue(descriptor1, 1, TargetedResult.EMPTY_LIST);
+ entry.setValue(descriptor1, 1, const <TargetedResult>[]);
expect(entry.getState(descriptor1), CacheState.VALID);
}
{
- entry.setValue(descriptor2, 2, TargetedResult.EMPTY_LIST);
+ entry.setValue(descriptor2, 2, const <TargetedResult>[]);
expect(entry.getState(descriptor1), CacheState.VALID);
expect(entry.getState(descriptor2), CacheState.VALID);
}
// get descriptor1, so that descriptor2 will be flushed
entry.getValue(descriptor1);
{
- entry.setValue(descriptor3, 3, TargetedResult.EMPTY_LIST);
+ entry.setValue(descriptor3, 3, const <TargetedResult>[]);
expect(entry.getState(descriptor1), CacheState.VALID);
expect(entry.getState(descriptor2), CacheState.FLUSHED);
expect(entry.getState(descriptor3), CacheState.VALID);
@@ -413,7 +413,7 @@
new ResultDescriptor<String>('test', null);
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
- entry.setValue(result, 'value', TargetedResult.EMPTY_LIST);
+ entry.setValue(result, 'value', const <TargetedResult>[]);
entry.invalidateAllInformation();
expect(entry.getState(result), CacheState.INVALID);
expect(entry.getValue(result), isNull);
@@ -427,9 +427,9 @@
// prepare some good state
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
- entry.setValue(result1, 10, TargetedResult.EMPTY_LIST);
- entry.setValue(result2, 20, TargetedResult.EMPTY_LIST);
- entry.setValue(result3, 30, TargetedResult.EMPTY_LIST);
+ entry.setValue(result1, 10, const <TargetedResult>[]);
+ entry.setValue(result2, 20, const <TargetedResult>[]);
+ entry.setValue(result3, 30, const <TargetedResult>[]);
// set error state
CaughtException exception = new CaughtException(null, null);
entry.setErrorState(exception, <ResultDescriptor>[result1, result2]);
@@ -455,7 +455,7 @@
ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
ResultDescriptor<int> result4 = new ResultDescriptor<int>('result4', -4);
// set results, all of them are VALID
- entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+ entry1.setValue(result1, 111, const <TargetedResult>[]);
entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
entry2.setValue(result3, 333, [new TargetedResult(target2, result2)]);
entry2.setValue(result4, 444, []);
@@ -515,7 +515,7 @@
ResultDescriptor<int> result = new ResultDescriptor<int>('test', null);
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
- entry.setValue(result, 42, TargetedResult.EMPTY_LIST);
+ entry.setValue(result, 42, const <TargetedResult>[]);
// an invalid state change
expect(() {
entry.setState(result, CacheState.ERROR);
@@ -531,7 +531,7 @@
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
// set VALID
- entry.setValue(result, 10, TargetedResult.EMPTY_LIST);
+ entry.setValue(result, 10, const <TargetedResult>[]);
expect(entry.getState(result), CacheState.VALID);
expect(entry.getValue(result), 10);
// set FLUSHED
@@ -546,7 +546,7 @@
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
// set VALID
- entry.setValue(result, 10, TargetedResult.EMPTY_LIST);
+ entry.setValue(result, 10, const <TargetedResult>[]);
expect(entry.getState(result), CacheState.VALID);
expect(entry.getValue(result), 10);
// set IN_PROCESS
@@ -561,7 +561,7 @@
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
// set VALID
- entry.setValue(result, 10, TargetedResult.EMPTY_LIST);
+ entry.setValue(result, 10, const <TargetedResult>[]);
expect(entry.getState(result), CacheState.VALID);
expect(entry.getValue(result), 10);
// listen, expect "result" invalidation event
@@ -620,7 +620,7 @@
ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
ResultDescriptor<int> result4 = new ResultDescriptor<int>('result4', -4);
// set results, all of them are VALID
- entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+ entry.setValue(result1, 111, const <TargetedResult>[]);
entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
entry.setValue(result3, 333, [new TargetedResult(target, result2)]);
entry.setValue(result4, 444, []);
@@ -653,7 +653,7 @@
cache.put(entry);
ResultDescriptor<int> result = new ResultDescriptor<int>('result1', -1);
// set results, all of them are VALID
- entry.setValue(result, 111, TargetedResult.EMPTY_LIST);
+ entry.setValue(result, 111, const <TargetedResult>[]);
expect(entry.getState(result), CacheState.VALID);
expect(entry.getValue(result), 111);
// invalidate result, keep entry
@@ -672,7 +672,7 @@
ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
// set results, all of them are VALID
- entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+ entry1.setValue(result1, 111, const <TargetedResult>[]);
entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
entry2.setValue(result3, 333, [new TargetedResult(target2, result2)]);
expect(entry1.getState(result1), CacheState.VALID);
@@ -695,7 +695,7 @@
ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
// set results, all of them are VALID
- entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+ entry.setValue(result1, 111, const <TargetedResult>[]);
entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
entry.setValue(result3, 333, [new TargetedResult(target, result2)]);
expect(entry.getState(result1), CacheState.VALID);
@@ -743,7 +743,7 @@
String value = 'value';
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
- entry.setValue(result, value, TargetedResult.EMPTY_LIST);
+ entry.setValue(result, value, const <TargetedResult>[]);
expect(entry.getState(result), CacheState.VALID);
expect(entry.getValue(result), value);
}
@@ -763,16 +763,16 @@
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
{
- entry.setValue(descriptor1, 1, TargetedResult.EMPTY_LIST);
+ entry.setValue(descriptor1, 1, const <TargetedResult>[]);
expect(entry.getState(descriptor1), CacheState.VALID);
}
{
- entry.setValue(descriptor2, 2, TargetedResult.EMPTY_LIST);
+ entry.setValue(descriptor2, 2, const <TargetedResult>[]);
expect(entry.getState(descriptor1), CacheState.VALID);
expect(entry.getState(descriptor2), CacheState.VALID);
}
{
- entry.setValue(descriptor3, 3, TargetedResult.EMPTY_LIST);
+ entry.setValue(descriptor3, 3, const <TargetedResult>[]);
expect(entry.getState(descriptor1), CacheState.FLUSHED);
expect(entry.getState(descriptor2), CacheState.VALID);
expect(entry.getState(descriptor3), CacheState.VALID);
@@ -803,14 +803,14 @@
cache.put(entry3);
// Set two results.
- entry1.setValue(descriptor1, 1, TargetedResult.EMPTY_LIST);
- entry2.setValue(descriptor2, 2, TargetedResult.EMPTY_LIST);
+ entry1.setValue(descriptor1, 1, const <TargetedResult>[]);
+ entry2.setValue(descriptor2, 2, const <TargetedResult>[]);
expect(entry1.getState(descriptor1), CacheState.VALID);
expect(entry2.getState(descriptor2), CacheState.VALID);
// Make source1 priority, so result2 is flushed instead.
context.prioritySources = <Source>[source1];
- entry3.setValue(descriptor3, 3, TargetedResult.EMPTY_LIST);
+ entry3.setValue(descriptor3, 3, const <TargetedResult>[]);
expect(entry1.getState(descriptor1), CacheState.VALID);
expect(entry2.getState(descriptor2), CacheState.FLUSHED);
expect(entry3.getState(descriptor3), CacheState.VALID);
@@ -823,14 +823,14 @@
ResultDescriptor<int> result1 = new ResultDescriptor<int>('result1', -1);
ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
// set results, all of them are VALID
- entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+ entry.setValue(result1, 111, const <TargetedResult>[]);
entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
expect(entry.getState(result1), CacheState.VALID);
expect(entry.getState(result2), CacheState.VALID);
expect(entry.getValue(result1), 111);
expect(entry.getValue(result2), 222);
// set result1; result2 is intact
- entry.setValue(result1, 1111, TargetedResult.EMPTY_LIST);
+ entry.setValue(result1, 1111, const <TargetedResult>[]);
expect(entry.getState(result1), CacheState.VALID);
expect(entry.getState(result2), CacheState.VALID);
expect(entry.getValue(result1), 1111);
@@ -848,7 +848,7 @@
ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
// set results, all of them are VALID
entry2.setValue(result2, 222, [new TargetedResult(target1, result1)]);
- entry1.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+ entry1.setValue(result1, 111, const <TargetedResult>[]);
expect(entry1.getState(result1), CacheState.VALID);
expect(entry2.getState(result2), CacheState.VALID);
expect(entry1.getValue(result1), 111);
@@ -867,7 +867,7 @@
ResultDescriptor<int> result2 = new ResultDescriptor<int>('result2', -2);
ResultDescriptor<int> result3 = new ResultDescriptor<int>('result3', -3);
// set results, all of them are VALID
- entry.setValue(result1, 111, TargetedResult.EMPTY_LIST);
+ entry.setValue(result1, 111, const <TargetedResult>[]);
entry.setValue(result2, 222, [new TargetedResult(target, result1)]);
entry.setValue(result3, 333, [new TargetedResult(target, result2)]);
expect(entry.getState(result1), CacheState.VALID);
@@ -901,7 +901,7 @@
ResultDescriptor<int> result = new ResultDescriptor<int>('test', null);
CacheEntry entry = new CacheEntry(target);
cache.put(entry);
- entry.setValue(result, 42, TargetedResult.EMPTY_LIST);
+ entry.setValue(result, 42, const <TargetedResult>[]);
expect(entry.toString(), isNotNull);
}
}
@@ -1266,7 +1266,7 @@
CacheEntry entry2 = new CacheEntry(target2);
partition1.put(entry1);
partition2.put(entry2);
- entry1.setValue(descriptor1, 1, TargetedResult.EMPTY_LIST);
+ entry1.setValue(descriptor1, 1, const <TargetedResult>[]);
entry2.setValue(descriptor2, 2, <TargetedResult>[result1]);
// target2 is listed as dependent in target1
expect(
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart
index 5b6ae42..1a18218 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart
@@ -19,13 +19,6 @@
@override
@failingTest
- @FastaProblem('https://github.com/dart-lang/sdk/issues/33795')
- test_annotation_onDirective_partOf() async {
- await super.test_annotation_onDirective_partOf();
- }
-
- @override
- @failingTest
test_generic_function_type() async {
await super.test_generic_function_type();
}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 390a0ca..8624cb8 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -956,6 +956,102 @@
assertElement(zRef, findElement.parameter('z'));
}
+ test_assign_to_postfix_increment() async {
+ addTestFile('''
+void f(num x, int y) {
+ x++ = y;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x++');
+ assertType(xRef, 'num');
+ assertElement(xRef, findElement.parameter('x'));
+ var yRef = findNode.simple('y;');
+ assertType(yRef, 'int');
+ assertElement(yRef, findElement.parameter('y'));
+ }
+
+ test_assign_to_postfix_increment_compound() async {
+ addTestFile('''
+void f(num x, int y) {
+ x++ += y;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x++');
+ assertType(xRef, 'num');
+ assertElement(xRef, findElement.parameter('x'));
+ var yRef = findNode.simple('y;');
+ assertType(yRef, 'int');
+ assertElement(yRef, findElement.parameter('y'));
+ }
+
+ test_assign_to_postfix_increment_null_aware() async {
+ addTestFile('''
+void f(num x, int y) {
+ x++ ??= y;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x++');
+ assertType(xRef, 'num');
+ assertElement(xRef, findElement.parameter('x'));
+ var yRef = findNode.simple('y;');
+ assertType(yRef, 'int');
+ assertElement(yRef, findElement.parameter('y'));
+ }
+
+ test_assign_to_prefix_increment() async {
+ addTestFile('''
+void f(num x, int y) {
+ ++x = y;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x =');
+ assertType(xRef, 'num');
+ assertElement(xRef, findElement.parameter('x'));
+ var yRef = findNode.simple('y;');
+ assertType(yRef, 'int');
+ assertElement(yRef, findElement.parameter('y'));
+ }
+
+ test_assign_to_prefix_increment_compound() async {
+ addTestFile('''
+void f(num x, int y) {
+ ++x += y;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x +=');
+ assertType(xRef, 'num');
+ assertElement(xRef, findElement.parameter('x'));
+ var yRef = findNode.simple('y;');
+ assertType(yRef, 'int');
+ assertElement(yRef, findElement.parameter('y'));
+ }
+
+ test_assign_to_prefix_increment_null_aware() async {
+ addTestFile('''
+void f(num x, int y) {
+ ++x ??= y;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x ??=');
+ assertType(xRef, 'num');
+ assertElement(xRef, findElement.parameter('x'));
+ var yRef = findNode.simple('y;');
+ assertType(yRef, 'int');
+ assertElement(yRef, findElement.parameter('y'));
+ }
+
test_assign_with_synthetic_lhs() async {
addTestFile('''
void f(int x) {
@@ -969,6 +1065,21 @@
assertElement(xRef, findElement.parameter('x'));
}
+ test_assign_with_synthetic_lhs_in_method() async {
+ addTestFile('''
+class C {
+ void f(int x) {
+ = x;
+ }
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x;');
+ assertType(xRef, 'int');
+ assertElement(xRef, findElement.parameter('x'));
+ }
+
test_assignment_to_final_parameter() async {
addTestFile('''
f(final int x) {
@@ -2486,7 +2597,6 @@
main() {
a.loadLibrary();
}
-
''');
await resolveTestFile();
var import = findElement.import('package:test/a.dart');
@@ -2514,7 +2624,6 @@
main() {
a.loadLibrary(b, c);
}
-
''');
await resolveTestFile();
var import = findElement.import('package:test/a.dart');
@@ -2548,7 +2657,6 @@
main() {
a.loadLibrary;
}
-
''');
await resolveTestFile();
var import = findElement.import('package:test/a.dart');
@@ -2574,7 +2682,6 @@
a.v;
a.v = 1;
}
-
''');
await resolveTestFile();
var import = findElement.import('package:test/a.dart');
@@ -2607,6 +2714,153 @@
}
}
+ test_directive_export() async {
+ var a = _p('/test/lib/a.dart');
+ provider.newFile(a, r'''
+class MyClass {}
+int myVar;
+int get myGetter => 0;
+int set mySetter(_) {}
+''');
+ addTestFile(r'''
+export 'a.dart' show MyClass, myVar, myGetter, mySetter, Unresolved;
+''');
+ await resolveTestFile();
+ var export = findElement.export('package:test/a.dart');
+ var namespace = export.exportedLibrary.exportNamespace;
+
+ {
+ var ref = findNode.simple('MyClass');
+ assertElement(ref, namespace.get('MyClass'));
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('myVar');
+ PropertyAccessorElement getter = namespace.get('myVar');
+ assertElement(ref, getter.variable);
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('myGetter');
+ PropertyAccessorElement getter = namespace.get('myGetter');
+ assertElement(ref, getter.variable);
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('mySetter');
+ PropertyAccessorElement getter = namespace.get('mySetter=');
+ assertElement(ref, getter.variable);
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('Unresolved');
+ assertElementNull(ref);
+ assertType(ref, null);
+ }
+ }
+
+ test_directive_import_hide() async {
+ var a = _p('/test/lib/a.dart');
+ provider.newFile(a, r'''
+class MyClass {}
+int myVar;
+int get myGetter => 0;
+int set mySetter(_) {}
+''');
+ addTestFile(r'''
+import 'a.dart' hide MyClass, myVar, myGetter, mySetter, Unresolved;
+''');
+ await resolveTestFile();
+ var import = findElement.import('package:test/a.dart');
+ var namespace = import.importedLibrary.exportNamespace;
+
+ {
+ var ref = findNode.simple('MyClass');
+ assertElement(ref, namespace.get('MyClass'));
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('myVar');
+ PropertyAccessorElement getter = namespace.get('myVar');
+ assertElement(ref, getter.variable);
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('myGetter');
+ PropertyAccessorElement getter = namespace.get('myGetter');
+ assertElement(ref, getter.variable);
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('mySetter');
+ PropertyAccessorElement getter = namespace.get('mySetter=');
+ assertElement(ref, getter.variable);
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('Unresolved');
+ assertElementNull(ref);
+ assertType(ref, null);
+ }
+ }
+
+ test_directive_import_show() async {
+ var a = _p('/test/lib/a.dart');
+ provider.newFile(a, r'''
+class MyClass {}
+int myVar;
+int get myGetter => 0;
+int set mySetter(_) {}
+''');
+ addTestFile(r'''
+import 'a.dart' show MyClass, myVar, myGetter, mySetter, Unresolved;
+''');
+ await resolveTestFile();
+ var import = findElement.import('package:test/a.dart');
+ var namespace = import.importedLibrary.exportNamespace;
+
+ {
+ var ref = findNode.simple('MyClass');
+ assertElement(ref, namespace.get('MyClass'));
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('myVar');
+ PropertyAccessorElement getter = namespace.get('myVar');
+ assertElement(ref, getter.variable);
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('myGetter');
+ PropertyAccessorElement getter = namespace.get('myGetter');
+ assertElement(ref, getter.variable);
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('mySetter');
+ PropertyAccessorElement getter = namespace.get('mySetter=');
+ assertElement(ref, getter.variable);
+ assertType(ref, null);
+ }
+
+ {
+ var ref = findNode.simple('Unresolved');
+ assertElementNull(ref);
+ assertType(ref, null);
+ }
+ }
+
test_enum_toString() async {
addTestFile(r'''
enum MyEnum { A, B, C }
@@ -4387,6 +4641,21 @@
assertIdentifierTopGetRef(arg2.expression, 'c');
}
+ test_invalid_invocation_arguments_requiredAfterNamed() async {
+ addTestFile(r'''
+var a = 0;
+var b = 0;
+main() {
+ f(p: a, b);
+}
+void f({p}) {}
+''');
+ await resolveTestFile();
+ expect(result.errors, isNotEmpty);
+ assertTopGetRef('a, ', 'a');
+ assertTopGetRef('b);', 'b');
+ }
+
test_invalid_invocation_arguments_static_method() async {
addTestFile(r'''
class C {
@@ -7149,6 +7418,32 @@
expectedPrefix: myImport.prefix);
}
+ test_postfix_increment_of_non_generator() async {
+ addTestFile('''
+void f(int g()) {
+ g()++;
+}
+''');
+ await resolveTestFile();
+
+ var gRef = findNode.simple('g()++');
+ assertType(gRef, '() → int');
+ assertElement(gRef, findElement.parameter('g'));
+ }
+
+ test_postfix_increment_of_postfix_increment() async {
+ addTestFile('''
+void f(int x) {
+ x ++ ++;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x ++');
+ assertType(xRef, 'int');
+ assertElement(xRef, findElement.parameter('x'));
+ }
+
test_postfixExpression_local() async {
String content = r'''
main() {
@@ -7223,6 +7518,45 @@
}
}
+ test_prefix_increment_of_non_generator() async {
+ addTestFile('''
+void f(bool x) {
+ ++!x;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x;');
+ assertType(xRef, 'bool');
+ assertElement(xRef, findElement.parameter('x'));
+ }
+
+ test_prefix_increment_of_postfix_increment() async {
+ addTestFile('''
+void f(int x) {
+ ++x++;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x++');
+ assertType(xRef, 'int');
+ assertElement(xRef, findElement.parameter('x'));
+ }
+
+ test_prefix_increment_of_prefix_increment() async {
+ addTestFile('''
+void f(int x) {
+ ++ ++ x;
+}
+''');
+ await resolveTestFile();
+
+ var xRef = findNode.simple('x;');
+ assertType(xRef, 'int');
+ assertElement(xRef, findElement.parameter('x'));
+ }
+
test_prefixedIdentifier_classInstance_instanceField() async {
String content = r'''
main() {
@@ -10241,6 +10575,23 @@
fail('Not found class: $name');
}
+ ExportElement export(String targetUri) {
+ ExportElement exportElement;
+ for (var export in unitElement.library.exports) {
+ var exportedUri = export.exportedLibrary.source.uri.toString();
+ if (exportedUri == targetUri) {
+ if (exportElement != null) {
+ throw new StateError('Not unique $targetUri export.');
+ }
+ exportElement = export;
+ }
+ }
+ if (exportElement != null) {
+ return exportElement;
+ }
+ fail('Not found export: $targetUri');
+ }
+
FieldElement field(String name) {
for (var type in unitElement.types) {
for (var field in type.fields) {
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 7a7e093..53e073e 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -1994,11 +1994,6 @@
@failingTest
@override
- test_searchReferences_TopLevelVariableElement() =>
- super.test_searchReferences_TopLevelVariableElement();
-
- @failingTest
- @override
test_subtypes_partWithoutLibrary() =>
super.test_subtypes_partWithoutLibrary();
}
diff --git a/pkg/analyzer/test/src/dart/constant/utilities_test.dart b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
index 13a0ed1..3a195fb 100644
--- a/pkg/analyzer/test/src/dart/constant/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/utilities_test.dart
@@ -252,7 +252,7 @@
constructorDeclaration.element = constructorElement;
classElement.constructors = <ConstructorElement>[constructorElement];
} else {
- classElement.constructors = ConstructorElement.EMPTY_LIST;
+ classElement.constructors = const <ConstructorElement>[];
}
return variableDeclaration;
}
diff --git a/pkg/analyzer/test/src/dart/constant/value_test.dart b/pkg/analyzer/test/src/dart/constant/value_test.dart
index ccce9b5..3d02cda 100644
--- a/pkg/analyzer/test/src/dart/constant/value_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/value_test.dart
@@ -1942,12 +1942,12 @@
}
DartObjectImpl _listValue(
- [List<DartObjectImpl> elements = DartObjectImpl.EMPTY_LIST]) {
+ [List<DartObjectImpl> elements = const <DartObjectImpl>[]]) {
return new DartObjectImpl(_typeProvider.listType, new ListState(elements));
}
DartObjectImpl _mapValue(
- [List<DartObjectImpl> keyElementPairs = DartObjectImpl.EMPTY_LIST]) {
+ [List<DartObjectImpl> keyElementPairs = const <DartObjectImpl>[]]) {
Map<DartObjectImpl, DartObjectImpl> map =
new Map<DartObjectImpl, DartObjectImpl>();
int count = keyElementPairs.length;
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index a47767a..45e17dcb 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -2534,7 +2534,7 @@
void test_getConstructors_empty() {
ClassElementImpl typeElement = ElementFactory.classElement2("A");
- typeElement.constructors = ConstructorElement.EMPTY_LIST;
+ typeElement.constructors = const <ConstructorElement>[];
InterfaceTypeImpl type = new InterfaceTypeImpl(typeElement);
expect(type.constructors, isEmpty);
}
diff --git a/pkg/analyzer/test/src/summary/summarize_ast_test.dart b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
index 195c480..9cdd293 100644
--- a/pkg/analyzer/test/src/summary/summarize_ast_test.dart
+++ b/pkg/analyzer/test/src/summary/summarize_ast_test.dart
@@ -42,9 +42,6 @@
bool get skipFullyLinkedData => false;
@override
- bool get skipNonConstInitializers => false;
-
- @override
void serializeLibraryText(String text, {bool allowErrors: false}) {
Map<String, UnlinkedUnitBuilder> uriToUnit = this._filesToLink.uriToUnit;
linkerInputs = createLinkerInputs(text);
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 0044bc0..980639d 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -138,13 +138,6 @@
LinkedUnit get definingUnit => linked.units[0];
/**
- * Whether the parts of the IDL marked `@informative` are expected to be
- * included in the generated summary; if `false`, these parts of the IDL won't
- * be checked.
- */
- bool get includeInformative => true;
-
- /**
* Get access to the linked summary that results from serializing and
* then deserializing the library under test.
*/
@@ -157,11 +150,6 @@
bool get skipFullyLinkedData;
/**
- * `true` if non-const variable initializers are not serialized.
- */
- bool get skipNonConstInitializers;
-
- /**
* Get access to the unlinked compilation unit summaries that result from
* serializing and deserializing the library under test.
*/
@@ -1128,7 +1116,6 @@
}
test_class_alias_documented() {
- if (!includeInformative) return;
String text = '''
// Extra comment so doc comment offset != 0
/**
@@ -1206,7 +1193,6 @@
}
test_class_codeRange() {
- if (!includeInformative) return;
UnlinkedClass cls = serializeClassText(' class C {}');
_assertCodeRange(cls.codeRange, 1, 10);
}
@@ -1295,7 +1281,6 @@
}
test_class_documented() {
- if (!includeInformative) return;
String text = '''
// Extra comment so doc comment offset != 0
/**
@@ -1308,7 +1293,6 @@
}
test_class_documented_tripleSlash() {
- if (!includeInformative) return;
String text = '''
/// aaa
/// bbbb
@@ -1321,7 +1305,6 @@
}
test_class_documented_with_references() {
- if (!includeInformative) return;
String text = '''
// Extra comment so doc comment offset != 0
/**
@@ -1337,7 +1320,6 @@
}
test_class_documented_with_with_windows_line_endings() {
- if (!includeInformative) return;
String text = '/**\r\n * Docs\r\n */\r\nclass C {}';
UnlinkedClass cls = serializeClassText(text);
expect(cls.documentationComment, isNotNull);
@@ -1388,9 +1370,7 @@
var classText = 'class C {}';
UnlinkedClass cls = serializeClassText(classText);
expect(cls.name, 'C');
- if (includeInformative) {
- expect(cls.nameOffset, classText.indexOf('C'));
- }
+ expect(cls.nameOffset, classText.indexOf('C'));
}
test_class_no_flags() {
@@ -1479,9 +1459,7 @@
UnlinkedClass cls = serializeClassText(text);
expect(cls.typeParameters, hasLength(1));
expect(cls.typeParameters[0].name, 'T');
- if (includeInformative) {
- expect(cls.typeParameters[0].nameOffset, text.indexOf('T'));
- }
+ expect(cls.typeParameters[0].nameOffset, text.indexOf('T'));
expect(cls.typeParameters[0].bound, isNull);
expect(unlinkedUnits[0].publicNamespace.names[0].numTypeParameters, 1);
}
@@ -1868,9 +1846,6 @@
}
test_constExpr_functionExpression() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
import 'dart:async';
const v = (f) async => await f;
@@ -3489,19 +3464,14 @@
expect(executable.isAsynchronous, isFalse);
expect(executable.isExternal, isFalse);
expect(executable.isGenerator, isFalse);
- if (includeInformative) {
- expect(executable.nameOffset, text.indexOf('C();'));
- expect(executable.periodOffset, 0);
- expect(executable.nameEnd, 0);
- }
+ expect(executable.nameOffset, text.indexOf('C();'));
+ expect(executable.periodOffset, 0);
+ expect(executable.nameEnd, 0);
expect(executable.isRedirectedConstructor, isFalse);
expect(executable.redirectedConstructor, isNull);
expect(executable.redirectedConstructorName, isEmpty);
-
- if (includeInformative) {
- expect(executable.visibleOffset, 0);
- expect(executable.visibleLength, 0);
- }
+ expect(executable.visibleOffset, 0);
+ expect(executable.visibleLength, 0);
}
test_constructor_anonymous() {
@@ -3526,7 +3496,6 @@
}
test_constructor_documented() {
- if (!includeInformative) return;
String text = '''
class C {
/**
@@ -3927,9 +3896,7 @@
expect(parameter.kind, UnlinkedParamKind.named);
expect(parameter.initializer, isNotNull);
expect(parameter.defaultValueCode, '42');
- if (includeInformative) {
- _assertCodeRange(parameter.codeRange, 13, 10);
- }
+ _assertCodeRange(parameter.codeRange, 13, 10);
assertUnlinkedConst(parameter.initializer.bodyExpr,
operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
@@ -3961,9 +3928,7 @@
expect(parameter.kind, UnlinkedParamKind.positional);
expect(parameter.initializer, isNotNull);
expect(parameter.defaultValueCode, '42');
- if (includeInformative) {
- _assertCodeRange(parameter.codeRange, 13, 11);
- }
+ _assertCodeRange(parameter.codeRange, 13, 11);
assertUnlinkedConst(parameter.initializer.bodyExpr,
operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
@@ -4005,12 +3970,10 @@
UnlinkedExecutable executable = findExecutable('foo',
executables: serializeClassText(text).executables);
expect(executable.name, 'foo');
- if (includeInformative) {
- expect(executable.nameOffset, text.indexOf('foo'));
- expect(executable.periodOffset, text.indexOf('.foo'));
- expect(executable.nameEnd, text.indexOf('()'));
- _assertCodeRange(executable.codeRange, 10, 8);
- }
+ expect(executable.nameOffset, text.indexOf('foo'));
+ expect(executable.periodOffset, text.indexOf('.foo'));
+ expect(executable.nameEnd, text.indexOf('()'));
+ _assertCodeRange(executable.codeRange, 10, 8);
}
test_constructor_non_const() {
@@ -5051,15 +5014,11 @@
String text = 'enum E { v1 }';
UnlinkedEnum e = serializeEnumText(text);
expect(e.name, 'E');
- if (includeInformative) {
- expect(e.nameOffset, text.indexOf('E'));
- }
+ expect(e.nameOffset, text.indexOf('E'));
expect(e.values, hasLength(1));
expect(e.values[0].name, 'v1');
- if (includeInformative) {
- expect(e.values[0].nameOffset, text.indexOf('v1'));
- _assertCodeRange(e.codeRange, 0, 13);
- }
+ expect(e.values[0].nameOffset, text.indexOf('v1'));
+ _assertCodeRange(e.codeRange, 0, 13);
expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
expect(unlinkedUnits[0].publicNamespace.names[0].kind,
ReferenceKind.classOrEnum);
@@ -5081,7 +5040,6 @@
}
test_enum_documented() {
- if (!includeInformative) return;
String text = '''
// Extra comment so doc comment offset != 0
/**
@@ -5106,7 +5064,6 @@
}
test_enum_value_documented() {
- if (!includeInformative) return;
String text = '''
enum E {
/**
@@ -5146,11 +5103,9 @@
expect(executable.isAsynchronous, isFalse);
expect(executable.isExternal, isFalse);
expect(executable.isGenerator, isFalse);
- if (includeInformative) {
- expect(executable.nameOffset, text.indexOf('f'));
- expect(executable.visibleOffset, 0);
- expect(executable.visibleLength, 0);
- }
+ expect(executable.nameOffset, text.indexOf('f'));
+ expect(executable.visibleOffset, 0);
+ expect(executable.visibleLength, 0);
expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
expect(unlinkedUnits[0].publicNamespace.names[0].kind,
ReferenceKind.topLevelFunction);
@@ -5200,9 +5155,7 @@
expect(executable.isAsynchronous, isFalse);
expect(executable.isExternal, isFalse);
expect(executable.isGenerator, isFalse);
- if (includeInformative) {
- expect(executable.nameOffset, text.indexOf('f'));
- }
+ expect(executable.nameOffset, text.indexOf('f'));
expect(findVariable('f'), isNull);
expect(findExecutable('f='), isNull);
expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
@@ -5256,11 +5209,9 @@
expect(executable.isAsynchronous, isFalse);
expect(executable.isExternal, isFalse);
expect(executable.isGenerator, isFalse);
- if (includeInformative) {
- expect(executable.visibleOffset, 0);
- expect(executable.visibleLength, 0);
- _assertCodeRange(executable.codeRange, 10, 6);
- }
+ expect(executable.visibleOffset, 0);
+ expect(executable.visibleLength, 0);
+ _assertCodeRange(executable.codeRange, 10, 6);
}
test_executable_member_function_async() {
@@ -5311,9 +5262,7 @@
expect(executable.isExternal, isFalse);
expect(executable.isGenerator, isFalse);
expect(executable.isStatic, isFalse);
- if (includeInformative) {
- _assertCodeRange(executable.codeRange, 10, 15);
- }
+ _assertCodeRange(executable.codeRange, 10, 15);
expect(findVariable('f', variables: cls.fields), isNull);
expect(findExecutable('f=', executables: cls.executables), isNull);
expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
@@ -5356,9 +5305,7 @@
expect(executable.isAsynchronous, isFalse);
expect(executable.isExternal, isFalse);
expect(executable.isGenerator, isFalse);
- if (includeInformative) {
- _assertCodeRange(executable.codeRange, 10, 20);
- }
+ _assertCodeRange(executable.codeRange, 10, 20);
expect(findVariable('f', variables: cls.fields), isNull);
expect(findExecutable('f', executables: cls.executables), isNull);
}
@@ -5496,7 +5443,6 @@
}
test_executable_param_codeRange() {
- if (!includeInformative) return;
UnlinkedExecutable executable = serializeExecutableText('f(int x) {}');
UnlinkedParam parameter = executable.parameters[0];
_assertCodeRange(parameter.codeRange, 2, 5);
@@ -5588,9 +5534,7 @@
expect(param.kind, UnlinkedParamKind.named);
expect(param.initializer, isNotNull);
expect(param.defaultValueCode, '42');
- if (includeInformative) {
- _assertCodeRange(param.codeRange, 3, 5);
- }
+ _assertCodeRange(param.codeRange, 3, 5);
assertUnlinkedConst(param.initializer.bodyExpr,
operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
@@ -5609,9 +5553,7 @@
expect(param.kind, UnlinkedParamKind.positional);
expect(param.initializer, isNotNull);
expect(param.defaultValueCode, '42');
- if (includeInformative) {
- _assertCodeRange(param.codeRange, 3, 6);
- }
+ _assertCodeRange(param.codeRange, 3, 6);
assertUnlinkedConst(param.initializer.bodyExpr,
operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
@@ -5629,9 +5571,7 @@
UnlinkedExecutable executable = serializeExecutableText(text);
expect(executable.parameters, hasLength(1));
expect(executable.parameters[0].name, 'x');
- if (includeInformative) {
- expect(executable.parameters[0].nameOffset, text.indexOf('x'));
- }
+ expect(executable.parameters[0].nameOffset, text.indexOf('x'));
}
test_executable_param_no_flags() {
@@ -5736,9 +5676,7 @@
expect(executable.isAsynchronous, isFalse);
expect(executable.isExternal, isFalse);
expect(executable.isGenerator, isFalse);
- if (includeInformative) {
- expect(executable.nameOffset, text.indexOf('f'));
- }
+ expect(executable.nameOffset, text.indexOf('f'));
expect(findVariable('f'), isNull);
expect(findExecutable('f'), isNull);
expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
@@ -5936,11 +5874,9 @@
'Future');
expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].hides[1],
'Stream');
- if (includeInformative) {
- expect(
- unlinkedUnits[0].publicNamespace.exports[0].combinators[0].offset, 0);
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].end, 0);
- }
+ expect(
+ unlinkedUnits[0].publicNamespace.exports[0].combinators[0].offset, 0);
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].end, 0);
expect(linked.exportNames, isNotEmpty);
}
@@ -6055,12 +5991,10 @@
'Future');
expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].shows[1],
'Stream');
- if (includeInformative) {
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].offset,
- libraryText.indexOf('show'));
- expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].end,
- libraryText.indexOf(';'));
- }
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].offset,
+ libraryText.indexOf('show'));
+ expect(unlinkedUnits[0].publicNamespace.exports[0].combinators[0].end,
+ libraryText.indexOf(';'));
}
test_export_typedef() {
@@ -6191,9 +6125,6 @@
}
test_expr_assignToIndex_ofFieldSequence() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class A {
B b;
@@ -6236,9 +6167,6 @@
}
test_expr_assignToIndex_ofIndexExpression() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class A {
List<B> b;
@@ -6294,9 +6222,6 @@
}
test_expr_assignToIndex_ofTopLevelVariable() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
List<int> a = <int>[0, 1, 2];
final v = (a[1] = 5);
@@ -6324,9 +6249,6 @@
}
test_expr_assignToProperty_ofInstanceCreation() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class C {
int f;
@@ -6358,9 +6280,6 @@
}
test_expr_assignToRef_classStaticField() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class C {
static int f;
@@ -6390,9 +6309,6 @@
}
test_expr_assignToRef_fieldSequence() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class A {
B b;
@@ -6452,9 +6368,6 @@
}
test_expr_assignToRef_topLevelVariable() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
int a = 0;
final v = (a = 1);
@@ -6479,9 +6392,6 @@
}
test_expr_assignToRef_topLevelVariable_imported() {
- if (skipNonConstInitializers) {
- return;
- }
addNamedSource('/a.dart', '''
int a = 0;
''');
@@ -6509,9 +6419,6 @@
}
test_expr_assignToRef_topLevelVariable_imported_withPrefix() {
- if (skipNonConstInitializers) {
- return;
- }
addNamedSource('/a.dart', '''
int a = 0;
''');
@@ -6542,9 +6449,6 @@
}
test_expr_cascadeSection_assignToIndex() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class C {
List<int> items;
@@ -6571,9 +6475,6 @@
}
test_expr_cascadeSection_assignToProperty() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class C {
int f1 = 0;
@@ -6599,9 +6500,6 @@
}
test_expr_cascadeSection_embedded() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class A {
int fa1;
@@ -6634,9 +6532,6 @@
}
test_expr_cascadeSection_invokeMethod() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class A {
int m(int _) => 0;
@@ -6658,9 +6553,6 @@
}
test_expr_extractIndex_ofClassField() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class C {
List<int> get items => null;
@@ -6690,9 +6582,6 @@
}
test_expr_extractProperty_ofInvokeConstructor() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class C {
int f = 0;
@@ -6774,9 +6663,6 @@
}
test_expr_functionExpression_withBlockBody() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
final v = () { return 42; };
''');
@@ -6787,9 +6673,6 @@
}
test_expr_functionExpression_withExpressionBody() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
final v = () => 42;
''');
@@ -6800,9 +6683,6 @@
}
test_expr_functionExpressionInvocation_withBlockBody() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
final v = ((a, b) {return 42;})(1, 2);
''');
@@ -6811,9 +6691,6 @@
}
test_expr_functionExpressionInvocation_withExpressionBody() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
final v = ((a, b) => 42)(1, 2);
''');
@@ -6822,9 +6699,6 @@
}
test_expr_inClosure() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('var v = () => 1;');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
operators: [UnlinkedExprOperation.pushInt], ints: [1]);
@@ -6838,9 +6712,6 @@
}
test_expr_inClosure_refersToOuterParam() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable =
serializeVariableText('var v = (x) => (y) => x;');
assertUnlinkedConst(
@@ -6850,18 +6721,12 @@
}
test_expr_inClosure_refersToParam() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('var v = (x) => x;');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
operators: [UnlinkedExprOperation.pushParameter], strings: ['x']);
}
test_expr_inClosure_refersToParam_methodCall() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('var v = (x) => x.f();');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
operators: [
@@ -6880,9 +6745,6 @@
}
test_expr_inClosure_refersToParam_methodCall_prefixed() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable =
serializeVariableText('var v = (x) => x.y.f();');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
@@ -6904,9 +6766,6 @@
}
test_expr_inClosure_refersToParam_outOfScope() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable =
serializeVariableText('var x; var v = (b) => (b ? (x) => x : x);');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
@@ -6931,9 +6790,6 @@
}
test_expr_inClosure_refersToParam_prefixedIdentifier() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('var v = (x) => x.y;');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
operators: [
@@ -6947,9 +6803,6 @@
}
test_expr_inClosure_refersToParam_prefixedIdentifier_assign() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable =
serializeVariableText('var v = (x) => x.y = null;');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
@@ -6969,9 +6822,6 @@
}
test_expr_inClosure_refersToParam_prefixedPrefixedIdentifier() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('var v = (x) => x.y.z;');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
operators: [
@@ -6987,9 +6837,6 @@
}
test_expr_inClosure_refersToParam_prefixedPrefixedIdentifier_assign() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable =
serializeVariableText('var v = (x) => x.y.z = null;');
assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
@@ -7011,9 +6858,6 @@
}
test_expr_invalid_typeParameter_asPrefix() {
- if (skipNonConstInitializers) {
- return;
- }
var c = serializeClassText('''
class C<T> {
final f = T.k;
@@ -7061,9 +6905,6 @@
}
test_expr_invokeMethod_withTypeParameters() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class C {
f<T, U>() => null;
@@ -7094,9 +6935,6 @@
}
test_expr_invokeMethodRef_instance() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
class A {
B b;
@@ -7133,9 +6971,6 @@
}
test_expr_invokeMethodRef_static_importedWithPrefix() {
- if (skipNonConstInitializers) {
- return;
- }
addNamedSource('/a.dart', '''
class C {
static int m() => 42;
@@ -7163,9 +6998,6 @@
}
test_expr_invokeMethodRef_with_reference_arg() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
f(x) => null;
final u = null;
@@ -7187,9 +7019,6 @@
}
test_expr_invokeMethodRef_withTypeParameters() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
f<T, U>() => null;
final v = f<int, String>();
@@ -7275,9 +7104,6 @@
}
test_expr_super() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
final v = super;
''');
@@ -7287,9 +7113,6 @@
}
test_expr_this() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
final v = this;
''');
@@ -7299,9 +7122,6 @@
}
test_expr_throwException() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
final v = throw 1 + 2;
''');
@@ -7320,9 +7140,6 @@
}
test_expr_typeCast() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
final v = 42 as num;
''');
@@ -7342,9 +7159,6 @@
}
test_expr_typeCheck() {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
final v = 42 is num;
''');
@@ -7389,7 +7203,6 @@
}
test_field_documented() {
- if (!includeInformative) return;
String text = '''
class C {
/**
@@ -7578,7 +7391,6 @@
}
test_function_documented() {
- if (!includeInformative) return;
String text = '''
// Extra comment so doc comment offset != 0
/**
@@ -7611,7 +7423,6 @@
}
test_getter_documented() {
- if (!includeInformative) return;
String text = '''
// Extra comment so doc comment offset != 0
/**
@@ -7720,10 +7531,8 @@
expect(unlinkedUnits[0].imports[0].combinators[0].hides, hasLength(2));
expect(unlinkedUnits[0].imports[0].combinators[0].hides[0], 'Future');
expect(unlinkedUnits[0].imports[0].combinators[0].hides[1], 'Stream');
- if (includeInformative) {
- expect(unlinkedUnits[0].imports[0].combinators[0].offset, 0);
- expect(unlinkedUnits[0].imports[0].combinators[0].end, 0);
- }
+ expect(unlinkedUnits[0].imports[0].combinators[0].offset, 0);
+ expect(unlinkedUnits[0].imports[0].combinators[0].end, 0);
}
test_import_implicit() {
@@ -7732,10 +7541,8 @@
expect(unlinkedUnits[0].imports, hasLength(1));
checkDependency(linked.importDependencies[0], 'dart:core');
expect(unlinkedUnits[0].imports[0].uri, isEmpty);
- if (includeInformative) {
- expect(unlinkedUnits[0].imports[0].uriOffset, 0);
- expect(unlinkedUnits[0].imports[0].uriEnd, 0);
- }
+ expect(unlinkedUnits[0].imports[0].uriOffset, 0);
+ expect(unlinkedUnits[0].imports[0].uriEnd, 0);
expect(unlinkedUnits[0].imports[0].prefixReference, 0);
expect(unlinkedUnits[0].imports[0].combinators, isEmpty);
expect(unlinkedUnits[0].imports[0].isImplicit, isTrue);
@@ -8317,7 +8124,6 @@
}
test_library_documented() {
- if (!includeInformative) return;
String text = '''
// Extra comment so doc comment offset != 0
/**
@@ -8926,7 +8732,6 @@
}
test_method_documented() {
- if (!includeInformative) return;
String text = '''
class C {
/**
@@ -9162,7 +8967,6 @@
}
test_setter_documented() {
- if (!includeInformative) return;
String text = '''
// Extra comment so doc comment offset != 0
/**
@@ -9386,7 +9190,6 @@
}
test_type_param_codeRange() {
- if (!includeInformative) return;
UnlinkedClass cls =
serializeClassText('class A {} class C<T extends A> {}');
UnlinkedTypeParam typeParameter = cls.typeParameters[0];
@@ -9631,13 +9434,11 @@
}
test_typedef_codeRange() {
- if (!includeInformative) return;
UnlinkedTypedef type = serializeTypedefText('typedef F();');
_assertCodeRange(type.codeRange, 0, 12);
}
test_typedef_documented() {
- if (!includeInformative) return;
String text = '''
// Extra comment so doc comment offset != 0
/**
@@ -9707,9 +9508,7 @@
String text = 'typedef F();';
UnlinkedTypedef type = serializeTypedefText(text);
expect(type.name, 'F');
- if (includeInformative) {
- expect(type.nameOffset, text.indexOf('F'));
- }
+ expect(type.nameOffset, text.indexOf('F'));
expect(unlinkedUnits[0].publicNamespace.names, hasLength(1));
expect(
unlinkedUnits[0].publicNamespace.names[0].kind, ReferenceKind.typedef);
@@ -9778,7 +9577,6 @@
}
test_unit_codeRange() {
- if (!includeInformative) return;
serializeLibraryText(' int a = 1; ');
UnlinkedUnit unit = unlinkedUnits[0];
_assertCodeRange(unit.codeRange, 0, 14);
@@ -9855,9 +9653,7 @@
test_variable() {
String text = 'int i;';
UnlinkedVariable v = serializeVariableText(text, variableName: 'i');
- if (includeInformative) {
- expect(v.nameOffset, text.indexOf('i;'));
- }
+ expect(v.nameOffset, text.indexOf('i;'));
expect(findExecutable('i'), isNull);
expect(findExecutable('i='), isNull);
expect(unlinkedUnits[0].publicNamespace.names, hasLength(2));
@@ -9872,7 +9668,6 @@
}
test_variable_codeRange() {
- if (!includeInformative) return;
serializeLibraryText(' int a = 1, b = 22;');
List<UnlinkedVariable> variables = unlinkedUnits[0].variables;
_assertCodeRange(variables[0].codeRange, 1, 9);
@@ -9886,7 +9681,6 @@
}
test_variable_documented() {
- if (!includeInformative) return;
String text = '''
// Extra comment so doc comment offset != 0
/**
@@ -9939,9 +9733,7 @@
UnlinkedVariable variable = serializeVariableText('var v = 42;');
UnlinkedExecutable initializer = variable.initializer;
expect(initializer, isNotNull);
- if (includeInformative) {
- expect(initializer.nameOffset, 8);
- }
+ expect(initializer.nameOffset, 8);
expect(initializer.name, isEmpty);
expect(initializer.localFunctions, isEmpty);
}
@@ -9957,38 +9749,28 @@
UnlinkedVariable variable = serializeVariableText(text);
UnlinkedExecutable initializer = variable.initializer;
expect(initializer, isNotNull);
- if (includeInformative) {
- expect(initializer.nameOffset, text.indexOf('<dynamic, dynamic>{"1'));
- }
+ expect(initializer.nameOffset, text.indexOf('<dynamic, dynamic>{"1'));
expect(initializer.name, isEmpty);
expect(initializer.localFunctions, hasLength(2));
// closure: () { f1() {} var v1; }
{
UnlinkedExecutable closure = initializer.localFunctions[0];
- if (includeInformative) {
- expect(closure.nameOffset, text.indexOf('() { f1()'));
- }
+ expect(closure.nameOffset, text.indexOf('() { f1()'));
expect(closure.name, isEmpty);
// closure - f1
expect(closure.localFunctions, hasLength(1));
expect(closure.localFunctions[0].name, 'f1');
- if (includeInformative) {
- expect(closure.localFunctions[0].nameOffset, text.indexOf('f1()'));
- }
+ expect(closure.localFunctions[0].nameOffset, text.indexOf('f1()'));
}
// closure: () { f2() {} var v2; }
{
UnlinkedExecutable closure = initializer.localFunctions[1];
- if (includeInformative) {
- expect(closure.nameOffset, text.indexOf('() { f2()'));
- }
+ expect(closure.nameOffset, text.indexOf('() { f2()'));
expect(closure.name, isEmpty);
// closure - f1
expect(closure.localFunctions, hasLength(1));
expect(closure.localFunctions[0].name, 'f2');
- if (includeInformative) {
- expect(closure.localFunctions[0].nameOffset, text.indexOf('f2()'));
- }
+ expect(closure.localFunctions[0].nameOffset, text.indexOf('f2()'));
}
}
@@ -10090,9 +9872,6 @@
*/
void _assertAssignmentOperator(
String expr, UnlinkedExprAssignOperator expectedAssignOperator) {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
int a = 0;
final v = $expr;
@@ -10148,9 +9927,6 @@
*/
void _assertRefPrefixPostfixIncrementDecrement(
String expr, UnlinkedExprAssignOperator expectedAssignmentOperator) {
- if (skipNonConstInitializers) {
- return;
- }
UnlinkedVariable variable = serializeVariableText('''
int a = 0;
final v = $expr;
diff --git a/pkg/analyzer/test/src/task/dart_test.dart b/pkg/analyzer/test/src/task/dart_test.dart
index 6853053..d5cd7ac 100644
--- a/pkg/analyzer/test/src/task/dart_test.dart
+++ b/pkg/analyzer/test/src/task/dart_test.dart
@@ -4667,7 +4667,8 @@
computeResult(target, VERIFY_ERRORS, matcher: isVerifyUnitTask);
// validate
_fillErrorListener(VERIFY_ERRORS);
- errorListener.assertNoErrors();
+ errorListener.assertErrorsWithCodes(
+ <ErrorCode>[CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
}
test_perform_ConstantValidator_dependencyCycle() {
diff --git a/pkg/analyzer/test/src/task/driver_test.dart b/pkg/analyzer/test/src/task/driver_test.dart
index 76c3312..bc4abcc 100644
--- a/pkg/analyzer/test/src/task/driver_test.dart
+++ b/pkg/analyzer/test/src/task/driver_test.dart
@@ -177,7 +177,7 @@
new ResultDescriptor<String>('result', null);
context
.getCacheEntry(target)
- .setValue(result, '', TargetedResult.EMPTY_LIST);
+ .setValue(result, '', const <TargetedResult>[]);
expect(analysisDriver.createWorkOrderForResult(target, result), isNull);
}
@@ -484,7 +484,7 @@
if (complete) {
context
.getCacheEntry(target)
- .setValue(result, '', TargetedResult.EMPTY_LIST);
+ .setValue(result, '', const <TargetedResult>[]);
} else {
context.getCacheEntry(target).setState(result, CacheState.INVALID);
}
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 5f32672..c176d1d 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -20,6 +20,7 @@
InstantiationConstantValue;
import 'elements/types.dart';
import 'elements/entities.dart';
+import 'kernel/kelements.dart' show KLocalFunction;
import 'library_loader.dart';
import 'universe/use.dart';
import 'universe/world_impact.dart'
@@ -278,16 +279,7 @@
// TODO(het): we would like to separate out types that are only needed for
// rti from types that are needed for their members.
if (type is FunctionType) {
- for (DartType argumentType in type.parameterTypes) {
- _collectTypeDependencies(argumentType, dependencies);
- }
- for (DartType argumentType in type.optionalParameterTypes) {
- _collectTypeDependencies(argumentType, dependencies);
- }
- for (DartType argumentType in type.namedParameterTypes) {
- _collectTypeDependencies(argumentType, dependencies);
- }
- _collectTypeDependencies(type.returnType, dependencies);
+ _collectFunctionTypeDependencies(type, dependencies);
} else if (type is TypedefType) {
type.typeArguments
.forEach((t) => _collectTypeDependencies(t, dependencies));
@@ -299,6 +291,23 @@
}
}
+ void _collectFunctionTypeDependencies(
+ FunctionType type, Dependencies dependencies) {
+ for (FunctionTypeVariable typeVariable in type.typeVariables) {
+ _collectTypeDependencies(typeVariable.bound, dependencies);
+ }
+ for (DartType argumentType in type.parameterTypes) {
+ _collectTypeDependencies(argumentType, dependencies);
+ }
+ for (DartType argumentType in type.optionalParameterTypes) {
+ _collectTypeDependencies(argumentType, dependencies);
+ }
+ for (DartType argumentType in type.namedParameterTypes) {
+ _collectTypeDependencies(argumentType, dependencies);
+ }
+ _collectTypeDependencies(type.returnType, dependencies);
+ }
+
/// Extract any dependencies that are known from the impact of [element].
void _collectDependenciesFromImpact(
MemberEntity element, Dependencies dependencies) {
@@ -307,14 +316,17 @@
element,
worldImpact,
new WorldImpactVisitorImpl(visitStaticUse: (StaticUse staticUse) {
- if (staticUse.element is MemberEntity) {
- dependencies.members.add(staticUse.element);
+ Entity usedEntity = staticUse.element;
+ if (usedEntity is MemberEntity) {
+ dependencies.members.add(usedEntity);
} else {
- assert(
- staticUse.element is Local,
- failedAt(
- staticUse.element, "Unexpected static use $staticUse."));
- dependencies.localFunctions.add(staticUse.element);
+ assert(usedEntity is KLocalFunction,
+ failedAt(usedEntity, "Unexpected static use $staticUse."));
+ KLocalFunction localFunction = usedEntity;
+ // TODO(sra): Consult KClosedWorld to see if signature is needed.
+ _collectFunctionTypeDependencies(
+ localFunction.functionType, dependencies);
+ dependencies.localFunctions.add(localFunction);
}
switch (staticUse.kind) {
case StaticUseKind.CONSTRUCTOR_INVOKE:
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index e5759ba..9a5f781 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -1092,7 +1092,8 @@
DartType type = _closedWorld.elementEnvironment.getFieldType(field);
if (!type.treatAsRaw ||
type.isTypeVariable ||
- type.unaliased.isFunctionType) {
+ type.unaliased.isFunctionType ||
+ type.unaliased.isFutureOr) {
// We cannot generate the correct type representation here, so don't
// inline this access.
// TODO(sra): If the input is such that we don't need a type check, we
diff --git a/pkg/front_end/lib/src/fasta/combinator.dart b/pkg/front_end/lib/src/fasta/combinator.dart
index 9f97607..5dfcf91 100644
--- a/pkg/front_end/lib/src/fasta/combinator.dart
+++ b/pkg/front_end/lib/src/fasta/combinator.dart
@@ -7,15 +7,30 @@
class Combinator {
final bool isShow;
+ final List<CombinatorIdentifier> identifiers;
+
final Set<String> names;
- Combinator(this.isShow, this.names, int charOffset, Uri fileUri);
+ Combinator(
+ this.isShow, this.identifiers, this.names, int charOffset, Uri fileUri);
- Combinator.show(Iterable<String> names, int charOffset, Uri fileUri)
- : this(true, new Set<String>.from(names), charOffset, fileUri);
+ Combinator.hide(List<CombinatorIdentifier> identifiers,
+ Iterable<String> names, int charOffset, Uri fileUri)
+ : this(false, identifiers, new Set<String>.from(names), charOffset,
+ fileUri);
- Combinator.hide(Iterable<String> names, int charOffset, Uri fileUri)
- : this(false, new Set<String>.from(names), charOffset, fileUri);
+ Combinator.show(List<CombinatorIdentifier> identifiers,
+ Iterable<String> names, int charOffset, Uri fileUri)
+ : this(true, identifiers, new Set<String>.from(names), charOffset,
+ fileUri);
bool get isHide => !isShow;
}
+
+class CombinatorIdentifier {
+ final int offset;
+ final String name;
+ final bool isSynthetic;
+
+ CombinatorIdentifier(this.offset, this.name, this.isSynthetic);
+}
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 537c775..a695393 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -974,6 +974,18 @@
message: r"""Field isn't final, but constructor is 'const'.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstConstructorRedirectionToNonConst =
+ messageConstConstructorRedirectionToNonConst;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstConstructorRedirectionToNonConst =
+ const MessageCode("ConstConstructorRedirectionToNonConst",
+ dart2jsCode: "*fatal*",
+ severity: Severity.error,
+ message:
+ r"""A constant constructor can't call a non-constant constructor.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeConstConstructorWithBody = messageConstConstructorWithBody;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3490,6 +3502,64 @@
tip: r"""Try moving the with clause before the implements clause.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeImplementsFutureOr = messageImplementsFutureOr;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageImplementsFutureOr = const MessageCode(
+ "ImplementsFutureOr",
+ dart2jsCode: "*fatal*",
+ severity: Severity.error,
+ message: r"""'FutureOr' can't be used in an 'implements' clause.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, int count)>
+ templateImplementsRepeated =
+ const Template<Message Function(String name, int count)>(
+ messageTemplate: r"""'#name' can only be implemented once.""",
+ tipTemplate: r"""Try removing #count of the occurrences.""",
+ withArguments: _withArgumentsImplementsRepeated);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, int count)> codeImplementsRepeated =
+ const Code<Message Function(String name, int count)>(
+ "ImplementsRepeated", templateImplementsRepeated,
+ analyzerCode: "IMPLEMENTS_REPEATED", dart2jsCode: "*fatal*");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsImplementsRepeated(String name, int count) {
+ return new Message(codeImplementsRepeated,
+ message: """'${name}' can only be implemented once.""",
+ tip: """Try removing ${count} of the occurrences.""",
+ arguments: {'name': name, 'count': count});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+ Message Function(
+ String
+ name)> templateImplementsSuperClass = const Template<
+ Message Function(String name)>(
+ messageTemplate:
+ r"""'#name' can't be used in both 'extends' and 'implements' clauses.""",
+ tipTemplate: r"""Try removing one of the occurrences.""",
+ withArguments: _withArgumentsImplementsSuperClass);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeImplementsSuperClass =
+ const Code<Message Function(String name)>(
+ "ImplementsSuperClass", templateImplementsSuperClass,
+ analyzerCode: "IMPLEMENTS_SUPER_CLASS", dart2jsCode: "*fatal*");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsImplementsSuperClass(String name) {
+ return new Message(codeImplementsSuperClass,
+ message:
+ """'${name}' can't be used in both 'extends' and 'implements' clauses.""",
+ tip: """Try removing one of the occurrences.""",
+ arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
DartType
@@ -6580,6 +6650,8 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageSuperAsIdentifier = const MessageCode(
"SuperAsIdentifier",
+ analyzerCode: "SUPER_AS_EXPRESSION",
+ dart2jsCode: "*fatal*",
message: r"""Expected identifier, but got 'super'.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 476c2da..399112b 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -469,10 +469,10 @@
combinators ??= <Combinator>[];
combinators.add(combinator.isShow
- ? new Combinator.show(
- combinator.names, combinator.fileOffset, library.fileUri)
- : new Combinator.hide(
- combinator.names, combinator.fileOffset, library.fileUri));
+ ? new Combinator.show(null, combinator.names,
+ combinator.fileOffset, library.fileUri)
+ : new Combinator.hide(null, combinator.names,
+ combinator.fileOffset, library.fileUri));
}
debugLibrary.addImport(
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 81eb16d..4be50c6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -1098,12 +1098,14 @@
Expression argument = toValue(node);
arguments[i] = argument;
if (i > firstNamedArgumentIndex) {
- arguments[i] = new NamedExpression(
- "#$i",
+ arguments[i] = new NamedExpressionJudgment(
+ tokensSaver?.namedExpressionTokens(null, null),
+ '#$i',
buildCompileTimeErrorExpression(
fasta.messageExpectedNamedArgument,
- forest.readOffset(argument)))
- ..fileOffset = beginToken.charOffset;
+ forest.readOffset(argument)),
+ originalValue: argument)
+ ..fileOffset = offsetForToken(beginToken);
}
}
}
@@ -2776,27 +2778,29 @@
@override
void handleUnaryPrefixAssignmentExpression(Token token) {
debugEvent("UnaryPrefixAssignmentExpression");
- Object generator = pop();
- if (generator is Generator) {
- push(generator.buildPrefixIncrement(incrementOperator(token),
- offset: token.charOffset));
+ Object target = pop();
+ Generator generator;
+ if (target is Generator) {
+ generator = target;
} else {
- push(
- wrapInCompileTimeError(toValue(generator), fasta.messageNotAnLvalue));
+ generator = new KernelNonLValueGenerator(this, token, toValue(target));
}
+ push(generator.buildPrefixIncrement(incrementOperator(token),
+ offset: token.charOffset));
}
@override
void handleUnaryPostfixAssignmentExpression(Token token) {
debugEvent("UnaryPostfixAssignmentExpression");
- Object generator = pop();
- if (generator is Generator) {
- push(new DelayedPostfixIncrement(
- this, token, generator, incrementOperator(token), null));
+ Object target = pop();
+ Generator generator;
+ if (target is Generator) {
+ generator = target;
} else {
- push(
- wrapInCompileTimeError(toValue(generator), fasta.messageNotAnLvalue));
+ generator = new KernelNonLValueGenerator(this, token, toValue(target));
}
+ push(new DelayedPostfixIncrement(
+ this, token, generator, incrementOperator(token), null));
}
@override
@@ -4341,7 +4345,7 @@
constructor,
forest.castArguments(arguments),
buildCompileTimeError(fasta.messageConstConstructorWithNonConstSuper,
- charOffset, member.name.length),
+ charOffset, constructor.name.name.length),
charOffset);
}
needsImplicitSuperInitializer = false;
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 05b2a4d..ec87044 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -68,6 +68,7 @@
DartType,
DynamicType,
Expression,
+ IllegalAssignmentJudgment,
Initializer,
InvalidConstructorInvocationJudgment,
InvalidType,
@@ -119,7 +120,8 @@
///
/// The returned expression evaluates to the assigned value, unless
/// [voidContext] is true, in which case it may evaluate to anything.
- Expression buildAssignment(Expression value, {bool voidContext});
+ Expression buildAssignment(Expression value,
+ {bool voidContext, int offset: -1});
/// Returns a [Expression] representing a null-aware assignment (`??=`) with
/// the generator on the LHS and [value] on the RHS.
@@ -779,7 +781,8 @@
}
@override
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
return new SyntheticExpressionJudgment(buildError(
forest.arguments(<Expression>[value], token, token),
isSetter: true));
@@ -790,7 +793,8 @@
{int offset: -1,
bool voidContext: false,
Procedure interfaceTarget,
- bool isPreIncDec: false}) {
+ bool isPreIncDec: false,
+ bool isPostIncDec: false}) {
return new SyntheticExpressionJudgment(buildError(
forest.arguments(<Expression>[value], token, token),
isGetter: true));
@@ -937,15 +941,16 @@
}
@override
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
- return makeInvalidWrite(value);
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
+ return buildInvalidAssignment(value, offset);
}
@override
Expression buildNullAwareAssignment(
Expression value, DartType type, int offset,
{bool voidContext: false}) {
- return makeInvalidWrite(value);
+ return buildInvalidAssignment(value, offset);
}
@override
@@ -953,20 +958,36 @@
{int offset: -1,
bool voidContext: false,
Procedure interfaceTarget,
- bool isPreIncDec: false}) {
- return makeInvalidWrite(value);
+ bool isPreIncDec: false,
+ bool isPostIncDec: false}) {
+ return buildInvalidAssignment(value, offset);
}
@override
Expression buildPrefixIncrement(Name binaryOperator,
{int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
- return makeInvalidWrite(null);
+ return buildInvalidAssignment(
+ forest.literalInt(1, null, isSynthetic: true), offset);
}
@override
Expression buildPostfixIncrement(Name binaryOperator,
{int offset: -1, bool voidContext: false, Procedure interfaceTarget}) {
- return makeInvalidWrite(null);
+ return buildInvalidAssignment(
+ forest.literalInt(1, null, isSynthetic: true), offset);
+ }
+
+ Expression buildInvalidAssignment(Expression value, int offset) {
+ var lhs = buildSimpleRead();
+ // The lhs expression needs to have a parent so that type inference can be
+ // applied to it, but it doesn't matter what the parent is because the
+ // lhs expression won't appear in the tree. So just give it a quick and
+ // dirty parent.
+ new VariableDeclaration.forValue(lhs);
+
+ return new IllegalAssignmentJudgment(value,
+ assignmentOffset: offset, desugared: makeInvalidWrite(value))
+ ..write = lhs;
}
@override
@@ -1025,7 +1046,8 @@
Expression makeAssignmentExpression(bool voidContext) {
if (identical("=", assignmentOperator)) {
- return generator.buildAssignment(value, voidContext: voidContext);
+ return generator.buildAssignment(value,
+ voidContext: voidContext, offset: token.offset);
} else if (identical("+=", assignmentOperator)) {
return generator.buildCompoundAssignment(plusName, value,
offset: offsetForToken(token), voidContext: voidContext);
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index ebd3eb6..42e8892 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -183,10 +183,11 @@
}
@override
- IntJudgment literalInt(int value, Token token, {Expression desugaredError}) {
+ IntJudgment literalInt(int value, Token token,
+ {Expression desugaredError, bool isSynthetic: false}) {
return new IntJudgment(
typeInferenceTokensSaver?.intLiteralTokens(token), value,
- desugaredError: desugaredError)
+ desugaredError: desugaredError, isSynthetic: isSynthetic)
..fileOffset = offsetForToken(token);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index db980e4..2e029e5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -76,7 +76,8 @@
/// Return a representation of an integer literal at the given [location]. The
/// literal has the given [value].
- Expression literalInt(int value, Token location, {Expression desugaredError});
+ Expression literalInt(int value, Token location,
+ {Expression desugaredError, bool isSynthetic: false});
/// Return a representation of a list literal. The [constKeyword] is the
/// location of the `const` keyword, or `null` if there is no keyword. The
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 90bdaf3..d46c89c 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -47,11 +47,14 @@
show
LocatedMessage,
Message,
+ messageImplementsFutureOr,
messagePatchClassOrigin,
messagePatchClassTypeVariablesMismatch,
messagePatchDeclarationMismatch,
messagePatchDeclarationOrigin,
noLength,
+ templateImplementsRepeated,
+ templateImplementsSuperClass,
templateMissingImplementationCause,
templateMissingImplementationNotAbstract,
templateOverriddenMethodCause,
@@ -79,6 +82,7 @@
KernelLibraryBuilder,
KernelProcedureBuilder,
KernelRedirectingFactoryBuilder,
+ KernelNamedTypeBuilder,
KernelTypeBuilder,
KernelTypeVariableBuilder,
LibraryBuilder,
@@ -194,6 +198,64 @@
}
}
+ void checkSupertypes(CoreTypes coreTypes) {
+ // This method determines whether the class (that's being built) its super
+ // class appears both in 'extends' and 'implements' clauses and whether any
+ // interface appears multiple times in the 'implements' clause.
+ if (interfaces == null) return;
+
+ // Extract super class (if it exists).
+ ClassBuilder superClass;
+ KernelTypeBuilder superClassType = supertype;
+ if (superClassType is KernelNamedTypeBuilder) {
+ Declaration decl = superClassType.declaration;
+ if (decl is ClassBuilder) {
+ superClass = decl;
+ }
+ }
+
+ // Validate interfaces.
+ Map<ClassBuilder, int> problems;
+ Map<ClassBuilder, int> problemsOffsets;
+ Set<ClassBuilder> implemented = new Set<ClassBuilder>();
+ for (KernelTypeBuilder type in interfaces) {
+ if (type is KernelNamedTypeBuilder) {
+ Declaration decl = type.declaration;
+ if (decl is ClassBuilder) {
+ ClassBuilder interface = decl;
+ if (superClass == interface) {
+ addCompileTimeError(
+ templateImplementsSuperClass.withArguments(interface.name),
+ type.charOffset,
+ noLength);
+ } else if (implemented.contains(interface)) {
+ // Aggregate repetitions.
+ problems ??= new Map<ClassBuilder, int>();
+ problems[interface] ??= 0;
+ problems[interface] += 1;
+
+ problemsOffsets ??= new Map<ClassBuilder, int>();
+ problemsOffsets[interface] ??= type.charOffset;
+ } else if (interface.target == coreTypes.futureOrClass) {
+ addCompileTimeError(messageImplementsFutureOr, type.charOffset,
+ interface.target.name.length);
+ } else {
+ implemented.add(interface);
+ }
+ }
+ }
+ }
+ if (problems != null) {
+ problems.forEach((ClassBuilder interface, int repetitions) {
+ addCompileTimeError(
+ templateImplementsRepeated.withArguments(
+ interface.name, repetitions),
+ problemsOffsets[interface],
+ noLength);
+ });
+ }
+ }
+
@override
int resolveConstructors(LibraryBuilder library) {
int count = super.resolveConstructors(library);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
index 90a8c07..004ea06 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator.dart
@@ -142,7 +142,8 @@
}
@override
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
var complexAssignment = startComplexAssignment(value);
return _finish(_makeSimpleWrite(value, voidContext, complexAssignment),
complexAssignment);
@@ -199,8 +200,8 @@
{int offset: TreeNode.noOffset,
bool voidContext: false,
Procedure interfaceTarget}) {
- return buildCompoundAssignment(
- binaryOperator, forest.literalInt(1, null)..fileOffset = offset,
+ return buildCompoundAssignment(binaryOperator,
+ forest.literalInt(1, null, isSynthetic: true)..fileOffset = offset,
offset: offset,
voidContext: voidContext,
interfaceTarget: interfaceTarget,
@@ -213,8 +214,8 @@
bool voidContext: false,
Procedure interfaceTarget}) {
if (voidContext) {
- return buildCompoundAssignment(
- binaryOperator, forest.literalInt(1, null)..fileOffset = offset,
+ return buildCompoundAssignment(binaryOperator,
+ forest.literalInt(1, null, isSynthetic: true)..fileOffset = offset,
offset: offset,
voidContext: voidContext,
interfaceTarget: interfaceTarget,
@@ -501,7 +502,8 @@
@override
ComplexAssignmentJudgment startComplexAssignment(Expression rhs) =>
- new PropertyAssignmentJudgment(null, rhs);
+ new PropertyAssignmentJudgment(null, rhs,
+ isSyntheticLhs: token.isSynthetic);
@override
void printOn(StringSink sink) {
@@ -1530,7 +1532,8 @@
: super(helper, token);
@override
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
return _buildUnresolvedVariableAssignment(false, value);
}
@@ -1539,7 +1542,8 @@
{int offset: TreeNode.noOffset,
bool voidContext: false,
Procedure interfaceTarget,
- bool isPreIncDec: false}) {
+ bool isPreIncDec: false,
+ bool isPostIncDec: false}) {
return _buildUnresolvedVariableAssignment(true, value);
}
@@ -1595,7 +1599,8 @@
super(helper, token);
@override
- Expression buildAssignment(Expression value, {bool voidContext}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext, int offset: -1}) {
return new PropertySet(receiver, name, value)
..fileOffset = offsetForToken(token);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
index cbff91f..c9cfbf9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
@@ -135,7 +135,8 @@
}
}
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
return buildAssignmentError();
}
@@ -260,7 +261,8 @@
return unsupported("buildSimpleRead", offsetForToken(token), uri);
}
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
return unsupported("buildAssignment", offsetForToken(token), uri);
}
@@ -331,7 +333,8 @@
return unsupported("buildSimpleRead", offsetForToken(token), uri);
}
- Expression buildAssignment(Expression value, {bool voidContext: false}) {
+ Expression buildAssignment(Expression value,
+ {bool voidContext: false, int offset: -1}) {
return unsupported("buildAssignment", offsetForToken(token), uri);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 11ed95df..5d79c08 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -65,8 +65,6 @@
import '../problems.dart' show unexpected, unhandled;
-import '../source/outline_listener.dart' show OutlineListener;
-
import '../source/source_class_builder.dart' show SourceClassBuilder;
import '../source/source_library_builder.dart'
@@ -150,13 +148,10 @@
/// the error message is the corresponding value in the map.
Map<String, String> unserializableExports;
- final OutlineListener outlineListener;
-
KernelLibraryBuilder(Uri uri, Uri fileUri, Loader loader, this.actualOrigin,
[Scope scope, Library target])
: library = target ??
(actualOrigin?.library ?? new Library(uri, fileUri: fileUri)),
- outlineListener = loader.createOutlineListener(fileUri),
super(loader, fileUri, scope);
@override
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
index cd00ddb..bcd41f7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart
@@ -559,7 +559,8 @@
/// pre-decrement.
bool isPreIncDec = false;
- ComplexAssignmentJudgment(this.rhs) : super(null);
+ ComplexAssignmentJudgment(this.rhs, {Expression desugared})
+ : super(desugared);
String toString() {
var parts = _getToStringParts();
@@ -665,7 +666,7 @@
combinedType = readType == null
? rhsType
: inferrer.typeSchemaEnvironment
- .getLeastUpperBound(readType, rhsType);
+ .getStandardUpperBound(readType, rhsType);
if (inferrer.strongMode) {
nullAwareCombiner.staticType = combinedType;
}
@@ -756,7 +757,7 @@
inferrer.inferExpression(otherwiseJudgment, typeContext, useLub,
isVoidAllowed: true);
inferredType = useLub
- ? inferrer.typeSchemaEnvironment.getLeastUpperBound(
+ ? inferrer.typeSchemaEnvironment.getStandardUpperBound(
thenJudgment.inferredType, otherwiseJudgment.inferredType)
: greatestClosure(inferrer.coreTypes, typeContext);
if (inferrer.strongMode) {
@@ -1438,13 +1439,9 @@
// - Let T = greatest closure of K with respect to `?` if K is not `_`, else
// UP(t0, t1)
// - Then the inferred type is T.
- if (rhsType is VoidType) {
- inferredType = rhsType;
- } else {
- inferredType = useLub
- ? inferrer.typeSchemaEnvironment.getLeastUpperBound(lhsType, rhsType)
- : greatestClosure(inferrer.coreTypes, typeContext);
- }
+ inferredType = useLub
+ ? inferrer.typeSchemaEnvironment.getStandardUpperBound(lhsType, rhsType)
+ : greatestClosure(inferrer.coreTypes, typeContext);
if (inferrer.strongMode) {
body.staticType = inferredType;
}
@@ -1492,8 +1489,9 @@
/// If `-1`, then there is no separate location for invalid assignment.
final int assignmentOffset;
- IllegalAssignmentJudgment(ExpressionJudgment rhs, {this.assignmentOffset: -1})
- : super(rhs) {
+ IllegalAssignmentJudgment(ExpressionJudgment rhs,
+ {this.assignmentOffset: -1, Expression desugared})
+ : super(rhs, desugared: desugared) {
rhs.parent = this;
}
@@ -1625,16 +1623,22 @@
class IntJudgment extends IntLiteral implements ExpressionJudgment {
IntLiteralTokens tokens;
final kernel.Expression desugaredError;
+ final bool isSynthetic;
DartType inferredType;
- IntJudgment(this.tokens, int value, {this.desugaredError}) : super(value);
+ IntJudgment(this.tokens, int value,
+ {this.desugaredError, this.isSynthetic: false})
+ : super(value);
@override
Expression infer<Expression, Statement, Initializer, Type>(
ShadowTypeInferrer inferrer, DartType typeContext) {
inferredType = inferrer.coreTypes.intClass.rawType;
- inferrer.listener.intLiteral(this, fileOffset, tokens, value, inferredType);
+ if (!isSynthetic) {
+ inferrer.listener
+ .intLiteral(this, fileOffset, tokens, value, inferredType);
+ }
if (desugaredError != null) {
parent.replaceChild(this, desugaredError);
parent = null;
@@ -2234,10 +2238,11 @@
/// If this assignment uses null-aware access (`?.`), the conditional
/// expression that guards the access; otherwise `null`.
ConditionalExpression nullAwareGuard;
+ final bool isSyntheticLhs;
PropertyAssignmentJudgment(
ExpressionJudgment receiver, ExpressionJudgment rhs,
- {bool isSuper: false})
+ {bool isSuper: false, this.isSyntheticLhs: false})
: super(receiver, rhs, isSuper);
@override
@@ -2287,6 +2292,7 @@
inferrer.listener.propertyAssign(
this,
write.fileOffset,
+ isSyntheticLhs,
receiverType,
inferrer.getRealTarget(writeMember),
writeContext,
@@ -3710,10 +3716,17 @@
/// Concrete shadow object representing a named expression.
class NamedExpressionJudgment extends NamedExpression {
- NamedExpressionTokens tokens;
+ final NamedExpressionTokens tokens;
- NamedExpressionJudgment(this.tokens, String nameLexeme, Expression value)
- : super(nameLexeme, value);
+ /// The original value that is wrapped by this synthetic named argument.
+ /// Its type will be inferred.
+ final Expression originalValue;
+
+ NamedExpressionJudgment(this.tokens, String nameLexeme, Expression value,
+ {this.originalValue})
+ : super(nameLexeme, value) {
+ originalValue?.parent = this;
+ }
ExpressionJudgment get judgment => value;
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index f128a30..0715e41 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -59,6 +59,7 @@
LocatedMessage,
messageConstConstructorNonFinalField,
messageConstConstructorNonFinalFieldCause,
+ messageConstConstructorRedirectionToNonConst,
noLength,
templateFinalFieldNotInitialized,
templateFinalFieldNotInitializedByConstructor,
@@ -260,6 +261,7 @@
computeCoreTypes();
loader.computeHierarchy();
loader.performTopLevelInference(myClasses);
+ loader.checkSupertypes(myClasses);
loader.checkOverrides(myClasses);
loader.checkAbstractMembers(myClasses);
loader.addNoSuchMethodForwarders(myClasses);
@@ -656,6 +658,12 @@
bool isRedirecting = false;
for (Initializer initializer in constructor.initializers) {
if (initializer is RedirectingInitializer) {
+ if (constructor.isConst && !initializer.target.isConst) {
+ builder.addCompileTimeError(
+ messageConstConstructorRedirectionToNonConst,
+ initializer.fileOffset,
+ initializer.target.name.name.length);
+ }
isRedirecting = true;
break;
}
@@ -689,6 +697,7 @@
constructor.function.body = new EmptyStatement();
constructor.function.body.parent = constructor.function;
}
+
Set<Field> myInitializedFields = new Set<Field>();
for (Initializer initializer in constructor.initializers) {
if (initializer is FieldInitializer) {
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index 49bf6ab..6ed6457 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -296,6 +296,11 @@
}
@override
+ void beginMixinDeclaration(Token mixinKeyword, Token name) {
+ listener?.beginMixinDeclaration(mixinKeyword, name);
+ }
+
+ @override
void beginNamedFunctionExpression(Token token) {
listener?.beginNamedFunctionExpression(token);
}
@@ -732,6 +737,11 @@
}
@override
+ void endMixinDeclaration(Token token) {
+ listener?.endMixinDeclaration(token);
+ }
+
+ @override
void endNamedFunctionExpression(Token endToken) {
listener?.endNamedFunctionExpression(endToken);
}
@@ -1118,6 +1128,16 @@
}
@override
+ void handleMixinHeader(Token mixinKeyword) {
+ listener?.handleMixinHeader(mixinKeyword);
+ }
+
+ @override
+ void handleMixinOn(Token onKeyword, int typeCount) {
+ listener?.handleMixinOn(onKeyword, typeCount);
+ }
+
+ @override
void handleNamedArgument(Token colon) {
listener?.handleNamedArgument(colon);
}
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index 460fec9..83d9acd 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -240,6 +240,9 @@
/// expressions are required.
final bool allowedInConstantExpression;
+ /// Indicated whether the `isSynthetic` flag is required for the identifier.
+ final bool requiresSyntheticFlag;
+
final Template<_MessageWithArgument<Token>> recoveryTemplate;
const IdentifierContext(this._name,
@@ -249,6 +252,7 @@
this.isContinuation: false,
this.isScopeReference: false,
this.isBuiltInIdentifierAllowed: true,
+ this.requiresSyntheticFlag: false,
bool allowedInConstantExpression,
this.recoveryTemplate: templateExpectedIdentifier})
: this.allowedInConstantExpression =
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index 9814c3b..078f2d6 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -81,7 +81,8 @@
/// See [IdentifierContext.combinator].
class CombinatorIdentifierContext extends IdentifierContext {
- const CombinatorIdentifierContext() : super('combinator');
+ const CombinatorIdentifierContext()
+ : super('combinator', requiresSyntheticFlag: true);
@override
Token ensureIdentifier(Token token, Parser parser) {
@@ -154,10 +155,12 @@
/// See [IdentifierContext.dottedName].
class DottedNameIdentifierContext extends IdentifierContext {
- const DottedNameIdentifierContext() : super('dottedName');
+ const DottedNameIdentifierContext()
+ : super('dottedName', requiresSyntheticFlag: true);
const DottedNameIdentifierContext.continuation()
- : super('dottedNameContinuation', isContinuation: true);
+ : super('dottedNameContinuation',
+ isContinuation: true, requiresSyntheticFlag: true);
@override
Token ensureIdentifier(Token token, Parser parser) {
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index d4fa7d9..803363f 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -136,6 +136,32 @@
logEvent("ClassDeclaration");
}
+ /// Handle the beginning of a mixin declaration.
+ void beginMixinDeclaration(Token mixinKeyword, Token name) {}
+
+ /// Handle an on clause in a mixin declaration. Substructures:
+ /// - implemented types
+ void handleMixinOn(Token onKeyword, int typeCount) {
+ logEvent("MixinOn");
+ }
+
+ /// Handle the header of a class declaration. Substructures:
+ /// - metadata
+ /// - mixin name
+ /// - type variables
+ /// - on types
+ /// - implemented types
+ void handleMixinHeader(Token mixinKeyword) {
+ logEvent("MixinHeader");
+ }
+
+ /// Handle the end of a mixin declaration. Substructures:
+ /// - mixin header
+ /// - class or mixin body
+ void endMixinDeclaration(Token token) {
+ logEvent("MixinDeclaration");
+ }
+
void beginCombinators(Token token) {}
void endCombinators(int count) {
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 40b3b4e..1885d3b 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -256,6 +256,9 @@
bool mayParseFunctionExpressions = true;
+ // TODO(danrubel): remove this once mixin support is enabled by default.
+ bool isMixinSupportEnabled = false;
+
/// Represents parser state: what asynchronous syntax is allowed in the
/// function being currently parsed. In rare situations, this can be set by
/// external clients, for example, to parse an expression outside a function.
@@ -574,8 +577,17 @@
directiveState?.checkDeclaration();
return parseTopLevelMemberImpl(start);
} else {
+ // TODO(danrubel): Remove this once mixin support is enabled by default.
+ if (!isMixinSupportEnabled && identical(value, 'mixin')) {
+ directiveState?.checkDeclaration();
+ return parseTopLevelMemberImpl(start);
+ }
+
parseTopLevelKeywordModifiers(start, keyword);
- if (identical(value, 'typedef')) {
+ if (identical(value, 'mixin')) {
+ directiveState?.checkDeclaration();
+ return parseMixin(keyword);
+ } else if (identical(value, 'typedef')) {
directiveState?.checkDeclaration();
return parseTypedef(keyword);
} else if (identical(value, 'library')) {
@@ -1845,6 +1857,63 @@
return token;
}
+ /// Parse a mixin declaration.
+ ///
+ /// ```
+ /// mixinDeclaration:
+ /// metadata? 'mixin' [SimpleIdentifier] [TypeParameterList]?
+ /// [OnClause]? [ImplementsClause]? '{' [ClassMember]* '}'
+ /// ;
+ /// ```
+ Token parseMixin(Token mixinKeyword) {
+ assert(optional('mixin', mixinKeyword));
+ Token name = ensureIdentifier(
+ mixinKeyword, IdentifierContext.classOrMixinDeclaration);
+ Token token = computeTypeParamOrArg(name, true).parseVariables(name, this);
+ listener.beginMixinDeclaration(mixinKeyword, name);
+ token = parseMixinHeaderOpt(token, mixinKeyword);
+ if (!optional('{', token.next)) {
+ // Recovery
+ token = parseMixinHeaderRecovery(mixinKeyword);
+ ensureBlock(token, fasta.templateExpectedClassOrMixinBody);
+ }
+ token = parseClassOrMixinBody(token);
+ listener.endMixinDeclaration(token);
+ return token;
+ }
+
+ Token parseMixinHeaderOpt(Token token, Token mixinKeyword) {
+ token = parseMixinOnOpt(token);
+ token = parseClassOrMixinImplementsOpt(token);
+ listener.handleMixinHeader(mixinKeyword);
+ return token;
+ }
+
+ Token parseMixinHeaderRecovery(Token mixinKeyword) {
+ // TODO(danrubel): Add mixin recovery similiar to class recovery.
+ return mixinKeyword;
+ }
+
+ /// ```
+ /// onClause:
+ /// 'on' typeName (',' typeName)*
+ /// ;
+ /// ```
+ Token parseMixinOnOpt(Token token) {
+ Token onKeyword;
+ int typeCount = 0;
+ if (optional('on', token.next)) {
+ onKeyword = token.next;
+ do {
+ token =
+ computeType(token.next, true).ensureTypeNotVoid(token.next, this);
+ ++typeCount;
+ } while (optional(',', token.next));
+ }
+ listener.handleMixinOn(onKeyword, typeCount);
+ return token;
+ }
+
Token parseStringPart(Token token) {
Token next = token.next;
if (next.kind != STRING_TOKEN) {
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index fcab286..f4159f2 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -76,6 +76,11 @@
int importExportDirectiveIndex = 0;
int partDirectiveIndex = 0;
+ /// The unit currently being parsed, might be the same as [library] when
+ /// the defining unit of the library is being parsed, updated from outside
+ /// before parsing each part.
+ SourceLibraryBuilder currentUnit;
+
ClassBuilder currentClass;
/// For top-level declarations, this is the library scope. For class members,
@@ -121,7 +126,8 @@
Token partKeyword, Token ofKeyword, Token semicolon, bool hasName) {
debugEvent("PartOf");
if (hasName) discard(1);
- discard(1); // Metadata.
+ Token metadata = pop();
+ parseMetadata(currentUnit, metadata, currentUnit.target);
}
@override
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index d487929..6fc54ed 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -14,7 +14,7 @@
import '../builder/metadata_builder.dart' show ExpressionMetadataBuilder;
-import '../combinator.dart' show Combinator;
+import '../combinator.dart' show Combinator, CombinatorIdentifier;
import '../fasta_codes.dart'
show
@@ -113,12 +113,14 @@
int popCharOffset() => pop();
- List<String> popIdentifierList(int count) {
+ List<CombinatorIdentifier> popIdentifierList(int count) {
if (count == 0) return null;
- List<String> list = new List<String>.filled(count, null, growable: true);
+ var list = new List<CombinatorIdentifier>.filled(count, null);
for (int i = count - 1; i >= 0; i--) {
- popCharOffset();
- list[i] = pop();
+ bool isSynthetic = pop();
+ int offset = popCharOffset();
+ String name = pop();
+ list[i] = new CombinatorIdentifier(offset, name, isSynthetic);
}
return list;
}
@@ -177,15 +179,21 @@
@override
void endHide(Token hideKeyword) {
debugEvent("Hide");
- List<String> names = pop();
- push(new Combinator.hide(names, hideKeyword.charOffset, library.fileUri));
+ List<CombinatorIdentifier> identifiers = pop();
+ List<String> names =
+ identifiers.map((identifier) => identifier.name).toList();
+ push(new Combinator.hide(
+ identifiers, names, hideKeyword.charOffset, library.fileUri));
}
@override
void endShow(Token showKeyword) {
debugEvent("Show");
- List<String> names = pop();
- push(new Combinator.show(names, showKeyword.charOffset, library.fileUri));
+ List<CombinatorIdentifier> identifiers = pop();
+ List<String> names =
+ identifiers.map((identifier) => identifier.name).toList();
+ push(new Combinator.show(
+ identifiers, names, showKeyword.charOffset, library.fileUri));
}
@override
@@ -270,7 +278,9 @@
@override
void handleDottedName(int count, Token firstIdentifier) {
debugEvent("DottedName");
- push(popIdentifierList(count).join('.'));
+ push(popIdentifierList(count)
+ .map((identifier) => identifier.name)
+ .join('.'));
}
@override
@@ -319,6 +329,9 @@
super.handleIdentifier(token, context);
push(token.charOffset);
}
+ if (context.requiresSyntheticFlag) {
+ push(token.isSynthetic);
+ }
if (inConstructor && context == IdentifierContext.methodDeclaration) {
inConstructorName = true;
}
diff --git a/pkg/front_end/lib/src/fasta/source/outline_listener.dart b/pkg/front_end/lib/src/fasta/source/outline_listener.dart
index 4728332..0f77d6c 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_listener.dart
@@ -22,5 +22,8 @@
/// `List<int>` will have a reference to `List` and type `List<int>`, i.e.
/// with type arguments applied.
void store(int offset, bool isSynthetic,
- {int importIndex, Node reference, DartType type}) {}
+ {int importIndex,
+ bool isNamespaceCombinatorReference,
+ Node reference,
+ DartType type}) {}
}
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 e6a127e..75ee308 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
@@ -65,6 +65,8 @@
import '../problems.dart' show unhandled;
+import '../source/outline_listener.dart' show OutlineListener;
+
import 'source_loader.dart' show SourceLoader;
abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
@@ -113,6 +115,8 @@
bool canAddImplementationBuilders = false;
+ final OutlineListener outlineListener;
+
SourceLibraryBuilder(SourceLoader loader, Uri fileUri, Scope scope)
: this.fromScopes(loader, fileUri, new DeclarationBuilder<T>.library(),
scope ?? new Scope.top());
@@ -121,6 +125,7 @@
this.loader, this.fileUri, this.libraryDeclaration, this.importScope)
: disableTypeInference = loader.target.disableTypeInference,
currentDeclaration = libraryDeclaration,
+ outlineListener = loader.createOutlineListener(fileUri),
super(
fileUri, libraryDeclaration.toScope(importScope), new Scope.top());
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 638cd4d..cbe5078 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -45,6 +45,8 @@
NamedTypeBuilder,
TypeBuilder;
+import '../combinator.dart';
+
import '../deprecated_problems.dart' show deprecated_inputError;
import '../export.dart' show Export;
@@ -102,6 +104,8 @@
import 'outline_builder.dart' show OutlineBuilder;
+import 'outline_listener.dart' show OutlineListener;
+
import 'source_class_builder.dart' show SourceClassBuilder;
import 'source_library_builder.dart' show SourceLibraryBuilder;
@@ -209,9 +213,13 @@
// time we suppress lexical errors.
Token tokens = await tokenize(library, suppressLexicalErrors: true);
if (tokens == null) return;
+
DietListener listener = createDietListener(library);
DietParser parser = new DietParser(listener);
+
+ listener.currentUnit = library;
parser.parseUnit(tokens);
+
for (SourceLibraryBuilder part in library.parts) {
if (part.partOfLibrary != library) {
// Part was included in multiple libraries. Skip it here.
@@ -219,6 +227,7 @@
}
Token tokens = await tokenize(part);
if (tokens != null) {
+ listener.currentUnit = part;
listener.uri = part.fileUri;
listener.partDirectiveIndex = 0;
parser.parseUnit(tokens);
@@ -339,6 +348,21 @@
// and can lead to memory leaks.
exportee.exporters.clear();
}
+ for (var library in builders.values) {
+ if (library is SourceLibraryBuilder) {
+ OutlineListener outlineListener = library.outlineListener;
+ if (outlineListener != null) {
+ for (var import in library.imports) {
+ storeCombinatorIdentifiersResolution(
+ outlineListener, import.imported, import.combinators);
+ }
+ for (var export in library.exports) {
+ storeCombinatorIdentifiersResolution(
+ outlineListener, export.exported, export.combinators);
+ }
+ }
+ }
+ }
ticker.logMs("Computed library scopes");
// debugPrintExports();
}
@@ -702,6 +726,15 @@
ticker.logMs("Computed core types");
}
+ void checkSupertypes(List<SourceClassBuilder> sourceClasses) {
+ for (SourceClassBuilder builder in sourceClasses) {
+ if (builder.library.loader == this) {
+ builder.checkSupertypes(coreTypes);
+ }
+ }
+ ticker.logMs("Checked overrides");
+ }
+
void checkOverrides(List<SourceClassBuilder> sourceClasses) {
assert(hierarchy != null);
for (SourceClassBuilder builder in sourceClasses) {
@@ -939,4 +972,19 @@
hierarchy = null;
typeInferenceEngine = null;
}
+
+ void storeCombinatorIdentifiersResolution(OutlineListener outlineListener,
+ LibraryBuilder consumed, List<Combinator> combinators) {
+ if (combinators != null) {
+ for (var combinator in combinators) {
+ for (var identifier in combinator.identifiers) {
+ var declaration = consumed.exportScope.local[identifier.name];
+ declaration ??= consumed.exportScope.setters[identifier.name];
+ outlineListener.store(identifier.offset, identifier.isSynthetic,
+ isNamespaceCombinatorReference: true,
+ reference: declaration?.target);
+ }
+ }
+ }
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
index 3bd22e4..b3c28bb 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_listener.dart
@@ -643,6 +643,7 @@
void propertyAssign(
ExpressionJudgment judgment,
Location location,
+ bool isSyntheticLhs,
DartType receiverType,
Reference writeMember,
DartType writeContext,
@@ -1060,8 +1061,15 @@
NullLiteralTokens tokens, bool isSynthetic, DartType inferredType) {}
@override
- void propertyAssign(ExpressionJudgment judgment, location, receiverType,
- writeMember, DartType writeContext, combiner, DartType inferredType) {}
+ void propertyAssign(
+ ExpressionJudgment judgment,
+ location,
+ bool isSyntheticLhs,
+ receiverType,
+ writeMember,
+ DartType writeContext,
+ combiner,
+ DartType inferredType) {}
@override
void propertyGet(ExpressionJudgment judgment, location,
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 c53cd10..b8113fe 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
@@ -191,8 +191,6 @@
final bool _needToInferReturnType;
- final bool _needImplicitDowncasts;
-
/// The type that actually appeared as the subexpression of `return` or
/// `yield` statements inside the function.
///
@@ -204,12 +202,9 @@
/// wrapping this type in `Stream` or `Iterator`, as appropriate.
DartType _inferredUnwrappedReturnOrYieldType;
- factory ClosureContext(
- TypeInferrerImpl inferrer,
- AsyncMarker asyncMarker,
- DartType returnContext,
- bool needToInferReturnType,
- bool needImplicitDowncasts) {
+ factory ClosureContext(TypeInferrerImpl inferrer, AsyncMarker asyncMarker,
+ DartType returnContext, bool needToInferReturnType) {
+ assert(returnContext != null);
DartType declaredReturnType = returnContext;
bool isAsync = asyncMarker == AsyncMarker.Async ||
asyncMarker == AsyncMarker.AsyncStar;
@@ -228,41 +223,77 @@
inferrer.typeSchemaEnvironment.unfutureType(returnContext));
}
return new ClosureContext._(isAsync, isGenerator, returnContext,
- declaredReturnType, needToInferReturnType, needImplicitDowncasts);
+ declaredReturnType, needToInferReturnType);
}
- ClosureContext._(
- this.isAsync,
- this.isGenerator,
- this.returnOrYieldContext,
- this.declaredReturnType,
- this._needToInferReturnType,
- this._needImplicitDowncasts) {
- assert(returnOrYieldContext != null);
- }
+ ClosureContext._(this.isAsync, this.isGenerator, this.returnOrYieldContext,
+ this.declaredReturnType, this._needToInferReturnType) {}
/// Updates the inferred return type based on the presence of a return
/// statement returning the given [type].
void handleReturn(TypeInferrerImpl inferrer, DartType type,
Expression expression, int fileOffset, bool isArrow) {
if (isGenerator) return;
- _updateInferredReturnType(
- inferrer, type, expression, fileOffset, true, false, isArrow);
+ if (inferrer.ensureAssignable(
+ returnOrYieldContext, type, expression, fileOffset,
+ isReturnFromAsync: isAsync,
+ isReturn: true,
+ declaredReturnType: declaredReturnType,
+ isArrow: isArrow) !=
+ null) {
+ type = greatestClosure(inferrer.coreTypes, returnOrYieldContext);
+ }
+ if (_needToInferReturnType) {
+ var unwrappedType = type;
+ if (isAsync) {
+ unwrappedType = inferrer.typeSchemaEnvironment.unfutureType(type);
+ }
+ if (_inferredUnwrappedReturnOrYieldType == null) {
+ _inferredUnwrappedReturnOrYieldType = unwrappedType;
+ } else {
+ _inferredUnwrappedReturnOrYieldType = inferrer.typeSchemaEnvironment
+ .getStandardUpperBound(
+ _inferredUnwrappedReturnOrYieldType, unwrappedType);
+ }
+ }
}
void handleYield(TypeInferrerImpl inferrer, bool isYieldStar, DartType type,
Expression expression, int fileOffset) {
if (!isGenerator) return;
- _updateInferredReturnType(
- inferrer, type, expression, fileOffset, false, isYieldStar, false);
+ var expectedType = isYieldStar
+ ? _wrapAsyncOrGenerator(inferrer, returnOrYieldContext)
+ : returnOrYieldContext;
+ if (inferrer.ensureAssignable(expectedType, type, expression, fileOffset,
+ isReturnFromAsync: isAsync) !=
+ null) {
+ type = greatestClosure(inferrer.coreTypes, expectedType);
+ }
+ if (_needToInferReturnType) {
+ var unwrappedType = type;
+ if (isYieldStar) {
+ unwrappedType = inferrer.getDerivedTypeArgumentOf(
+ type,
+ isAsync
+ ? inferrer.coreTypes.streamClass
+ : inferrer.coreTypes.iterableClass) ??
+ type;
+ }
+ if (_inferredUnwrappedReturnOrYieldType == null) {
+ _inferredUnwrappedReturnOrYieldType = unwrappedType;
+ } else {
+ _inferredUnwrappedReturnOrYieldType = inferrer.typeSchemaEnvironment
+ .getStandardUpperBound(
+ _inferredUnwrappedReturnOrYieldType, unwrappedType);
+ }
+ }
}
DartType inferReturnType(TypeInferrerImpl inferrer) {
assert(_needToInferReturnType);
DartType inferredType =
inferrer.inferReturnType(_inferredUnwrappedReturnOrYieldType);
- if (returnOrYieldContext != null &&
- !_analyzerSubtypeOf(inferrer, inferredType, returnOrYieldContext)) {
+ if (!_analyzerSubtypeOf(inferrer, inferredType, returnOrYieldContext)) {
// If the inferred return type isn't a subtype of the context, we use the
// context.
inferredType = greatestClosure(inferrer.coreTypes, returnOrYieldContext);
@@ -271,53 +302,6 @@
return _wrapAsyncOrGenerator(inferrer, inferredType);
}
- void _updateInferredReturnType(
- TypeInferrerImpl inferrer,
- DartType type,
- Expression expression,
- int fileOffset,
- bool isReturn,
- bool isYieldStar,
- bool isArrow) {
- if (_needImplicitDowncasts) {
- var expectedType = isYieldStar
- ? _wrapAsyncOrGenerator(inferrer, returnOrYieldContext)
- : returnOrYieldContext;
- if (expectedType != null) {
- expectedType = greatestClosure(inferrer.coreTypes, expectedType);
- if (inferrer.ensureAssignable(
- expectedType, type, expression, fileOffset,
- isReturnFromAsync: isAsync,
- isReturn: isReturn,
- declaredReturnType: declaredReturnType,
- isArrow: isArrow) !=
- null) {
- type = expectedType;
- }
- }
- }
- var unwrappedType = type;
- if (isAsync && isReturn) {
- unwrappedType = inferrer.typeSchemaEnvironment.unfutureType(type);
- } else if (isYieldStar) {
- unwrappedType = inferrer.getDerivedTypeArgumentOf(
- type,
- isAsync
- ? inferrer.coreTypes.streamClass
- : inferrer.coreTypes.iterableClass) ??
- type;
- }
- if (_needToInferReturnType) {
- if (_inferredUnwrappedReturnOrYieldType == null) {
- _inferredUnwrappedReturnOrYieldType = unwrappedType;
- } else {
- _inferredUnwrappedReturnOrYieldType = inferrer.typeSchemaEnvironment
- .getLeastUpperBound(
- _inferredUnwrappedReturnOrYieldType, unwrappedType);
- }
- }
- }
-
DartType _wrapAsyncOrGenerator(TypeInferrerImpl inferrer, DartType type) {
if (isGenerator) {
if (isAsync) {
@@ -1255,8 +1239,7 @@
Statement body) {
assert(closureContext == null);
this.helper = helper;
- closureContext =
- new ClosureContext(this, asyncMarker, returnType, false, true);
+ closureContext = new ClosureContext(this, asyncMarker, returnType, false);
inferStatement(body);
closureContext = null;
this.helper = null;
@@ -1561,13 +1544,8 @@
// to `xi` in `B` having type `Pi`. This produces `B’`.
bool needToSetReturnType = hasImplicitReturnType && strongMode;
ClosureContext oldClosureContext = this.closureContext;
- bool needImplicitDowncasts = returnContext != null;
ClosureContext closureContext = new ClosureContext(
- this,
- function.asyncMarker,
- returnContext,
- needToSetReturnType,
- needImplicitDowncasts);
+ this, function.asyncMarker, returnContext, needToSetReturnType);
this.closureContext = closureContext;
inferStatement(function.body);
@@ -1978,13 +1956,14 @@
return new InterfaceType(class_, <DartType>[type ?? const DynamicType()]);
}
- void _forEachArgument(
- Arguments arguments, void callback(String name, Expression expression)) {
+ void _forEachArgument(ArgumentsJudgment arguments,
+ void callback(String name, Expression expression)) {
for (var expression in arguments.positional) {
callback(null, expression);
}
- for (var namedExpression in arguments.named) {
- callback(namedExpression.name, namedExpression.value);
+ for (var namedExpression in arguments.namedJudgments) {
+ callback(namedExpression.name,
+ namedExpression.originalValue ?? namedExpression.value);
}
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
index 5577ced..8b5aac7 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
@@ -94,25 +94,29 @@
/// Modify the given [constraint]'s lower bound to include [lower].
void addLowerBound(TypeConstraint constraint, DartType lower) {
- constraint.lower = getLeastUpperBound(constraint.lower, lower);
+ constraint.lower = getStandardUpperBound(constraint.lower, lower);
}
/// Modify the given [constraint]'s upper bound to include [upper].
void addUpperBound(TypeConstraint constraint, DartType upper) {
- constraint.upper = getGreatestLowerBound(constraint.upper, upper);
+ constraint.upper = getStandardLowerBound(constraint.upper, upper);
}
- /// Computes the greatest lower bound of [type1] and [type2].
- DartType getGreatestLowerBound(DartType type1, DartType type2) {
- // The greatest lower bound relation is reflexive. Note that we don't test
- // for equality because we don't want to make the algorithm quadratic. This
- // is ok because the check is not needed for correctness; it's just a speed
+ /// Computes the standard lower bound of [type1] and [type2].
+ ///
+ /// Standard lower bound is a lower bound function that imposes an
+ /// ordering on the top types `void`, `dynamic`, and `object`. This function
+ /// additionally handles the unknown type that appears during type inference.
+ DartType getStandardLowerBound(DartType type1, DartType type2) {
+ // For all types T, SLB(T,T) = T. Note that we don't test for equality
+ // because we don't want to make the algorithm quadratic. This is ok
+ // because the check is not needed for correctness; it's just a speed
// optimization.
if (identical(type1, type2)) {
return type1;
}
- // For any type T, GLB(?, T) == T.
+ // For any type T, SLB(?, T) = SLB(T, ?) = T.
if (type1 is UnknownType) {
return type2;
}
@@ -120,22 +124,45 @@
return type1;
}
- // The GLB of top and any type is just that type.
- // Also GLB of bottom and any type is bottom.
- if (isTop(type1) || isBottom(type2)) {
+ // SLB(void, T) = SLB(T, void) = T.
+ if (type1 is VoidType) {
return type2;
}
- if (isTop(type2) || isBottom(type1)) {
+ if (type2 is VoidType) {
return type1;
}
- // Function types have structural GLB.
- if (type1 is FunctionType && type2 is FunctionType) {
- return _functionGreatestLowerBound(type1, type2);
+ // SLB(dynamic, T) = SLB(T, dynamic) = T if T is not void.
+ if (type1 is DynamicType) {
+ return type2;
+ }
+ if (type2 is DynamicType) {
+ return type1;
}
- // Otherwise, the GLB of two types is one of them it if it is a subtype of
- // the other.
+ // SLB(Object, T) = SLB(T, Object) = T if T is not void or dynamic.
+ if (type1 == objectType) {
+ return type2;
+ }
+ if (type2 == objectType) {
+ return type1;
+ }
+
+ // SLB(bottom, T) = SLB(T, bottom) = bottom.
+ if (isBottom(type1)) {
+ return type1;
+ }
+ if (isBottom(type2)) {
+ return type2;
+ }
+
+ // Function types have structural lower bounds.
+ if (type1 is FunctionType && type2 is FunctionType) {
+ return _functionStandardLowerBound(type1, type2);
+ }
+
+ // Otherwise, the lower bounds of two types is one of them it if it is a
+ // subtype of the other.
if (isSubtypeOf(type1, type2)) {
return type1;
}
@@ -144,21 +171,25 @@
return type2;
}
- // No subtype relation, so no known GLB.
+ // No subtype relation, so the lower bound is bottom.
return const BottomType();
}
- /// Compute the least upper bound of two types.
- DartType getLeastUpperBound(DartType type1, DartType type2) {
- // The least upper bound relation is reflexive. Note that we don't test
- // for equality because we don't want to make the algorithm quadratic. This
- // is ok because the check is not needed for correctness; it's just a speed
+ /// Computes the standard upper bound of two types.
+ ///
+ /// Standard upper bound is an upper bound function that imposes an ordering
+ /// on the top types 'void', 'dynamic', and `object`. This function
+ /// additionally handles the unknown type that appears during type inference.
+ DartType getStandardUpperBound(DartType type1, DartType type2) {
+ // For all types T, SUB(T,T) = T. Note that we don't test for equality
+ // because we don't want to make the algorithm quadratic. This is ok
+ // because the check is not needed for correctness; it's just a speed
// optimization.
if (identical(type1, type2)) {
return type1;
}
- // For any type T, LUB(?, T) == T.
+ // For any type T, SUB(?, T) = SUB(T, ?) = T.
if (type1 is UnknownType) {
return type2;
}
@@ -166,29 +197,44 @@
return type1;
}
- // The least upper bound of void and any type T != dynamic is void.
+ // SUB(void, T) = SUB(T, void) = void.
if (type1 is VoidType) {
- return type2 is DynamicType ? type2 : type1;
- }
- if (type2 is VoidType) {
- return type1 is DynamicType ? type1 : type2;
- }
-
- // The least upper bound of top and any type T is top.
- // The least upper bound of bottom and any type T is T.
- if (isTop(type1) || isBottom(type2)) {
return type1;
}
- if (isTop(type2) || isBottom(type1)) {
+ if (type2 is VoidType) {
return type2;
}
- if (type1 is TypeParameterType || type2 is TypeParameterType) {
- return _typeParameterLeastUpperBound(type1, type2);
+ // SUB(dynamic, T) = SUB(T, dynamic) = dynamic if T is not void.
+ if (type1 is DynamicType) {
+ return type1;
+ }
+ if (type2 is DynamicType) {
+ return type2;
}
- // The least upper bound of a function type and an interface type T is the
- // least upper bound of Function and T.
+ // SUB(Obect, T) = SUB(T, Object) = Object if T is not void or dynamic.
+ if (type1 == objectType) {
+ return type1;
+ }
+ if (type2 == objectType) {
+ return type2;
+ }
+
+ // SUB(bottom, T) = SUB(T, bottom) = T.
+ if (isBottom(type1)) {
+ return type2;
+ }
+ if (isBottom(type2)) {
+ return type1;
+ }
+
+ if (type1 is TypeParameterType || type2 is TypeParameterType) {
+ return _typeParameterStandardUpperBound(type1, type2);
+ }
+
+ // The standard upper bound of a function type and an interface type T is
+ // the standard upper bound of Function and T.
if (type1 is FunctionType && type2 is InterfaceType) {
type1 = rawFunctionType;
}
@@ -199,11 +245,11 @@
// At this point type1 and type2 should both either be interface types or
// function types.
if (type1 is InterfaceType && type2 is InterfaceType) {
- return _interfaceLeastUpperBound(type1, type2);
+ return _interfaceStandardUpperBound(type1, type2);
}
if (type1 is FunctionType && type2 is FunctionType) {
- return _functionLeastUpperBound(type1, type2);
+ return _functionStandardUpperBound(type1, type2);
}
// Should never happen. As a defensive measure, return the dynamic type.
@@ -327,9 +373,9 @@
var typeParamBound = typeParam.bound;
DartType extendsConstraint;
if (!hasOmittedBound(typeParam)) {
- extendsConstraint = Substitution
- .fromPairs(typeParametersToInfer, inferredTypes)
- .substituteType(typeParamBound);
+ extendsConstraint =
+ Substitution.fromPairs(typeParametersToInfer, inferredTypes)
+ .substituteType(typeParamBound);
}
var constraint = constraints[typeParam];
@@ -353,9 +399,9 @@
for (int i = 0; i < typeParametersToInfer.length; i++) {
TypeParameter typeParam = typeParametersToInfer[i];
var constraint = constraints[typeParam];
- var typeParamBound = Substitution
- .fromPairs(typeParametersToInfer, inferredTypes)
- .substituteType(typeParam.bound);
+ var typeParamBound =
+ Substitution.fromPairs(typeParametersToInfer, inferredTypes)
+ .substituteType(typeParam.bound);
var inferred = inferredTypes[i];
bool success = typeSatisfiesConstraint(inferred, constraint);
@@ -460,9 +506,9 @@
isSubtypeOf(type, constraint.upper);
}
- /// Compute the greatest lower bound of function types [f] and [g].
+ /// Compute the standard lower bound of function types [f] and [g].
///
- /// The spec rules for GLB on function types, informally, are pretty simple:
+ /// The spec rules for SLB on function types, informally, are pretty simple:
///
/// - If a parameter is required in both, it stays required.
///
@@ -473,15 +519,15 @@
///
/// - Named parameters are unioned together.
///
- /// - For any parameter that exists in both functions, use the LUB of them as
+ /// - For any parameter that exists in both functions, use the SUB of them as
/// the resulting parameter type.
///
- /// - Use the GLB of their return types.
- DartType _functionGreatestLowerBound(FunctionType f, FunctionType g) {
+ /// - Use the SLB of their return types.
+ DartType _functionStandardLowerBound(FunctionType f, FunctionType g) {
// TODO(rnystrom,paulberry): Right now, this assumes f and g do not have any
// type parameters. Revisit that in the presence of generic methods.
- // Calculate the LUB of each corresponding pair of parameters.
+ // Calculate the SUB of each corresponding pair of parameters.
int totalPositional =
math.max(f.positionalParameters.length, g.positionalParameters.length);
var positionalParameters = new List<DartType>(totalPositional);
@@ -490,7 +536,7 @@
var fType = f.positionalParameters[i];
if (i < g.positionalParameters.length) {
var gType = g.positionalParameters[i];
- positionalParameters[i] = getLeastUpperBound(fType, gType);
+ positionalParameters[i] = getStandardUpperBound(fType, gType);
} else {
positionalParameters[i] = fType;
}
@@ -524,7 +570,7 @@
} else {
namedParameters.add(new NamedType(
fName,
- getLeastUpperBound(f.namedParameters[i++].type,
+ getStandardUpperBound(f.namedParameters[i++].type,
g.namedParameters[j++].type)));
}
} else {
@@ -543,16 +589,16 @@
// and named parameters. If we would synthesize that, give up.
if (hasPositional && hasNamed) return const BottomType();
- // Calculate the GLB of the return type.
- DartType returnType = getGreatestLowerBound(f.returnType, g.returnType);
+ // Calculate the SLB of the return type.
+ DartType returnType = getStandardLowerBound(f.returnType, g.returnType);
return new FunctionType(positionalParameters, returnType,
namedParameters: namedParameters,
requiredParameterCount: requiredParameterCount);
}
- /// Compute the least upper bound of function types [f] and [g].
+ /// Compute the standard upper bound of function types [f] and [g].
///
- /// The rules for LUB on function types, informally, are pretty simple:
+ /// The rules for SUB on function types, informally, are pretty simple:
///
/// - If the functions don't have the same number of required parameters,
/// always return `Function`.
@@ -560,29 +606,29 @@
/// - Discard any optional named or positional parameters the two types do not
/// have in common.
///
- /// - Compute the GLB of each corresponding pair of parameter types, and the
- /// LUB of the return types. Return a function type with those types.
- DartType _functionLeastUpperBound(FunctionType f, FunctionType g) {
+ /// - Compute the SLB of each corresponding pair of parameter types, and the
+ /// SUB of the return types. Return a function type with those types.
+ DartType _functionStandardUpperBound(FunctionType f, FunctionType g) {
// TODO(rnystrom): Right now, this assumes f and g do not have any type
// parameters. Revisit that in the presence of generic methods.
// If F and G differ in their number of required parameters, then the
- // least upper bound of F and G is Function.
+ // standard upper bound of F and G is Function.
// TODO(paulberry): We could do better here, e.g.:
- // LUB(([int]) -> void, (int) -> void) = (int) -> void
+ // SUB(([int]) -> void, (int) -> void) = (int) -> void
if (f.requiredParameterCount != g.requiredParameterCount) {
return coreTypes.functionClass.rawType;
}
int requiredParameterCount = f.requiredParameterCount;
- // Calculate the GLB of each corresponding pair of parameters.
+ // Calculate the SLB of each corresponding pair of parameters.
// Ignore any extra optional positional parameters if one has more than the
// other.
int totalPositional =
math.min(f.positionalParameters.length, g.positionalParameters.length);
var positionalParameters = new List<DartType>(totalPositional);
for (int i = 0; i < totalPositional; i++) {
- positionalParameters[i] = getGreatestLowerBound(
+ positionalParameters[i] = getStandardLowerBound(
f.positionalParameters[i], g.positionalParameters[i]);
}
@@ -604,7 +650,7 @@
} else {
namedParameters.add(new NamedType(
fName,
- getGreatestLowerBound(f.namedParameters[i++].type,
+ getStandardLowerBound(f.namedParameters[i++].type,
g.namedParameters[j++].type)));
}
} else {
@@ -616,8 +662,8 @@
}
}
- // Calculate the LUB of the return type.
- DartType returnType = getLeastUpperBound(f.returnType, g.returnType);
+ // Calculate the SUB of the return type.
+ DartType returnType = getStandardUpperBound(f.returnType, g.returnType);
return new FunctionType(positionalParameters, returnType,
namedParameters: namedParameters,
requiredParameterCount: requiredParameterCount);
@@ -661,20 +707,21 @@
return t;
}
- DartType _interfaceLeastUpperBound(InterfaceType type1, InterfaceType type2) {
- // This currently does not implement a very complete least upper bound
+ DartType _interfaceStandardUpperBound(
+ InterfaceType type1, InterfaceType type2) {
+ // This currently does not implement a very complete standard upper bound
// algorithm, but handles a couple of the very common cases that are
// causing pain in real code. The current algorithm is:
// 1. If either of the types is a supertype of the other, return it.
// This is in fact the best result in this case.
// 2. If the two types have the same class element, then take the
- // pointwise least upper bound of the type arguments. This is again
+ // pointwise standard upper bound of the type arguments. This is again
// the best result, except that the recursive calls may not return
- // the true least upper bounds. The result is guaranteed to be a
+ // the true standard upper bounds. The result is guaranteed to be a
// well-formed type under the assumption that the input types were
// well-formed (and assuming that the recursive calls return
// well-formed types).
- // 3. Otherwise return the spec-defined least upper bound. This will
+ // 3. Otherwise return the spec-defined standard upper bound. This will
// be an upper bound, might (or might not) be least, and might
// (or might not) be a well-formed type.
if (isSubtypeOf(type1, type2)) {
@@ -692,24 +739,24 @@
assert(tArgs1.length == tArgs2.length);
List<DartType> tArgs = new List(tArgs1.length);
for (int i = 0; i < tArgs1.length; i++) {
- tArgs[i] = getLeastUpperBound(tArgs1[i], tArgs2[i]);
+ tArgs[i] = getStandardUpperBound(tArgs1[i], tArgs2[i]);
}
return new InterfaceType(type1.classNode, tArgs);
}
return hierarchy.getClassicLeastUpperBound(type1, type2);
}
- DartType _typeParameterLeastUpperBound(DartType type1, DartType type2) {
- // This currently just implements a simple least upper bound to
+ DartType _typeParameterStandardUpperBound(DartType type1, DartType type2) {
+ // This currently just implements a simple standard upper bound to
// handle some common cases. It also avoids some termination issues
- // with the naive spec algorithm. The least upper bound of two types
+ // with the naive spec algorithm. The standard upper bound of two types
// (at least one of which is a type parameter) is computed here as:
// 1. If either type is a supertype of the other, return it.
// 2. If the first type is a type parameter, replace it with its bound,
// with recursive occurrences of itself replaced with Object.
// The second part of this should ensure termination. Informally,
// each type variable instantiation in one of the arguments to the
- // least upper bound algorithm now strictly reduces the number
+ // standard upper bound algorithm now strictly reduces the number
// of bound variables in scope in that argument position.
// 3. If the second type is a type parameter, do the symmetric operation
// to #2.
@@ -742,15 +789,15 @@
// TODO(paulberry): Analyzer collapses simple bounds in one step, i.e. for
// C<T extends U, U extends List>, T gets resolved directly to List. Do
// we need to replicate that behavior?
- return getLeastUpperBound(
- Substitution.fromMap({type1.parameter: objectType}).substituteType(
- type1.parameter.bound),
+ return getStandardUpperBound(
+ Substitution.fromMap({type1.parameter: objectType})
+ .substituteType(type1.parameter.bound),
type2);
} else if (type2 is TypeParameterType) {
- return getLeastUpperBound(
+ return getStandardUpperBound(
type1,
- Substitution.fromMap({type2.parameter: objectType}).substituteType(
- type2.parameter.bound));
+ Substitution.fromMap({type2.parameter: objectType})
+ .substituteType(type2.parameter.bound));
} else {
// We should only be called when at least one of the types is a
// TypeParameterType
diff --git a/pkg/front_end/lib/src/scanner/scanner.dart b/pkg/front_end/lib/src/scanner/scanner.dart
deleted file mode 100644
index 26e2f29..0000000
--- a/pkg/front_end/lib/src/scanner/scanner.dart
+++ /dev/null
@@ -1,1337 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:charcode/ascii.dart';
-
-import 'errors.dart';
-import 'reader.dart';
-import 'string_utilities.dart';
-import 'token.dart';
-
-/**
- * A state in a state machine used to scan keywords.
- */
-class KeywordState {
- /**
- * An empty transition table used by leaf states.
- */
- static List<KeywordState> _EMPTY_TABLE = new List<KeywordState>($z - $A + 1);
-
- /**
- * The initial state in the state machine.
- */
- static final KeywordState KEYWORD_STATE = _createKeywordStateTable();
-
- /**
- * A table mapping characters to the states to which those characters will
- * transition. (The index into the array is the offset from the character
- * `'a'` to the transitioning character.)
- */
- final List<KeywordState> _table;
-
- /**
- * The keyword that is recognized by this state, or `null` if this state is
- * not a terminal state.
- */
- Keyword _keyword;
-
- /**
- * Initialize a newly created state to have the given transitions and to
- * recognize the keyword with the given [syntax].
- */
- KeywordState(this._table, String syntax) {
- this._keyword = (syntax == null) ? null : Keyword.keywords[syntax];
- }
-
- /**
- * Return the keyword that was recognized by this state, or `null` if this
- * state does not recognized a keyword.
- */
- Keyword keyword() => _keyword;
-
- /**
- * Return the state that follows this state on a transition of the given
- * [character], or `null` if there is no valid state reachable from this state
- * with such a transition.
- */
- KeywordState next(int character) => _table[character - $A];
-
- /**
- * Create the next state in the state machine where we have already recognized
- * the subset of strings in the given array of [strings] starting at the given
- * [offset] and having the given [length]. All of these strings have a common
- * prefix and the next character is at the given [start] index.
- */
- static KeywordState _computeKeywordStateTable(
- int start, List<String> strings, int offset, int length) {
- List<KeywordState> result = new List<KeywordState>($z - $A + 1);
- assert(length != 0);
- int chunk = $nul;
- int chunkStart = -1;
- bool isLeaf = false;
- for (int i = offset; i < offset + length; i++) {
- if (strings[i].length == start) {
- isLeaf = true;
- }
- if (strings[i].length > start) {
- int c = strings[i].codeUnitAt(start);
- if (chunk != c) {
- if (chunkStart != -1) {
- result[chunk - $A] = _computeKeywordStateTable(
- start + 1, strings, chunkStart, i - chunkStart);
- }
- chunkStart = i;
- chunk = c;
- }
- }
- }
- if (chunkStart != -1) {
- assert(result[chunk - $A] == null);
- result[chunk - $A] = _computeKeywordStateTable(
- start + 1, strings, chunkStart, offset + length - chunkStart);
- } else {
- assert(length == 1);
- return new KeywordState(_EMPTY_TABLE, strings[offset]);
- }
- if (isLeaf) {
- return new KeywordState(result, strings[offset]);
- } else {
- return new KeywordState(result, null);
- }
- }
-
- /**
- * Create and return the initial state in the state machine.
- */
- static KeywordState _createKeywordStateTable() {
- List<Keyword> values = Keyword.values;
- List<String> strings = new List<String>(values.length);
- for (int i = 0; i < values.length; i++) {
- strings[i] = values[i].lexeme;
- }
- strings.sort();
- return _computeKeywordStateTable(0, strings, 0, strings.length);
- }
-}
-
-/**
- * The class `Scanner` implements a scanner for Dart code.
- *
- * The lexical structure of Dart is ambiguous without knowledge of the context
- * in which a token is being scanned. For example, without context we cannot
- * determine whether source of the form "<<" should be scanned as a single
- * left-shift operator or as two left angle brackets. This scanner does not have
- * any context, so it always resolves such conflicts by scanning the longest
- * possible token.
- */
-abstract class Scanner {
- /**
- * The reader used to access the characters in the source.
- */
- final CharacterReader _reader;
-
- /**
- * The flag specifying whether documentation comments should be parsed.
- */
- bool _preserveComments = true;
-
- /**
- * The token pointing to the head of the linked list of tokens.
- */
- Token _tokens;
-
- /**
- * The last token that was scanned.
- */
- Token _tail;
-
- /**
- * The first token in the list of comment tokens found since the last
- * non-comment token.
- */
- Token _firstComment;
-
- /**
- * The last token in the list of comment tokens found since the last
- * non-comment token.
- */
- Token _lastComment;
-
- /**
- * The index of the first character of the current token.
- */
- int _tokenStart = 0;
-
- /**
- * A list containing the offsets of the first character of each line in the
- * source code.
- */
- List<int> _lineStarts = new List<int>();
-
- /**
- * A list, treated something like a stack, of tokens representing the
- * beginning of a matched pair. It is used to pair the end tokens with the
- * begin tokens.
- */
- List<BeginToken> _groupingStack = new List<BeginToken>();
-
- /**
- * The index of the last item in the [_groupingStack], or `-1` if the stack is
- * empty.
- */
- int _stackEnd = -1;
-
- /**
- * A flag indicating whether any unmatched groups were found during the parse.
- */
- bool _hasUnmatchedGroups = false;
-
- /**
- * A flag indicating whether to parse generic method comments, of the form
- * `/*=T*/` and `/*<T>*/`.
- */
- bool scanGenericMethodComments = false;
-
- /**
- * A flag indicating whether the lazy compound assignment operators '&&=' and
- * '||=' are enabled.
- */
- bool scanLazyAssignmentOperators = false;
-
- /**
- * Initialize a newly created scanner to scan characters from the given
- * character [_reader].
- */
- Scanner.create(this._reader) {
- _tokens = new Token.eof(-1);
- _tail = _tokens;
- _tokenStart = -1;
- _lineStarts.add(0);
- }
-
- /**
- * Return the first token in the token stream that was scanned.
- */
- Token get firstToken => _tokens.next;
-
- /**
- * Return `true` if any unmatched groups were found during the parse.
- */
- bool get hasUnmatchedGroups => _hasUnmatchedGroups;
-
- /**
- * Return an array containing the offsets of the first character of each line
- * in the source code.
- */
- List<int> get lineStarts => _lineStarts;
-
- /**
- * Set whether documentation tokens should be preserved.
- */
- void set preserveComments(bool preserveComments) {
- this._preserveComments = preserveComments;
- }
-
- /**
- * Return the last token that was scanned.
- */
- Token get tail => _tail;
-
- /**
- * Append the given [token] to the end of the token stream being scanned. This
- * method is intended to be used by subclasses that copy existing tokens and
- * should not normally be used because it will fail to correctly associate any
- * comments with the token being passed in.
- */
- void appendToken(Token token) {
- _tail = _tail.setNext(token);
- }
-
- int bigSwitch(int next) {
- _beginToken();
- if (next == $cr) {
- // '\r'
- next = _reader.advance();
- if (next == $lf) {
- // '\n'
- next = _reader.advance();
- }
- recordStartOfLine();
- return next;
- } else if (next == $lf) {
- // '\n'
- next = _reader.advance();
- recordStartOfLine();
- return next;
- } else if (next == $tab || next == $space) {
- // '\t' || ' '
- return _reader.advance();
- }
- if (next == $r) {
- // 'r'
- int peek = _reader.peek();
- if (peek == $double_quote || peek == $single_quote) {
- // '"' || "'"
- int start = _reader.offset;
- return _tokenizeString(_reader.advance(), start, true);
- }
- }
- if (($A <= next && next <= $Z) || ($a <= next && next <= $z)) {
- // 'A'-'Z' || 'a'-'z'
- return _tokenizeKeywordOrIdentifier(next, true);
- }
- if (next == $_ || next == $$) {
- // '_' || '$'
- return _tokenizeIdentifier(next, _reader.offset, true);
- }
- if (next == $lt) {
- // '<'
- return _tokenizeLessThan(next);
- }
- if (next == $gt) {
- // '>'
- return _tokenizeGreaterThan(next);
- }
- if (next == $equal) {
- // '='
- return _tokenizeEquals(next);
- }
- if (next == $exclamation) {
- // '!'
- return _tokenizeExclamation(next);
- }
- if (next == $plus) {
- // '+'
- return _tokenizePlus(next);
- }
- if (next == $minus) {
- // '-'
- return _tokenizeMinus(next);
- }
- if (next == $asterisk) {
- // '*'
- return _tokenizeMultiply(next);
- }
- if (next == $percent) {
- // '%'
- return _tokenizePercent(next);
- }
- if (next == $ampersand) {
- // '&'
- return _tokenizeAmpersand(next);
- }
- if (next == $bar) {
- // '|'
- return _tokenizeBar(next);
- }
- if (next == $caret) {
- // '^'
- return _tokenizeCaret(next);
- }
- if (next == $open_bracket) {
- // '['
- return _tokenizeOpenSquareBracket(next);
- }
- if (next == $tilde) {
- // '~'
- return _tokenizeTilde(next);
- }
- if (next == $backslash) {
- // '\\'
- _appendTokenOfType(TokenType.BACKSLASH);
- return _reader.advance();
- }
- if (next == $hash) {
- // '#'
- return _tokenizeTag(next);
- }
- if (next == $open_paren) {
- // '('
- _appendBeginToken(TokenType.OPEN_PAREN);
- return _reader.advance();
- }
- if (next == $close_paren) {
- // ')'
- _appendEndToken(TokenType.CLOSE_PAREN, TokenType.OPEN_PAREN);
- return _reader.advance();
- }
- if (next == $comma) {
- // ','
- _appendTokenOfType(TokenType.COMMA);
- return _reader.advance();
- }
- if (next == $colon) {
- // ':'
- _appendTokenOfType(TokenType.COLON);
- return _reader.advance();
- }
- if (next == $semicolon) {
- // ';'
- _appendTokenOfType(TokenType.SEMICOLON);
- return _reader.advance();
- }
- if (next == $question) {
- // '?'
- return _tokenizeQuestion();
- }
- if (next == $close_bracket) {
- // ']'
- _appendEndToken(
- TokenType.CLOSE_SQUARE_BRACKET, TokenType.OPEN_SQUARE_BRACKET);
- return _reader.advance();
- }
- if (next == $backquote) {
- // '`'
- _appendTokenOfType(TokenType.BACKPING);
- return _reader.advance();
- }
- if (next == $lbrace) {
- // '{'
- _appendBeginToken(TokenType.OPEN_CURLY_BRACKET);
- return _reader.advance();
- }
- if (next == $rbrace) {
- // '}'
- _appendEndToken(
- TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
- return _reader.advance();
- }
- if (next == $slash) {
- // '/'
- return _tokenizeSlashOrComment(next);
- }
- if (next == $at) {
- // '@'
- _appendTokenOfType(TokenType.AT);
- return _reader.advance();
- }
- if (next == $double_quote || next == $single_quote) {
- // '"' || "'"
- return _tokenizeString(next, _reader.offset, false);
- }
- if (next == $dot) {
- // '.'
- return _tokenizeDotOrNumber(next);
- }
- if (next == $0) {
- // '0'
- return _tokenizeHexOrNumber(next);
- }
- if ($1 <= next && next <= $9) {
- // '1'-'9'
- return _tokenizeNumber(next);
- }
- if (next == -1) {
- // EOF
- return -1;
- }
- _reportError(ScannerErrorCode.ILLEGAL_CHARACTER, [next]);
- return _reader.advance();
- }
-
- /**
- * Record the fact that we are at the beginning of a new line in the source.
- */
- void recordStartOfLine() {
- _lineStarts.add(_reader.offset);
- }
-
- /**
- * Report an error at the given offset. The [errorCode] is the error code
- * indicating the nature of the error. The [arguments] are any arguments
- * needed to complete the error message
- */
- void reportError(
- ScannerErrorCode errorCode, int offset, List<Object> arguments);
-
- /**
- * Record that the source begins on the given [line] and [column] at the
- * current offset as given by the reader. Both the line and the column are
- * one-based indexes. The line starts for lines before the given line will not
- * be correct.
- *
- * This method must be invoked at most one time and must be invoked before
- * scanning begins. The values provided must be sensible. The results are
- * undefined if these conditions are violated.
- */
- void setSourceStart(int line, int column) {
- int offset = _reader.offset;
- if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
- return;
- }
- for (int i = 2; i < line; i++) {
- _lineStarts.add(1);
- }
- _lineStarts.add(offset - column + 1);
- }
-
- /**
- * Scan the source code to produce a list of tokens representing the source,
- * and return the first token in the list of tokens that were produced.
- */
- Token tokenize() {
- int next = _reader.advance();
- while (next != -1) {
- next = bigSwitch(next);
- }
- _appendEofToken();
- return firstToken;
- }
-
- void _appendBeginToken(TokenType type) {
- BeginToken token;
- if (_firstComment == null) {
- token = new BeginToken(type, _tokenStart);
- } else {
- token = new BeginToken(type, _tokenStart, _firstComment);
- _firstComment = null;
- _lastComment = null;
- }
- _tail = _tail.setNext(token);
- _groupingStack.add(token);
- _stackEnd++;
- }
-
- void _appendCommentToken(TokenType type, String value) {
- CommentToken token = null;
- TokenType genericComment = _matchGenericMethodCommentType(value);
- if (genericComment != null) {
- token = new CommentToken(genericComment, value, _tokenStart);
- } else if (!_preserveComments) {
- // Ignore comment tokens if client specified that it doesn't need them.
- return;
- } else {
- // OK, remember comment tokens.
- if (_isDocumentationComment(value)) {
- token = new DocumentationCommentToken(type, value, _tokenStart);
- } else {
- token = new CommentToken(type, value, _tokenStart);
- }
- }
- if (_firstComment == null) {
- _firstComment = token;
- _lastComment = _firstComment;
- } else {
- _lastComment = _lastComment.setNext(token);
- }
- }
-
- void _appendEndToken(TokenType type, TokenType beginType) {
- Token token;
- if (_firstComment == null) {
- token = new Token(type, _tokenStart);
- } else {
- token = new Token(type, _tokenStart, _firstComment);
- _firstComment = null;
- _lastComment = null;
- }
- _tail = _tail.setNext(token);
- if (_stackEnd >= 0) {
- BeginToken begin = _groupingStack[_stackEnd];
- if (begin.type == beginType) {
- begin.endToken = token;
- _groupingStack.removeAt(_stackEnd--);
- }
- }
- }
-
- void _appendEofToken() {
- Token eofToken;
- if (_firstComment == null) {
- eofToken = new Token.eof(_reader.offset + 1);
- } else {
- eofToken = new Token.eof(_reader.offset + 1, _firstComment);
- _firstComment = null;
- _lastComment = null;
- }
- // The EOF token points to itself so that there is always infinite
- // look-ahead.
- eofToken.setNext(eofToken);
- _tail = _tail.setNext(eofToken);
- if (_stackEnd >= 0) {
- _hasUnmatchedGroups = true;
- // TODO(brianwilkerson): Fix the ungrouped tokens?
- }
- }
-
- void _appendKeywordToken(Keyword keyword) {
- if (_firstComment == null) {
- _tail = _tail.setNext(new KeywordToken(keyword, _tokenStart));
- } else {
- _tail =
- _tail.setNext(new KeywordToken(keyword, _tokenStart, _firstComment));
- _firstComment = null;
- _lastComment = null;
- }
- }
-
- void _appendStringToken(TokenType type, String value) {
- if (_firstComment == null) {
- _tail = _tail.setNext(new StringToken(type, value, _tokenStart));
- } else {
- _tail = _tail
- .setNext(new StringToken(type, value, _tokenStart, _firstComment));
- _firstComment = null;
- _lastComment = null;
- }
- }
-
- void _appendStringTokenWithOffset(TokenType type, String value, int offset) {
- if (_firstComment == null) {
- _tail = _tail.setNext(new StringToken(type, value, _tokenStart + offset));
- } else {
- _tail = _tail.setNext(
- new StringToken(type, value, _tokenStart + offset, _firstComment));
- _firstComment = null;
- _lastComment = null;
- }
- }
-
- void _appendTokenOfType(TokenType type) {
- if (_firstComment == null) {
- _tail = _tail.setNext(new Token(type, _tokenStart));
- } else {
- _tail = _tail.setNext(new Token(type, _tokenStart, _firstComment));
- _firstComment = null;
- _lastComment = null;
- }
- }
-
- void _appendTokenOfTypeWithOffset(TokenType type, int offset) {
- if (_firstComment == null) {
- _tail = _tail.setNext(new Token(type, offset));
- } else {
- _tail = _tail.setNext(new Token(type, offset, _firstComment));
- _firstComment = null;
- _lastComment = null;
- }
- }
-
- void _beginToken() {
- _tokenStart = _reader.offset;
- }
-
- /**
- * Return the beginning token corresponding to a closing brace that was found
- * while scanning inside a string interpolation expression. Tokens that cannot
- * be matched with the closing brace will be dropped from the stack.
- */
- BeginToken _findTokenMatchingClosingBraceInInterpolationExpression() {
- while (_stackEnd >= 0) {
- BeginToken begin = _groupingStack[_stackEnd];
- if (begin.type == TokenType.OPEN_CURLY_BRACKET ||
- begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
- return begin;
- }
- _hasUnmatchedGroups = true;
- _groupingStack.removeAt(_stackEnd--);
- }
- //
- // We should never get to this point because we wouldn't be inside a string
- // interpolation expression unless we had previously found the start of the
- // expression.
- //
- return null;
- }
-
- /**
- * Checks if [value] is the start of a generic method type annotation comment.
- *
- * This can either be of the form `/*<T>*/` or `/*=T*/`. The token type is
- * returned, or null if it was not a generic method comment.
- */
- TokenType _matchGenericMethodCommentType(String value) {
- if (scanGenericMethodComments) {
- // Match /*< and >*/
- if (StringUtilities.startsWith3(value, 0, $slash, $asterisk, $lt) &&
- StringUtilities.endsWith3(value, $gt, $asterisk, $slash)) {
- return TokenType.GENERIC_METHOD_TYPE_LIST;
- }
- // Match /*=
- if (StringUtilities.startsWith3(value, 0, $slash, $asterisk, $equal)) {
- return TokenType.GENERIC_METHOD_TYPE_ASSIGN;
- }
- }
- return null;
- }
-
- /**
- * Report an error at the current offset. The [errorCode] is the error code
- * indicating the nature of the error. The [arguments] are any arguments
- * needed to complete the error message
- */
- void _reportError(ScannerErrorCode errorCode, [List<Object> arguments]) {
- reportError(errorCode, _reader.offset, arguments);
- }
-
- int _select(int choice, TokenType yesType, TokenType noType) {
- int next = _reader.advance();
- if (next == choice) {
- _appendTokenOfType(yesType);
- return _reader.advance();
- } else {
- _appendTokenOfType(noType);
- return next;
- }
- }
-
- int _selectWithOffset(
- int choice, TokenType yesType, TokenType noType, int offset) {
- int next = _reader.advance();
- if (next == choice) {
- _appendTokenOfTypeWithOffset(yesType, offset);
- return _reader.advance();
- } else {
- _appendTokenOfTypeWithOffset(noType, offset);
- return next;
- }
- }
-
- int _tokenizeAmpersand(int next) {
- // &&= && &= &
- next = _reader.advance();
- if (next == $ampersand) {
- next = _reader.advance();
- if (scanLazyAssignmentOperators && next == $equal) {
- _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND_EQ);
- return _reader.advance();
- }
- _appendTokenOfType(TokenType.AMPERSAND_AMPERSAND);
- return next;
- } else if (next == $equal) {
- _appendTokenOfType(TokenType.AMPERSAND_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.AMPERSAND);
- return next;
- }
- }
-
- int _tokenizeBar(int next) {
- // ||= || |= |
- next = _reader.advance();
- if (next == $bar) {
- next = _reader.advance();
- if (scanLazyAssignmentOperators && next == $equal) {
- _appendTokenOfType(TokenType.BAR_BAR_EQ);
- return _reader.advance();
- }
- _appendTokenOfType(TokenType.BAR_BAR);
- return next;
- } else if (next == $equal) {
- _appendTokenOfType(TokenType.BAR_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.BAR);
- return next;
- }
- }
-
- int _tokenizeCaret(int next) =>
- _select($equal, TokenType.CARET_EQ, TokenType.CARET);
-
- int _tokenizeDotOrNumber(int next) {
- int start = _reader.offset;
- next = _reader.advance();
- if ($0 <= next && next <= $9) {
- return _tokenizeFractionPart(next, start);
- } else if ($dot == next) {
- return _select(
- $dot, TokenType.PERIOD_PERIOD_PERIOD, TokenType.PERIOD_PERIOD);
- } else {
- _appendTokenOfType(TokenType.PERIOD);
- return next;
- }
- }
-
- int _tokenizeEquals(int next) {
- // = == =>
- next = _reader.advance();
- if (next == $equal) {
- _appendTokenOfType(TokenType.EQ_EQ);
- return _reader.advance();
- } else if (next == $gt) {
- _appendTokenOfType(TokenType.FUNCTION);
- return _reader.advance();
- }
- _appendTokenOfType(TokenType.EQ);
- return next;
- }
-
- int _tokenizeExclamation(int next) {
- // ! !=
- next = _reader.advance();
- if (next == $equal) {
- _appendTokenOfType(TokenType.BANG_EQ);
- return _reader.advance();
- }
- _appendTokenOfType(TokenType.BANG);
- return next;
- }
-
- int _tokenizeExponent(int next) {
- if (next == $plus || next == $minus) {
- next = _reader.advance();
- }
- bool hasDigits = false;
- while (true) {
- if ($0 <= next && next <= $9) {
- hasDigits = true;
- } else {
- if (!hasDigits) {
- _reportError(ScannerErrorCode.MISSING_DIGIT);
- }
- return next;
- }
- next = _reader.advance();
- }
- }
-
- int _tokenizeFractionPart(int next, int start) {
- bool done = false;
- bool hasDigit = false;
- LOOP:
- while (!done) {
- if ($0 <= next && next <= $9) {
- hasDigit = true;
- } else if ($e == next || $E == next) {
- hasDigit = true;
- next = _tokenizeExponent(_reader.advance());
- done = true;
- continue LOOP;
- } else {
- done = true;
- continue LOOP;
- }
- next = _reader.advance();
- }
- if (!hasDigit) {
- _appendStringToken(TokenType.INT, _reader.getString(start, -2));
- if ($dot == next) {
- return _selectWithOffset($dot, TokenType.PERIOD_PERIOD_PERIOD,
- TokenType.PERIOD_PERIOD, _reader.offset - 1);
- }
- _appendTokenOfTypeWithOffset(TokenType.PERIOD, _reader.offset - 1);
- return bigSwitch(next);
- }
- _appendStringToken(
- TokenType.DOUBLE, _reader.getString(start, next < 0 ? 0 : -1));
- return next;
- }
-
- int _tokenizeGreaterThan(int next) {
- // > >= >> >>=
- next = _reader.advance();
- if ($equal == next) {
- _appendTokenOfType(TokenType.GT_EQ);
- return _reader.advance();
- } else if ($gt == next) {
- next = _reader.advance();
- if ($equal == next) {
- _appendTokenOfType(TokenType.GT_GT_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.GT_GT);
- return next;
- }
- } else {
- _appendTokenOfType(TokenType.GT);
- return next;
- }
- }
-
- int _tokenizeHex(int next) {
- int start = _reader.offset - 1;
- bool hasDigits = false;
- while (true) {
- next = _reader.advance();
- if (($0 <= next && next <= $9) ||
- ($A <= next && next <= $F) ||
- ($a <= next && next <= $f)) {
- hasDigits = true;
- } else {
- if (!hasDigits) {
- _reportError(ScannerErrorCode.MISSING_HEX_DIGIT);
- }
- _appendStringToken(
- TokenType.HEXADECIMAL, _reader.getString(start, next < 0 ? 0 : -1));
- return next;
- }
- }
- }
-
- int _tokenizeHexOrNumber(int next) {
- int x = _reader.peek();
- if (x == $x || x == $X) {
- _reader.advance();
- return _tokenizeHex(x);
- }
- return _tokenizeNumber(next);
- }
-
- int _tokenizeIdentifier(int next, int start, bool allowDollar) {
- while (($a <= next && next <= $z) ||
- ($A <= next && next <= $Z) ||
- ($0 <= next && next <= $9) ||
- next == $_ ||
- (next == $$ && allowDollar)) {
- next = _reader.advance();
- }
- _appendStringToken(
- TokenType.IDENTIFIER, _reader.getString(start, next < 0 ? 0 : -1));
- return next;
- }
-
- int _tokenizeInterpolatedExpression(int next, int start) {
- _appendBeginToken(TokenType.STRING_INTERPOLATION_EXPRESSION);
- next = _reader.advance();
- while (next != -1) {
- if (next == $rbrace) {
- BeginToken begin =
- _findTokenMatchingClosingBraceInInterpolationExpression();
- if (begin == null) {
- _beginToken();
- _appendTokenOfType(TokenType.CLOSE_CURLY_BRACKET);
- next = _reader.advance();
- _beginToken();
- return next;
- } else if (begin.type == TokenType.OPEN_CURLY_BRACKET) {
- _beginToken();
- _appendEndToken(
- TokenType.CLOSE_CURLY_BRACKET, TokenType.OPEN_CURLY_BRACKET);
- next = _reader.advance();
- _beginToken();
- } else if (begin.type == TokenType.STRING_INTERPOLATION_EXPRESSION) {
- _beginToken();
- _appendEndToken(TokenType.CLOSE_CURLY_BRACKET,
- TokenType.STRING_INTERPOLATION_EXPRESSION);
- next = _reader.advance();
- _beginToken();
- return next;
- }
- } else {
- next = bigSwitch(next);
- }
- }
- return next;
- }
-
- int _tokenizeInterpolatedIdentifier(int next, int start) {
- _appendStringTokenWithOffset(
- TokenType.STRING_INTERPOLATION_IDENTIFIER, "\$", 0);
- if (($A <= next && next <= $Z) ||
- ($a <= next && next <= $z) ||
- next == $_) {
- _beginToken();
- next = _tokenizeKeywordOrIdentifier(next, false);
- }
- _beginToken();
- return next;
- }
-
- int _tokenizeKeywordOrIdentifier(int next, bool allowDollar) {
- KeywordState state = KeywordState.KEYWORD_STATE;
- int start = _reader.offset;
- while (state != null &&
- (($A <= next && next <= $Z) || $a <= next && next <= $z)) {
- state = state.next(next);
- next = _reader.advance();
- }
- if (state == null || state.keyword() == null) {
- return _tokenizeIdentifier(next, start, allowDollar);
- }
- if (($0 <= next && next <= $9) || next == $_ || next == $$) {
- return _tokenizeIdentifier(next, start, allowDollar);
- } else if (next < 128) {
- _appendKeywordToken(state.keyword());
- return next;
- } else {
- return _tokenizeIdentifier(next, start, allowDollar);
- }
- }
-
- int _tokenizeLessThan(int next) {
- // < <= << <<=
- next = _reader.advance();
- if ($equal == next) {
- _appendTokenOfType(TokenType.LT_EQ);
- return _reader.advance();
- } else if ($lt == next) {
- return _select($equal, TokenType.LT_LT_EQ, TokenType.LT_LT);
- } else {
- _appendTokenOfType(TokenType.LT);
- return next;
- }
- }
-
- int _tokenizeMinus(int next) {
- // - -- -=
- next = _reader.advance();
- if (next == $minus) {
- _appendTokenOfType(TokenType.MINUS_MINUS);
- return _reader.advance();
- } else if (next == $equal) {
- _appendTokenOfType(TokenType.MINUS_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.MINUS);
- return next;
- }
- }
-
- int _tokenizeMultiLineComment(int next) {
- int nesting = 1;
- next = _reader.advance();
- while (true) {
- if (-1 == next) {
- _reportError(ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT);
- _appendCommentToken(
- TokenType.MULTI_LINE_COMMENT, _reader.getString(_tokenStart, 0));
- return next;
- } else if ($asterisk == next) {
- next = _reader.advance();
- if ($slash == next) {
- --nesting;
- if (0 == nesting) {
- _appendCommentToken(TokenType.MULTI_LINE_COMMENT,
- _reader.getString(_tokenStart, 0));
- return _reader.advance();
- } else {
- next = _reader.advance();
- }
- }
- } else if ($slash == next) {
- next = _reader.advance();
- if ($asterisk == next) {
- next = _reader.advance();
- ++nesting;
- }
- } else if (next == $cr) {
- next = _reader.advance();
- if (next == $lf) {
- next = _reader.advance();
- }
- recordStartOfLine();
- } else if (next == $lf) {
- next = _reader.advance();
- recordStartOfLine();
- } else {
- next = _reader.advance();
- }
- }
- }
-
- int _tokenizeMultiLineRawString(int quoteChar, int start) {
- int next = _reader.advance();
- outer:
- while (next != -1) {
- while (next != quoteChar) {
- if (next == -1) {
- break outer;
- } else if (next == $cr) {
- next = _reader.advance();
- if (next == $lf) {
- next = _reader.advance();
- }
- recordStartOfLine();
- } else if (next == $lf) {
- next = _reader.advance();
- recordStartOfLine();
- } else {
- next = _reader.advance();
- }
- }
- next = _reader.advance();
- if (next == quoteChar) {
- next = _reader.advance();
- if (next == quoteChar) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- }
- }
- }
- _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- }
-
- int _tokenizeMultiLineString(int quoteChar, int start, bool raw) {
- if (raw) {
- return _tokenizeMultiLineRawString(quoteChar, start);
- }
- int next = _reader.advance();
- while (next != -1) {
- if (next == $$) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
- next = _tokenizeStringInterpolation(start);
- _beginToken();
- start = _reader.offset;
- continue;
- }
- if (next == quoteChar) {
- next = _reader.advance();
- if (next == quoteChar) {
- next = _reader.advance();
- if (next == quoteChar) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- }
- }
- continue;
- }
- if (next == $backslash) {
- next = _reader.advance();
- if (next == -1) {
- break;
- }
- if (next == $cr) {
- next = _reader.advance();
- if (next == $lf) {
- next = _reader.advance();
- }
- recordStartOfLine();
- } else if (next == $lf) {
- recordStartOfLine();
- next = _reader.advance();
- } else {
- next = _reader.advance();
- }
- } else if (next == $cr) {
- next = _reader.advance();
- if (next == $lf) {
- next = _reader.advance();
- }
- recordStartOfLine();
- } else if (next == $lf) {
- recordStartOfLine();
- next = _reader.advance();
- } else {
- next = _reader.advance();
- }
- }
- _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
- if (start == _reader.offset) {
- _appendStringTokenWithOffset(TokenType.STRING, "", 1);
- } else {
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- }
- return _reader.advance();
- }
-
- int _tokenizeMultiply(int next) =>
- _select($equal, TokenType.STAR_EQ, TokenType.STAR);
-
- int _tokenizeNumber(int next) {
- int start = _reader.offset;
- while (true) {
- next = _reader.advance();
- if ($0 <= next && next <= $9) {
- continue;
- } else if (next == $dot) {
- return _tokenizeFractionPart(_reader.advance(), start);
- } else if (next == $e || next == $E) {
- return _tokenizeFractionPart(next, start);
- } else {
- _appendStringToken(
- TokenType.INT, _reader.getString(start, next < 0 ? 0 : -1));
- return next;
- }
- }
- }
-
- int _tokenizeOpenSquareBracket(int next) {
- // [ [] []=
- next = _reader.advance();
- if (next == $close_bracket) {
- return _select($equal, TokenType.INDEX_EQ, TokenType.INDEX);
- } else {
- _appendBeginToken(TokenType.OPEN_SQUARE_BRACKET);
- return next;
- }
- }
-
- int _tokenizePercent(int next) =>
- _select($equal, TokenType.PERCENT_EQ, TokenType.PERCENT);
-
- int _tokenizePlus(int next) {
- // + ++ +=
- next = _reader.advance();
- if ($plus == next) {
- _appendTokenOfType(TokenType.PLUS_PLUS);
- return _reader.advance();
- } else if ($equal == next) {
- _appendTokenOfType(TokenType.PLUS_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.PLUS);
- return next;
- }
- }
-
- int _tokenizeQuestion() {
- // ? ?. ?? ??=
- int next = _reader.advance();
- if (next == $dot) {
- // '.'
- _appendTokenOfType(TokenType.QUESTION_PERIOD);
- return _reader.advance();
- } else if (next == $question) {
- // '?'
- next = _reader.advance();
- if (next == $equal) {
- // '='
- _appendTokenOfType(TokenType.QUESTION_QUESTION_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.QUESTION_QUESTION);
- return next;
- }
- } else {
- _appendTokenOfType(TokenType.QUESTION);
- return next;
- }
- }
-
- int _tokenizeSingleLineComment(int next) {
- while (true) {
- next = _reader.advance();
- if (-1 == next) {
- _appendCommentToken(
- TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, 0));
- return next;
- } else if ($lf == next || $cr == next) {
- _appendCommentToken(
- TokenType.SINGLE_LINE_COMMENT, _reader.getString(_tokenStart, -1));
- return next;
- }
- }
- }
-
- int _tokenizeSingleLineRawString(int next, int quoteChar, int start) {
- next = _reader.advance();
- while (next != -1) {
- if (next == quoteChar) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- } else if (next == $cr || next == $lf) {
- _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
- _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
- return _reader.advance();
- }
- next = _reader.advance();
- }
- _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- }
-
- int _tokenizeSingleLineString(int next, int quoteChar, int start) {
- while (next != quoteChar) {
- if (next == $backslash) {
- next = _reader.advance();
- } else if (next == $$) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
- next = _tokenizeStringInterpolation(start);
- _beginToken();
- start = _reader.offset;
- continue;
- }
- if (next <= $cr && (next == $lf || next == $cr || next == -1)) {
- _reportError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL);
- if (start == _reader.offset) {
- _appendStringTokenWithOffset(TokenType.STRING, "", 1);
- } else if (next == -1) {
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- } else {
- _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
- }
- return _reader.advance();
- }
- next = _reader.advance();
- }
- _appendStringToken(TokenType.STRING, _reader.getString(start, 0));
- return _reader.advance();
- }
-
- int _tokenizeSlashOrComment(int next) {
- next = _reader.advance();
- if ($asterisk == next) {
- return _tokenizeMultiLineComment(next);
- } else if ($slash == next) {
- return _tokenizeSingleLineComment(next);
- } else if ($equal == next) {
- _appendTokenOfType(TokenType.SLASH_EQ);
- return _reader.advance();
- } else {
- _appendTokenOfType(TokenType.SLASH);
- return next;
- }
- }
-
- int _tokenizeString(int next, int start, bool raw) {
- int quoteChar = next;
- next = _reader.advance();
- if (quoteChar == next) {
- next = _reader.advance();
- if (quoteChar == next) {
- // Multiline string.
- return _tokenizeMultiLineString(quoteChar, start, raw);
- } else {
- // Empty string.
- _appendStringToken(TokenType.STRING, _reader.getString(start, -1));
- return next;
- }
- }
- if (raw) {
- return _tokenizeSingleLineRawString(next, quoteChar, start);
- } else {
- return _tokenizeSingleLineString(next, quoteChar, start);
- }
- }
-
- int _tokenizeStringInterpolation(int start) {
- _beginToken();
- int next = _reader.advance();
- if (next == $lbrace) {
- return _tokenizeInterpolatedExpression(next, start);
- } else {
- return _tokenizeInterpolatedIdentifier(next, start);
- }
- }
-
- int _tokenizeTag(int next) {
- // # or #!.*[\n\r]
- if (_reader.offset == 0) {
- if (_reader.peek() == $exclamation) {
- do {
- next = _reader.advance();
- } while (next != $lf && next != $cr && next > 0);
- _appendStringToken(
- TokenType.SCRIPT_TAG, _reader.getString(_tokenStart, 0));
- return next;
- }
- }
- _appendTokenOfType(TokenType.HASH);
- return _reader.advance();
- }
-
- int _tokenizeTilde(int next) {
- // ~ ~/ ~/=
- next = _reader.advance();
- if (next == $slash) {
- return _select($equal, TokenType.TILDE_SLASH_EQ, TokenType.TILDE_SLASH);
- } else {
- _appendTokenOfType(TokenType.TILDE);
- return next;
- }
- }
-
- /**
- * Checks if [value] is a single-line or multi-line comment.
- */
- static bool _isDocumentationComment(String value) {
- return StringUtilities.startsWith3(value, 0, $slash, $slash, $slash) ||
- StringUtilities.startsWith3(value, 0, $slash, $asterisk, $asterisk);
- }
-}
diff --git a/pkg/front_end/lib/src/scanner/string_utilities.dart b/pkg/front_end/lib/src/scanner/string_utilities.dart
index 2398978b..3b5540b 100644
--- a/pkg/front_end/lib/src/scanner/string_utilities.dart
+++ b/pkg/front_end/lib/src/scanner/string_utilities.dart
@@ -7,20 +7,5 @@
class StringUtilities {
static Interner INTERNER = new NullInterner();
- static bool endsWith3(String str, int c1, int c2, int c3) {
- var length = str.length;
- return length >= 3 &&
- str.codeUnitAt(length - 3) == c1 &&
- str.codeUnitAt(length - 2) == c2 &&
- str.codeUnitAt(length - 1) == c3;
- }
-
static String intern(String string) => INTERNER.intern(string);
-
- static bool startsWith3(String str, int start, int c1, int c2, int c3) {
- return str.length - start >= 3 &&
- str.codeUnitAt(start) == c1 &&
- str.codeUnitAt(start + 1) == c2 &&
- str.codeUnitAt(start + 2) == c3;
- }
}
diff --git a/pkg/front_end/lib/src/scanner/token.dart b/pkg/front_end/lib/src/scanner/token.dart
index e9e0fee..7015f5c 100644
--- a/pkg/front_end/lib/src/scanner/token.dart
+++ b/pkg/front_end/lib/src/scanner/token.dart
@@ -214,7 +214,8 @@
static const Keyword LIBRARY = const Keyword("library", "LIBRARY",
isBuiltIn: true, isTopLevelKeyword: true);
- static const Keyword MIXIN = const Keyword("mixin", "MIXIN", isBuiltIn: true);
+ static const Keyword MIXIN =
+ const Keyword("mixin", "MIXIN", isBuiltIn: true, isTopLevelKeyword: true);
static const Keyword NATIVE =
const Keyword("native", "NATIVE", isPseudo: true);
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 2b6a9a5..0c4ff07 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -52,6 +52,7 @@
ConstAndVar/script1: Fail
ConstConstructorInSubclassOfMixinApplication/example: Fail
ConstConstructorNonFinalField/example: Fail
+ConstConstructorRedirectionToNonConst/analyzerCode: Fail # The analyzer doesn't report this error.
ConstConstructorWithNonConstSuper/example: Fail
ConstEvalContext/analyzerCode: Fail # This is just used for displaying the context.
ConstEvalContext/example: Fail # This is just used for displaying the context.
@@ -194,6 +195,7 @@
IllegalSyncGeneratorVoidReturnType/analyzerCode: Fail # The analyzer doesn't report this error.
ImplementsBeforeExtends/script: Fail
ImplementsBeforeWith/script: Fail
+ImplementsFutureOr/analyzerCode: Fail # The analyzer doesn't report this error.
ImplicitCallOfNonMethod/example: Fail
ImportAfterPart/script1: Fail
InitializerForStaticField/example: Fail
@@ -323,7 +325,6 @@
StackOverflow/example: Fail
StaticAfterConst/script1: Fail
SuperAsExpression/example: Fail
-SuperAsIdentifier/analyzerCode: Fail
SuperAsIdentifier/example: Fail
SuperNullAware/example: Fail
SuperclassHasNoDefaultConstructor/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index e240cc0..b428d444 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -303,6 +303,27 @@
dart2jsCode: "*ignored*"
script: "class A extends B implements C with D {}"
+ImplementsRepeated:
+ template: "'#name' can only be implemented once."
+ analyzerCode: IMPLEMENTS_REPEATED
+ dart2jsCode: "*fatal*"
+ tip: "Try removing #count of the occurrences."
+ script:
+ - >-
+ abstract class I {}
+ abstract class J {}
+ class K implements I, J, I {}
+
+ImplementsSuperClass:
+ template: "'#name' can't be used in both 'extends' and 'implements' clauses."
+ analyzerCode: IMPLEMENTS_SUPER_CLASS
+ dart2jsCode: "*fatal*"
+ tip: "Try removing one of the occurrences."
+ script:
+ - >-
+ abstract class A {}
+ class C extends A implements A {}
+
MultipleImplements:
template: "Each class definition can have at most one implements clause."
tip: "Try combining all of the implements clauses into a single clause."
@@ -310,6 +331,15 @@
dart2jsCode: "GENERIC"
script: "class A implements B implements C, D {}"
+ImplementsFutureOr:
+ template: "'FutureOr' can't be used in an 'implements' clause."
+ severity: ERROR
+ dart2jsCode: "*fatal*"
+ script:
+ - >-
+ import 'dart:async';
+ class A implements FutureOr<int> {}
+
ExpectedClassOrMixinBody:
template: "Expected a class or mixin body, but got '#lexeme'."
analyzerCode: MISSING_CLASS_BODY
@@ -2341,6 +2371,8 @@
SuperAsIdentifier:
template: "Expected identifier, but got 'super'."
+ analyzerCode: SUPER_AS_EXPRESSION
+ dart2jsCode: "*fatal*"
SuperAsExpression:
template: "Can't use 'super' as an expression."
@@ -2432,6 +2464,17 @@
analyzerCode: CONST_CONSTRUCTOR_IN_SUBCLASS_OF_MIXIN_APPLICATION
dart2jsCode: "*fatal*"
+ConstConstructorRedirectionToNonConst:
+ template: "A constant constructor can't call a non-constant constructor."
+ severity: ERROR
+ dart2jsCode: "*fatal*"
+ script:
+ - >-
+ class A {
+ const A.foo() : this.bar();
+ A.bar() {}
+ }
+
AccessError:
template: "Access error: '#name'."
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
index 4621b9a..cddd384 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
@@ -94,8 +94,8 @@
void test_glb_bottom() {
var A = _addClass(_class('A')).rawType;
var env = _makeEnv();
- expect(env.getGreatestLowerBound(bottomType, A), same(bottomType));
- expect(env.getGreatestLowerBound(A, bottomType), same(bottomType));
+ expect(env.getStandardLowerBound(bottomType, A), same(bottomType));
+ expect(env.getStandardLowerBound(A, bottomType), same(bottomType));
}
void test_glb_function() {
@@ -105,30 +105,30 @@
var env = _makeEnv();
// GLB(() -> A, () -> B) = () -> B
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([], A), new FunctionType([], B)),
new FunctionType([], B));
// GLB(() -> void, (A, B) -> void) = ([A, B]) -> void
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([], voidType), new FunctionType([A, B], voidType)),
new FunctionType([A, B], voidType, requiredParameterCount: 0));
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([A, B], voidType), new FunctionType([], voidType)),
new FunctionType([A, B], voidType, requiredParameterCount: 0));
// GLB((A) -> void, (B) -> void) = (A) -> void
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([A], voidType), new FunctionType([B], voidType)),
new FunctionType([A], voidType));
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([B], voidType), new FunctionType([A], voidType)),
new FunctionType([A], voidType));
// GLB(({a: A}) -> void, ({b: B}) -> void) = ({a: A, b: B}) -> void
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([], voidType,
namedParameters: [new NamedType('a', A)]),
new FunctionType([], voidType,
@@ -136,7 +136,7 @@
new FunctionType([], voidType,
namedParameters: [new NamedType('a', A), new NamedType('b', B)]));
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([], voidType,
namedParameters: [new NamedType('b', B)]),
new FunctionType([], voidType,
@@ -146,7 +146,7 @@
// GLB(({a: A, c: A}) -> void, ({b: B, d: B}) -> void)
// = ({a: A, b: B, c: A, d: B}) -> void
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([], voidType,
namedParameters: [
new NamedType('a', A),
@@ -167,7 +167,7 @@
// GLB(({a: A, b: B}) -> void, ({a: B, b: A}) -> void)
// = ({a: A, b: A}) -> void
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([], voidType,
namedParameters: [
new NamedType('a', A),
@@ -181,7 +181,7 @@
new FunctionType([], voidType,
namedParameters: [new NamedType('a', A), new NamedType('b', A)]));
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([], voidType,
namedParameters: [
new NamedType('a', B),
@@ -196,7 +196,7 @@
namedParameters: [new NamedType('a', A), new NamedType('b', A)]));
// GLB((B, {a: A}) -> void, (B) -> void) = (B, {a: A}) -> void
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([B], voidType,
namedParameters: [new NamedType('a', A)]),
new FunctionType([B], voidType)),
@@ -204,14 +204,14 @@
namedParameters: [new NamedType('a', A)]));
// GLB(({a: A}) -> void, (B) -> void) = bottom
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([], voidType,
namedParameters: [new NamedType('a', A)]),
new FunctionType([B], voidType)),
same(bottomType));
// GLB(({a: A}) -> void, ([B]) -> void) = bottom
expect(
- env.getGreatestLowerBound(
+ env.getStandardLowerBound(
new FunctionType([], voidType,
namedParameters: [new NamedType('a', A)]),
new FunctionType([B], voidType, requiredParameterCount: 0)),
@@ -221,8 +221,8 @@
void test_glb_identical() {
var A = _addClass(_class('A')).rawType;
var env = _makeEnv();
- expect(env.getGreatestLowerBound(A, A), same(A));
- expect(env.getGreatestLowerBound(new InterfaceType(A.classNode), A), A);
+ expect(env.getStandardLowerBound(A, A), same(A));
+ expect(env.getStandardLowerBound(new InterfaceType(A.classNode), A), A);
}
void test_glb_subtype() {
@@ -230,33 +230,33 @@
var B =
_addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
var env = _makeEnv();
- expect(env.getGreatestLowerBound(A, B), same(B));
- expect(env.getGreatestLowerBound(B, A), same(B));
+ expect(env.getStandardLowerBound(A, B), same(B));
+ expect(env.getStandardLowerBound(B, A), same(B));
}
void test_glb_top() {
var A = _addClass(_class('A')).rawType;
var env = _makeEnv();
- expect(env.getGreatestLowerBound(dynamicType, A), same(A));
- expect(env.getGreatestLowerBound(A, dynamicType), same(A));
- expect(env.getGreatestLowerBound(objectType, A), same(A));
- expect(env.getGreatestLowerBound(A, objectType), same(A));
- expect(env.getGreatestLowerBound(voidType, A), same(A));
- expect(env.getGreatestLowerBound(A, voidType), same(A));
+ expect(env.getStandardLowerBound(dynamicType, A), same(A));
+ expect(env.getStandardLowerBound(A, dynamicType), same(A));
+ expect(env.getStandardLowerBound(objectType, A), same(A));
+ expect(env.getStandardLowerBound(A, objectType), same(A));
+ expect(env.getStandardLowerBound(voidType, A), same(A));
+ expect(env.getStandardLowerBound(A, voidType), same(A));
}
void test_glb_unknown() {
var A = _addClass(_class('A')).rawType;
var env = _makeEnv();
- expect(env.getGreatestLowerBound(A, unknownType), same(A));
- expect(env.getGreatestLowerBound(unknownType, A), same(A));
+ expect(env.getStandardLowerBound(A, unknownType), same(A));
+ expect(env.getStandardLowerBound(unknownType, A), same(A));
}
void test_glb_unrelated() {
var A = _addClass(_class('A')).rawType;
var B = _addClass(_class('B')).rawType;
var env = _makeEnv();
- expect(env.getGreatestLowerBound(A, B), same(bottomType));
+ expect(env.getStandardLowerBound(A, B), same(bottomType));
}
void test_inferGenericFunctionOrType() {
@@ -364,12 +364,12 @@
C.classNode.asThisSupertype
])).rawType;
var env = _makeEnv();
- expect(env.getLeastUpperBound(D, E), A);
+ expect(env.getStandardUpperBound(D, E), A);
}
void test_lub_commonClass() {
var env = _makeEnv();
- expect(env.getLeastUpperBound(_list(intType), _list(doubleType)),
+ expect(env.getStandardUpperBound(_list(intType), _list(doubleType)),
_list(numType));
}
@@ -380,43 +380,43 @@
var env = _makeEnv();
// LUB(() -> A, () -> B) = () -> A
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([], A), new FunctionType([], B)),
new FunctionType([], A));
// LUB(([A]) -> void, (A) -> void) = Function
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([A], voidType, requiredParameterCount: 0),
new FunctionType([A], voidType)),
functionType);
// LUB(() -> void, (A, B) -> void) = Function
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([], voidType), new FunctionType([A, B], voidType)),
functionType);
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([A, B], voidType), new FunctionType([], voidType)),
functionType);
// LUB((A) -> void, (B) -> void) = (B) -> void
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([A], voidType), new FunctionType([B], voidType)),
new FunctionType([B], voidType));
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([B], voidType), new FunctionType([A], voidType)),
new FunctionType([B], voidType));
// LUB(({a: A}) -> void, ({b: B}) -> void) = () -> void
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([], voidType,
namedParameters: [new NamedType('a', A)]),
new FunctionType([], voidType,
namedParameters: [new NamedType('b', B)])),
new FunctionType([], voidType));
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([], voidType,
namedParameters: [new NamedType('b', B)]),
new FunctionType([], voidType,
@@ -424,7 +424,7 @@
new FunctionType([], voidType));
// LUB(({a: A, c: A}) -> void, ({b: B, d: B}) -> void) = () -> void
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([], voidType,
namedParameters: [
new NamedType('a', A),
@@ -439,7 +439,7 @@
// LUB(({a: A, b: B}) -> void, ({a: B, b: A}) -> void)
// = ({a: B, b: B}) -> void
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([], voidType,
namedParameters: [
new NamedType('a', A),
@@ -453,7 +453,7 @@
new FunctionType([], voidType,
namedParameters: [new NamedType('a', B), new NamedType('b', B)]));
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([], voidType,
namedParameters: [
new NamedType('a', B),
@@ -468,21 +468,21 @@
namedParameters: [new NamedType('a', B), new NamedType('b', B)]));
// LUB((B, {a: A}) -> void, (B) -> void) = (B) -> void
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([B], voidType,
namedParameters: [new NamedType('a', A)]),
new FunctionType([B], voidType)),
new FunctionType([B], voidType));
// LUB(({a: A}) -> void, (B) -> void) = Function
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([], voidType,
namedParameters: [new NamedType('a', A)]),
new FunctionType([B], voidType)),
functionType);
// GLB(({a: A}) -> void, ([B]) -> void) = () -> void
expect(
- env.getLeastUpperBound(
+ env.getStandardUpperBound(
new FunctionType([], voidType,
namedParameters: [new NamedType('a', A)]),
new FunctionType([B], voidType, requiredParameterCount: 0)),
@@ -492,8 +492,8 @@
void test_lub_identical() {
var A = _addClass(_class('A')).rawType;
var env = _makeEnv();
- expect(env.getLeastUpperBound(A, A), same(A));
- expect(env.getLeastUpperBound(new InterfaceType(A.classNode), A), A);
+ expect(env.getStandardUpperBound(A, A), same(A));
+ expect(env.getStandardUpperBound(new InterfaceType(A.classNode), A), A);
}
void test_lub_sameClass() {
@@ -501,33 +501,34 @@
var B =
_addClass(_class('B', supertype: A.classNode.asThisSupertype)).rawType;
var env = _makeEnv();
- expect(env.getLeastUpperBound(_map(A, B), _map(B, A)), _map(A, A));
+ expect(env.getStandardUpperBound(_map(A, B), _map(B, A)), _map(A, A));
}
void test_lub_subtype() {
var env = _makeEnv();
- expect(env.getLeastUpperBound(_list(intType), _iterable(numType)),
+ expect(env.getStandardUpperBound(_list(intType), _iterable(numType)),
_iterable(numType));
- expect(env.getLeastUpperBound(_iterable(numType), _list(intType)),
+ expect(env.getStandardUpperBound(_iterable(numType), _list(intType)),
_iterable(numType));
}
void test_lub_top() {
var A = _addClass(_class('A')).rawType;
var env = _makeEnv();
- expect(env.getLeastUpperBound(dynamicType, A), same(dynamicType));
- expect(env.getLeastUpperBound(A, dynamicType), same(dynamicType));
- expect(env.getLeastUpperBound(objectType, A), same(objectType));
- expect(env.getLeastUpperBound(A, objectType), same(objectType));
- expect(env.getLeastUpperBound(voidType, A), same(voidType));
- expect(env.getLeastUpperBound(A, voidType), same(voidType));
- expect(env.getLeastUpperBound(dynamicType, objectType), same(dynamicType));
- // TODO(paulberry): see dartbug.com/28513.
- expect(env.getLeastUpperBound(objectType, dynamicType), same(objectType));
- expect(env.getLeastUpperBound(dynamicType, voidType), same(dynamicType));
- expect(env.getLeastUpperBound(voidType, dynamicType), same(dynamicType));
- expect(env.getLeastUpperBound(objectType, voidType), same(voidType));
- expect(env.getLeastUpperBound(voidType, objectType), same(voidType));
+ expect(env.getStandardUpperBound(dynamicType, A), same(dynamicType));
+ expect(env.getStandardUpperBound(A, dynamicType), same(dynamicType));
+ expect(env.getStandardUpperBound(objectType, A), same(objectType));
+ expect(env.getStandardUpperBound(A, objectType), same(objectType));
+ expect(env.getStandardUpperBound(voidType, A), same(voidType));
+ expect(env.getStandardUpperBound(A, voidType), same(voidType));
+ expect(
+ env.getStandardUpperBound(dynamicType, objectType), same(dynamicType));
+ expect(
+ env.getStandardUpperBound(objectType, dynamicType), same(dynamicType));
+ expect(env.getStandardUpperBound(dynamicType, voidType), same(voidType));
+ expect(env.getStandardUpperBound(voidType, dynamicType), same(voidType));
+ expect(env.getStandardUpperBound(objectType, voidType), same(voidType));
+ expect(env.getStandardUpperBound(voidType, objectType), same(voidType));
}
void test_lub_typeParameter() {
@@ -537,21 +538,21 @@
U.parameter.bound = _list(bottomType);
var env = _makeEnv();
// LUB(T, T) = T
- expect(env.getLeastUpperBound(T, T), same(T));
+ expect(env.getStandardUpperBound(T, T), same(T));
// LUB(T, List<Bottom>) = LUB(List<Object>, List<Bottom>) = List<Object>
- expect(env.getLeastUpperBound(T, _list(bottomType)), _list(objectType));
- expect(env.getLeastUpperBound(_list(bottomType), T), _list(objectType));
+ expect(env.getStandardUpperBound(T, _list(bottomType)), _list(objectType));
+ expect(env.getStandardUpperBound(_list(bottomType), T), _list(objectType));
// LUB(T, U) = LUB(List<Object>, U) = LUB(List<Object>, List<Bottom>)
// = List<Object>
- expect(env.getLeastUpperBound(T, U), _list(objectType));
- expect(env.getLeastUpperBound(U, T), _list(objectType));
+ expect(env.getStandardUpperBound(T, U), _list(objectType));
+ expect(env.getStandardUpperBound(U, T), _list(objectType));
}
void test_lub_unknown() {
var A = _addClass(_class('A')).rawType;
var env = _makeEnv();
- expect(env.getGreatestLowerBound(A, unknownType), same(A));
- expect(env.getGreatestLowerBound(unknownType, A), same(A));
+ expect(env.getStandardLowerBound(A, unknownType), same(A));
+ expect(env.getStandardLowerBound(unknownType, A), same(A));
}
void test_solveTypeConstraint() {
diff --git a/pkg/front_end/test/token_test.dart b/pkg/front_end/test/token_test.dart
index b2b21b8..4b39e62 100644
--- a/pkg/front_end/test/token_test.dart
+++ b/pkg/front_end/test/token_test.dart
@@ -138,6 +138,7 @@
Keyword.EXPORT,
Keyword.IMPORT,
Keyword.LIBRARY,
+ Keyword.MIXIN,
Keyword.PART,
Keyword.TYPEDEF,
]);
diff --git a/pkg/meta/lib/meta.dart b/pkg/meta/lib/meta.dart
index d59cc28..38a8283 100644
--- a/pkg/meta/lib/meta.dart
+++ b/pkg/meta/lib/meta.dart
@@ -193,13 +193,13 @@
/// Classes in the same package as the marked class or mixin may extend,
/// implement or mix-in the annotated class or mixin.
///
-/// Given a class or mixin `c`, which is annotated with this, and a class or
-/// mixin `d`, which extends, implements, or mixes in `c`, then tools, such as
+/// Given a class or mixin `C`, which is annotated with this, and a class or
+/// mixin `D`, which extends, implements, or mixes in `C`, then tools, such as
/// the analyzer, may emit warnings if:
///
-/// * `c` and `d` are declared in different packages, or
-/// * `c` and `d` are declared in the same package, and `d` is not also
-/// annotated with this.
+/// * `C` and `D` are declared in different packages, or
+/// * `C` and `D` are declared in the same package, and `D` is not also
+/// annotated with this.
const _Sealed sealed = const _Sealed();
/// Used to annotate a field that is allowed to be overridden in Strong Mode.
diff --git a/pkg/pkg.status b/pkg/pkg.status
index c8f7401..3077d69 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -227,6 +227,7 @@
analysis_server/test/analysis/get_errors_test: Skip # runtime error, Issue 22180
analysis_server/test/benchmarks_test: RuntimeError # Issue 32355
analysis_server/test/integration/*: Skip # Issue 32356
+analysis_server/test/src/plugin/plugin_manager_test: Pass, Slow, RuntimeError # Issue 34231
analyzer/test/generated/non_error_resolver_kernel_test: RuntimeError # Issue 30785
analyzer/test/src/task/strong/checker_test: Pass, Slow
analyzer/tool/task_dependency_graph/check_test: Slow, Pass
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index bc3f8ac..469682e 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -174,6 +174,11 @@
emitWord(_encodeT(Opcode.kJumpIfNoAsserts, label.jumpOperand(offset)));
}
+ void emitJumpIfNotZeroTypeArgs(Label label) {
+ emitWord(
+ _encodeT(Opcode.kJumpIfNotZeroTypeArgs, label.jumpOperand(offset)));
+ }
+
void patchJump(int pos, int rt) {
final Opcode opcode = Opcode.values[_getOpcodeAt(pos)];
assert(isJump(opcode));
@@ -944,6 +949,10 @@
emitWord(_encode0(Opcode.kDeoptRewind));
}
+ void emitEntryFixed(int ra, int rd) {
+ emitWord(_encodeAD(Opcode.kEntryFixed, ra, rd));
+ }
+
void emitEntryOptional(int ra, int rb, int rc) {
emitWord(_encodeABC(Opcode.kEntryOptional, ra, rb, rc));
}
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index 5ca0253..000d960 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -37,6 +37,12 @@
// 10. InstanceCall1 and InstanceCall2 instructions are superseded by
// InstanceCall which works for any number of checked arguments.
//
+// 11. EntryFixed instruction works like Entry. In addition, it checks number
+// of fixed arguments.
+//
+// 12. JumpIfNotZeroTypeArgs instruction jumps if number of passed
+// function type arguments is not zero.
+//
enum Opcode {
kTrap,
@@ -49,6 +55,7 @@
kDrop,
kJump,
kJumpIfNoAsserts,
+ kJumpIfNotZeroTypeArgs,
kReturn,
kReturnTOS,
kMove,
@@ -210,6 +217,7 @@
kBooleanNegate,
kThrow,
kEntry,
+ kEntryFixed,
kEntryOptional,
kEntryOptimized,
kFrame,
@@ -292,6 +300,8 @@
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kJumpIfNoAsserts: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
+ Opcode.kJumpIfNotZeroTypeArgs: const Format(
+ Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kReturn: const Format(
Encoding.kA, const [Operand.reg, Operand.none, Operand.none]),
Opcode.kReturnTOS: const Format(
@@ -614,6 +624,10 @@
Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
Opcode.kEntry: const Format(
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
+ Opcode.kEntryFixed: const Format(
+ Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
+ Opcode.kEntryOptional: const Format(
+ Encoding.kABC, const [Operand.imm, Operand.imm, Operand.imm]),
Opcode.kEntryOptimized: const Format(
Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kFrame: const Format(
@@ -674,8 +688,6 @@
Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kDeoptRewind: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
- Opcode.kEntryOptional: const Format(
- Encoding.kABC, const [Operand.imm, Operand.imm, Operand.imm]),
};
// Should match constant in runtime/vm/stack_frame_dbc.h.
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index cd7cc9a..19a91fe 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -716,6 +716,9 @@
}
void _genPrologue(Node node, FunctionNode function) {
+ final bool isClosure =
+ node is FunctionDeclaration || node is FunctionExpression;
+
if (locals.hasOptionalParameters) {
final int numOptionalPositional = function.positionalParameters.length -
function.requiredParameterCount;
@@ -743,14 +746,13 @@
}
asm.emitFrame(locals.frameSize - locals.numParameters);
+ } else if (isClosure) {
+ asm.emitEntryFixed(locals.numParameters, locals.frameSize);
} else {
asm.emitEntry(locals.frameSize);
}
asm.emitCheckStack();
- final bool isClosure =
- node is FunctionDeclaration || node is FunctionExpression;
-
if (isClosure) {
asm.emitPush(locals.closureVarIndexInFrame);
asm.emitLoadFieldTOS(cp.add(new ConstantInstanceField(closureContext)));
@@ -762,6 +764,22 @@
assert(!(node is Procedure && node.isFactory));
asm.emitCheckFunctionTypeArgs(function.typeParameters.length,
locals.functionTypeArgsVarIndexInFrame);
+
+ bool hasNonDynamicDefaultTypes = function.typeParameters.any((p) =>
+ p.defaultType != null && p.defaultType != const DynamicType());
+ if (hasNonDynamicDefaultTypes) {
+ List<DartType> defaultTypes = function.typeParameters
+ .map((p) => p.defaultType ?? const DynamicType())
+ .toList();
+ assert(defaultTypes
+ .every((t) => !containsTypeVariable(t, functionTypeParameters)));
+
+ Label done = new Label();
+ asm.emitJumpIfNotZeroTypeArgs(done);
+ _genTypeArguments(defaultTypes);
+ asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
+ asm.bind(done);
+ }
}
if (isClosure) {
@@ -2608,7 +2626,8 @@
}
final bool result = node.positionalParameters.any((t) => t.accept(this)) ||
- node.namedParameters.any((p) => p.type.accept(this));
+ node.namedParameters.any((p) => p.type.accept(this)) ||
+ node.returnType.accept(this);
if (node.typeParameters.isNotEmpty) {
_declaredTypeParameters.removeAll(node.typeParameters);
diff --git a/pkg/vm/lib/transformations/call_site_annotator.dart b/pkg/vm/lib/transformations/call_site_annotator.dart
index dd87e57..3d80936 100644
--- a/pkg/vm/lib/transformations/call_site_annotator.dart
+++ b/pkg/vm/lib/transformations/call_site_annotator.dart
@@ -65,9 +65,12 @@
}
// TODO(vegorov) handle setters as well.
+ // TODO(34162): We don't need to save the type here, just whether or not it's
+ // a statically-checked call.
static bool shouldAnnotate(MethodInvocation node) =>
- node.interfaceTarget != null &&
- hasGenericCovariantParameters(node.interfaceTarget);
+ (node.interfaceTarget != null &&
+ hasGenericCovariantParameters(node.interfaceTarget)) ||
+ node.name.name == "call";
/// Return [true] if the given list of [VariableDeclaration] contains
/// any annotated with generic-covariant-impl.
diff --git a/pkg/vm/testcases/bytecode/asserts.dart.expect b/pkg/vm/testcases/bytecode/asserts.dart.expect
index 3f5cf69..176424f 100644
--- a/pkg/vm/testcases/bytecode/asserts.dart.expect
+++ b/pkg/vm/testcases/bytecode/asserts.dart.expect
@@ -65,7 +65,7 @@
[7] = Null
}
]static method test2(() → core::bool condition, () → core::String message) → void {
- assert(condition.call(), message.call());
+ assert([@vm.call-site-attributes.metadata=receiverType:() → dart.core::bool] condition.call(), [@vm.call-site-attributes.metadata=receiverType:() → dart.core::String] message.call());
}
[@vm.bytecode=
Bytecode {
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index 79176de..45fdde0 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -158,7 +158,7 @@
}
Closure CP#0 {
- Entry 4
+ EntryFixed 2, 4
CheckStack
Push FP[-6]
LoadFieldTOS CP#1
@@ -2121,7 +2121,7 @@
}
Closure CP#1 {
- Entry 4
+ EntryFixed 1, 4
CheckStack
Push FP[-5]
LoadFieldTOS CP#2
diff --git a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
index 16c0efe..a20221a 100644
--- a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
@@ -365,7 +365,7 @@
}
] static get platformScript() → dynamic {
if(self::VMLibraryHooks::_cachedScript.{core::Object::==}(null) && !self::VMLibraryHooks::_computeScriptUri.{core::Object::==}(null)) {
- self::VMLibraryHooks::_cachedScript = self::VMLibraryHooks::_computeScriptUri.call();
+ self::VMLibraryHooks::_cachedScript = [@vm.call-site-attributes.metadata=receiverType:dynamic] self::VMLibraryHooks::_computeScriptUri.call();
}
return self::VMLibraryHooks::_cachedScript;
}
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index 7959152..3347fd6 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -293,7 +293,7 @@
[57] = ICData target-name 'call', arg-desc CP#49
}
Closure CP#12 {
- Entry 4
+ EntryFixed 1, 4
CheckStack
Push FP[-5]
LoadFieldTOS CP#1
@@ -378,7 +378,7 @@
}
Closure CP#9 {
- Entry 5
+ EntryFixed 1, 5
CheckStack
Push FP[-5]
LoadFieldTOS CP#1
@@ -421,7 +421,7 @@
}
Closure CP#0 {
- Entry 5
+ EntryFixed 1, 5
CheckStack
Push FP[-5]
LoadFieldTOS CP#1
@@ -474,13 +474,13 @@
core::print(<core::Type>[self::A::T1, self::A::T2, self::A::foo::T3, self::A::foo::T4, T5, T6, T7, T8]);
self::callWithArgs<self::A::T1, self::A::T2, self::A::foo::T3, self::A::foo::T4, T5, T6, T7, T8>();
};
- nested3.call();
+ [@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] nested3.call();
}
- nested2.call<self::C7, self::C8>();
- nested2.call<core::List<self::C7>, core::List<self::C8>>();
+ [@vm.call-site-attributes.metadata=receiverType:<T7 extends dart.core::Object = dynamic, T8 extends dart.core::Object = dynamic>() → void] nested2.call<self::C7, self::C8>();
+ [@vm.call-site-attributes.metadata=receiverType:<T7 extends dart.core::Object = dynamic, T8 extends dart.core::Object = dynamic>() → void] nested2.call<core::List<self::C7>, core::List<self::C8>>();
}
- nested1.call<self::C5, self::C6>();
- nested1.call<core::List<self::C5>, core::List<self::C6>>();
+ [@vm.call-site-attributes.metadata=receiverType:<T5 extends dart.core::Object = dynamic, T6 extends dart.core::Object = dynamic>() → void] nested1.call<self::C5, self::C6>();
+ [@vm.call-site-attributes.metadata=receiverType:<T5 extends dart.core::Object = dynamic, T6 extends dart.core::Object = dynamic>() → void] nested1.call<core::List<self::C5>, core::List<self::C6>>();
}
}
class B extends core::Object {
@@ -638,7 +638,7 @@
[46] = ICData target-name 'call', arg-desc CP#18
}
Closure CP#16 {
- Entry 3
+ EntryFixed 1, 3
CheckStack
Push FP[-5]
LoadFieldTOS CP#4
@@ -666,7 +666,7 @@
}
Closure CP#3 {
- Entry 4
+ EntryFixed 2, 4
CheckStack
Push FP[-6]
LoadFieldTOS CP#4
@@ -739,7 +739,7 @@
}
Closure CP#43 {
- Entry 3
+ EntryFixed 1, 3
CheckStack
Push FP[-5]
LoadFieldTOS CP#4
@@ -768,12 +768,12 @@
z = x.{core::num::+}(2);
w = this.{self::B::foo}.{core::num::+}(y);
}
- closure2.call();
+ [@vm.call-site-attributes.metadata=receiverType:() → void] closure2.call();
core::print(w);
}
};
- closure1.call(10);
- closure1.call(11);
+ [@vm.call-site-attributes.metadata=receiverType:(dart.core::int) → dart.core::Null] closure1.call(10);
+ [@vm.call-site-attributes.metadata=receiverType:(dart.core::int) → dart.core::Null] closure1.call(11);
core::print(y);
core::print(z);
}
@@ -784,7 +784,7 @@
() → core::Null closure3 = () → core::Null {
this.{self::B::foo} = x;
};
- closure3.call();
+ [@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] closure3.call();
}
}
}
@@ -954,7 +954,7 @@
[33] = ICData target-name '+', arg-desc CP#2
}
Closure CP#8 {
- Entry 2
+ EntryFixed 1, 2
CheckStack
Push FP[-5]
LoadFieldTOS CP#9
@@ -972,7 +972,7 @@
}
Closure CP#25 {
- Entry 3
+ EntryFixed 2, 3
CheckStack
Push FP[-6]
LoadFieldTOS CP#9
@@ -1098,7 +1098,7 @@
[27] = StaticICData target 'dart.core::print', arg-desc CP#4
}
Closure CP#9 {
- Entry 3
+ EntryFixed 1, 3
CheckStack
Push FP[-5]
LoadFieldTOS CP#10
@@ -1118,7 +1118,7 @@
() → core::Null inc = () → core::Null {
i = i.{core::num::+}(1);
};
- inc.call();
+ [@vm.call-site-attributes.metadata=receiverType:() → dart.core::Null] inc.call();
core::print(i);
}
}
@@ -1204,7 +1204,7 @@
[18] = Reserved
}
Closure CP#5 {
- Entry 2
+ EntryFixed 1, 2
CheckStack
Push FP[-5]
LoadFieldTOS CP#6
@@ -1286,7 +1286,7 @@
[22] = ICData target-name 'call', arg-desc CP#8
}
Closure CP#1 {
- Entry 3
+ EntryFixed 2, 3
CheckStack
Push FP[-6]
LoadFieldTOS CP#2
@@ -1313,7 +1313,7 @@
(core::int) → core::Null inc = (core::int y) → core::Null {
x = x.{core::num::+}(y);
};
- inc.call(3);
+ [@vm.call-site-attributes.metadata=receiverType:(dart.core::int) → dart.core::Null] inc.call(3);
return x;
}
[@vm.bytecode=
@@ -1549,7 +1549,7 @@
[22] = TypeArgs [dart.core::int]
}
Closure CP#0 {
- Entry 3
+ EntryFixed 2, 3
CheckStack
Push FP[-6]
LoadFieldTOS CP#1
diff --git a/pkg/vm/testcases/bytecode/super_calls.dart.expect b/pkg/vm/testcases/bytecode/super_calls.dart.expect
index d0e8cf4..64c96cf 100644
--- a/pkg/vm/testcases/bytecode/super_calls.dart.expect
+++ b/pkg/vm/testcases/bytecode/super_calls.dart.expect
@@ -205,7 +205,7 @@
[6] = Null
}
] method testSuperCallViaGetter() → dynamic
- return super.{self::Base1::bar}.call<core::int>("param");
+ return [@vm.call-site-attributes.metadata=receiverType:dynamic] super.{self::Base1::bar}.call<core::int>("param");
[@vm.bytecode=
Bytecode {
Entry 1
@@ -467,7 +467,7 @@
[14] = Null
}
] method testSuperCallViaGetter() → dynamic
- return super.{self::Base2::bar}.call<core::int>("param");
+ return [@vm.call-site-attributes.metadata=receiverType:dynamic] super.{self::Base2::bar}.call<core::int>("param");
[@vm.bytecode=
Bytecode {
Entry 1
diff --git a/pkg/vm/testcases/bytecode/try_blocks.dart.expect b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
index 1917977..bd7e762 100644
--- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect
+++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
@@ -405,7 +405,7 @@
[42] = EndClosureFunctionScope
}
Closure CP#2 {
- Entry 6
+ EntryFixed 1, 6
CheckStack
Push FP[-5]
LoadFieldTOS CP#3
@@ -443,7 +443,7 @@
}
Closure CP#31 {
- Entry 6
+ EntryFixed 1, 6
CheckStack
Push FP[-5]
LoadFieldTOS CP#3
@@ -522,7 +522,7 @@
y = 3;
}
}
- foo.call();
+ [@vm.call-site-attributes.metadata=receiverType:() → void] foo.call();
core::print(y);
}
on dynamic catch(final dynamic e, final core::StackTrace st) {
@@ -934,7 +934,7 @@
[42] = StaticICData target 'dart.core::print', arg-desc CP#7
}
Closure CP#12 {
- Entry 2
+ EntryFixed 1, 2
CheckStack
Push FP[-5]
LoadFieldTOS CP#13
@@ -968,7 +968,7 @@
core::print(x);
core::print(y);
}
- foo.call();
+ [@vm.call-site-attributes.metadata=receiverType:() → void] foo.call();
continue #L4;
}
finally {
@@ -1103,7 +1103,7 @@
[39] = ICData target-name 'call', arg-desc CP#5
}
Closure CP#2 {
- Entry 6
+ EntryFixed 1, 6
CheckStack
Push FP[-5]
LoadFieldTOS CP#3
@@ -1293,7 +1293,7 @@
}
finally {
core::print(x);
- y.call();
+ [@vm.call-site-attributes.metadata=receiverType:dynamic] y.call();
}
}
[@vm.bytecode=
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index c0628ce..924e681 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -324,41 +324,49 @@
Entry 1
CheckStack
CheckFunctionTypeArgs 2, 0
+ JumpIfNotZeroTypeArgs L1
+ Push FP[-6]
+ LoadTypeArgumentsField CP#0
+ PushConstant CP#1
+ InstantiateTypeArgumentsTOS 0, CP#2
+ PopLocal r0
+L1:
Push FP[-6]
LoadTypeArgumentsField CP#0
Push r0
- PushConstant CP#1
- PushConstant CP#2
PushConstant CP#3
- AssertSubtype
PushConstant CP#4
- Push r0
PushConstant CP#5
+ AssertSubtype
+ PushConstant CP#1
+ Push r0
PushConstant CP#6
PushConstant CP#7
+ PushConstant CP#8
AssertSubtype
Push FP[-5]
- PushConstant CP#4
+ PushConstant CP#1
Push r0
- PushConstant CP#8
PushConstant CP#9
- AssertAssignable 0, CP#10
+ PushConstant CP#10
+ AssertAssignable 0, CP#11
Drop1
- PushConstant CP#4
+ PushConstant CP#1
ReturnTOS
}
ConstantPool {
[0] = TypeArgumentsField #lib::E
- [1] = Type #lib::E::foo6::T
- [2] = Type #lib::E::P
- [3] = String 'T'
- [4] = Null
- [5] = Type #lib::E::foo6::U
- [6] = Type dart.core::List<#lib::E::foo6::T>
- [7] = String 'U'
- [8] = Type dart.core::Map<#lib::E::foo6::T, #lib::E::foo6::U>
- [9] = String 'map'
- [10] = SubtypeTestCache
+ [1] = Null
+ [2] = TypeArgs [#lib::E::P, dart.core::List<#lib::E::P>]
+ [3] = Type #lib::E::foo6::T
+ [4] = Type #lib::E::P
+ [5] = String 'T'
+ [6] = Type #lib::E::foo6::U
+ [7] = Type dart.core::List<#lib::E::foo6::T>
+ [8] = String 'U'
+ [9] = Type dart.core::Map<#lib::E::foo6::T, #lib::E::foo6::U>
+ [10] = String 'map'
+ [11] = SubtypeTestCache
}
] method foo6<generic-covariant-impl T extends self::E::P = self::E::P, U extends core::List<self::E::foo6::T> = core::List<self::E::P>>(core::Map<self::E::foo6::T, self::E::foo6::U> map) → void {}
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
index f58857b..b75afef 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/future_or.dart.expect
@@ -35,7 +35,7 @@
self::foo2_a4(a4);
}
static method getDynamic() → dynamic
- return self::unknown.call();
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method main(core::List<core::String> args) → dynamic {
self::foo1([@vm.inferred-type.metadata=dart.async::_Future] asy::Future::value<self::B>(new self::B::•()), new self::B::•(), [@vm.inferred-type.metadata=dart.async::_Future] asy::Future::value<self::B>(new self::B::•()), new self::B::•());
self::foo2(self::getDynamic() as{TypeError} asy::Future<self::A>, self::getDynamic() as{TypeError} self::A, self::getDynamic() as{TypeError} asy::FutureOr<self::A>, self::getDynamic() as{TypeError} asy::FutureOr<self::A>);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
index 740d76d..a8d6be6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_field_initializer.dart.expect
@@ -64,7 +64,7 @@
[@vm.inferred-type.metadata=dart.core::Null?]static field core::Function unknown;
static field core::Object field1 = [@vm.inferred-type.metadata=!] self::getValue();
static method getDynamic() → dynamic
- return self::unknown.call();
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method getValue() → core::Object {
self::A aa = self::getDynamic() as{TypeError} self::A;
return [@vm.inferred-type.metadata=!] aa.{self::A::foo}();
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
index bee0c8e..9388a7d 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class1.dart.expect
@@ -33,7 +33,7 @@
static method use2([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, [@vm.inferred-type.metadata=#lib::B?] self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=#lib::T1] i.{self::Intermediate::bar}(aa);
static method getDynamic() → dynamic
- return self::unknown.call();
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method allocateB() → dynamic {
new self::B::•();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
index 2a40057..b6e35fd 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_class2.dart.expect
@@ -59,7 +59,7 @@
static method use3([@vm.inferred-type.metadata=#lib::Intermediate] self::Intermediate i, self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=!] i.{self::Intermediate::bar}(aa);
static method getDynamic() → dynamic
- return self::unknown.call();
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method allocateB() → dynamic {
new self::B::•();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
index 55d3d4e..3fd5f9f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_new_dynamic_target.dart.expect
@@ -49,7 +49,7 @@
static method use_bazz(dynamic x) → dynamic
return [@vm.inferred-type.metadata=#lib::T3] x.bazz();
static method getDynamic() → dynamic
- return self::unknown.call();
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method allocateA() → dynamic {
new self::A::•();
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
index 78b259d..10fdcc6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/invalidation_set_field.dart.expect
@@ -51,7 +51,7 @@
static method use2([@vm.inferred-type.metadata=#lib::DeepCaller2] self::DeepCaller2 x, [@vm.inferred-type.metadata=#lib::A?] self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2::barL1] [@vm.inferred-type.metadata=!] x.{self::DeepCaller2::barL1}(aa);
static method getDynamic() → dynamic
- return self::unknown.call();
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method setField2([@vm.inferred-type.metadata=#lib::A] self::A aa, [@vm.inferred-type.metadata=#lib::T2] dynamic value) → void {
[@vm.direct-call.metadata=#lib::A::field2] aa.{self::A::field2} = value;
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
index 86a3d0f..64585aa 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
@@ -113,7 +113,7 @@
[@vm.inferred-type.metadata=#lib::D?]static field self::A dd = new self::D::•();
[@vm.inferred-type.metadata=dart.core::Null?]static field core::Function unknown;
static method getDynamic() → dynamic
- return self::unknown.call();
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method main(core::List<core::String> args) → dynamic {
core::print([@vm.direct-call.metadata=#lib::B::foo??] [@vm.inferred-type.metadata=#lib::T1] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::foo}());
core::print([@vm.direct-call.metadata=#lib::B::bar??] [@vm.inferred-type.metadata=#lib::T1] [@vm.inferred-type.metadata=#lib::B?] self::bb.{self::A::bar});
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
index 3ea010c..eb9c442 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/param_types_before_strong_mode_checks.dart.expect
@@ -49,9 +49,9 @@
[@vm.direct-call.metadata=#lib::T2::foo??] t0.{self::T0::foo}();
}
static method getDynamic() → dynamic
- return self::unknown.call();
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call();
static method use(dynamic x) → dynamic
- return self::unknown.call(x);
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown.call(x);
static method main(core::List<core::String> args) → dynamic {
self::func1(self::getDynamic() as{TypeError} self::T0);
self::use(self::func2);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
index 1ad7392..8ef426f 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_flutter16182.dart.expect
@@ -56,7 +56,7 @@
: super self::B2Base::•()
;
method doSuperCall() → void {
- [@vm.direct-call.metadata=#lib::A2::call] [@vm.inferred-type.metadata=#lib::A2] super.{self::B2Base::aa2}.call(1, 2, 3, 4, 5, new self::T2::•());
+ [@vm.call-site-attributes.metadata=receiverType:dynamic] [@vm.direct-call.metadata=#lib::A2::call] [@vm.inferred-type.metadata=#lib::A2] super.{self::B2Base::aa2}.call(1, 2, 3, 4, 5, new self::T2::•());
}
}
class T3 extends core::Object {
@@ -127,7 +127,7 @@
exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
}
static method getDynamic3() → dynamic
- return self::unknown3.call();
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown3.call();
static method test3() → void {
self::getDynamic3().aa3(1, 2, 3, 4, 5, 6, new self::T3::•());
self::ok = false;
@@ -135,7 +135,7 @@
exp::Expect::isTrue([@vm.inferred-type.metadata=dart.core::bool?] self::ok);
}
static method getDynamic4() → dynamic
- return self::unknown4.call();
+ return [@vm.call-site-attributes.metadata=receiverType:dart.core::Function] self::unknown4.call();
static method test4() → void {
self::getDynamic4().aa4(1, 2, 3, 4, 5, 6, 7, new self::T4::•());
self::ok = false;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
index 8492698..871430a 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_dynamic_method.dart.expect
@@ -25,5 +25,5 @@
return new self::B::•();
static method main(core::List<core::String> args) → dynamic {
core::Function closure = () → self::B => new self::B::•();
- new self::TearOffDynamicMethod::•(closure.call());
+ new self::TearOffDynamicMethod::•([@vm.call-site-attributes.metadata=receiverType:dart.core::Function] closure.call());
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
index 689ae8c..eed4b00 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tear_off_super_method.dart.expect
@@ -22,7 +22,7 @@
method foo() → core::int
return [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+] [@vm.inferred-type.metadata=int?] 3.{core::num::+}([@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=int?] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
method doCall(dynamic x) → core::int
- return x.call() as{TypeError} core::int;
+ return [@vm.call-site-attributes.metadata=receiverType:dynamic] x.call() as{TypeError} core::int;
}
class TearOffSuperMethod extends self::Base {
synthetic constructor •() → void
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 3583691..96351e9 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -880,16 +880,6 @@
executable = false
}
-bin_to_linkable("platform_dill_linkable") {
- deps = [
- "../vm:vm_legacy_platform",
- ]
- input = "$root_out_dir/vm_platform.dill"
- symbol = "kPlatformDill"
- size_symbol = "kPlatformDillSize"
- executable = false
-}
-
bin_to_linkable("platform_strong_dill_linkable") {
deps = [
"../vm:vm_platform",
@@ -918,11 +908,9 @@
visibility = [ ":*" ]
deps = [
":kernel_service_dill_linkable",
- ":platform_dill_linkable",
":platform_strong_dill_linkable",
]
sources = get_target_outputs(":kernel_service_dill_linkable") +
- get_target_outputs(":platform_dill_linkable") +
get_target_outputs(":platform_strong_dill_linkable")
}
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index b6de97c..5e58c20 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -18,15 +18,11 @@
#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
extern const uint8_t kKernelServiceDill[];
extern intptr_t kKernelServiceDillSize;
-extern const uint8_t kPlatformDill[];
-extern intptr_t kPlatformDillSize;
extern const uint8_t kPlatformStrongDill[];
extern intptr_t kPlatformStrongDillSize;
#else
const uint8_t* kKernelServiceDill = NULL;
intptr_t kKernelServiceDillSize = 0;
-const uint8_t* kPlatformDill = NULL;
-intptr_t kPlatformDillSize = 0;
const uint8_t* kPlatformStrongDill = NULL;
intptr_t kPlatformStrongDillSize = 0;
#endif // !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM)
@@ -42,15 +38,11 @@
#if defined(DART_NO_SNAPSHOT) || defined(DART_PRECOMPILER)
const uint8_t* kernel_service_dill = NULL;
const intptr_t kernel_service_dill_size = 0;
-const uint8_t* platform_dill = NULL;
-const intptr_t platform_dill_size = 0;
const uint8_t* platform_strong_dill = NULL;
const intptr_t platform_strong_dill_size = 0;
#else
const uint8_t* kernel_service_dill = kKernelServiceDill;
const intptr_t kernel_service_dill_size = kKernelServiceDillSize;
-const uint8_t* platform_dill = kPlatformDill;
-const intptr_t platform_dill_size = kPlatformDillSize;
const uint8_t* platform_strong_dill = kPlatformStrongDill;
const intptr_t platform_strong_dill_size = kPlatformStrongDillSize;
#endif
@@ -98,7 +90,7 @@
}
void DFE::Init() {
- if (platform_dill == NULL) {
+ if (platform_strong_dill == NULL) {
return;
}
@@ -138,19 +130,13 @@
}
void DFE::LoadPlatform(const uint8_t** kernel_buffer,
- intptr_t* kernel_buffer_size,
- bool strong) {
- if (strong) {
- *kernel_buffer = platform_strong_dill;
- *kernel_buffer_size = platform_strong_dill_size;
- } else {
- *kernel_buffer = platform_dill;
- *kernel_buffer_size = platform_dill_size;
- }
+ intptr_t* kernel_buffer_size) {
+ *kernel_buffer = platform_strong_dill;
+ *kernel_buffer_size = platform_strong_dill_size;
}
bool DFE::CanUseDartFrontend() const {
- return (platform_dill != NULL) &&
+ return (platform_strong_dill != NULL) &&
(KernelServiceDillAvailable() || (frontend_filename() != NULL));
}
@@ -191,7 +177,6 @@
};
Dart_KernelCompilationResult DFE::CompileScript(const char* script_uri,
- bool strong,
bool incremental,
const char* package_config) {
// TODO(aam): When Frontend is ready, VM should be passing vm_outline.dill
@@ -203,12 +188,8 @@
const char* sanitized_uri = script_uri;
#endif
- const uint8_t* platform_binary =
- strong ? platform_strong_dill : platform_dill;
- intptr_t platform_binary_size =
- strong ? platform_strong_dill_size : platform_dill_size;
- return Dart_CompileToKernel(sanitized_uri, platform_binary,
- platform_binary_size, incremental,
+ return Dart_CompileToKernel(sanitized_uri, platform_strong_dill,
+ platform_strong_dill_size, incremental,
package_config);
}
@@ -217,10 +198,9 @@
intptr_t* kernel_buffer_size,
char** error,
int* exit_code,
- bool strong,
const char* package_config) {
- Dart_KernelCompilationResult result = CompileScript(
- script_uri, strong, use_incremental_compiler(), package_config);
+ Dart_KernelCompilationResult result =
+ CompileScript(script_uri, use_incremental_compiler(), package_config);
switch (result.status) {
case Dart_KernelCompilationStatus_Ok:
*kernel_buffer = result.kernel;
diff --git a/runtime/bin/dfe.h b/runtime/bin/dfe.h
index 433550f..af520658 100644
--- a/runtime/bin/dfe.h
+++ b/runtime/bin/dfe.h
@@ -57,7 +57,6 @@
// Compiles specified script.
// Returns result from compiling the script.
Dart_KernelCompilationResult CompileScript(const char* script_uri,
- bool strong,
bool incremental,
const char* package_config);
@@ -70,7 +69,6 @@
intptr_t* kernel_buffer_size,
char** error,
int* exit_code,
- bool strong,
const char* package_config);
// Reads the script kernel file if specified 'script_uri' is a kernel file.
@@ -98,8 +96,7 @@
bool CanUseDartFrontend() const;
void LoadPlatform(const uint8_t** kernel_buffer,
- intptr_t* kernel_buffer_size,
- bool strong = false);
+ intptr_t* kernel_buffer_size);
void LoadKernelService(const uint8_t** kernel_service_buffer,
intptr_t* kernel_service_buffer_size);
diff --git a/runtime/bin/loader.cc b/runtime/bin/loader.cc
index 95bf352..b3a9074 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -702,8 +702,7 @@
path);
}
- Dart_Handle result =
- Extensions::LoadExtension(decoder.decoded(), path, library);
+ Dart_Handle result = Extensions::LoadExtension(lib_path, path, library);
free(lib_path);
return result;
}
@@ -792,7 +791,7 @@
uint8_t* kernel_buffer = NULL;
intptr_t kernel_buffer_size = -1;
dfe.CompileAndReadScript(url_string, &kernel_buffer, &kernel_buffer_size,
- &error, &exit_code, true /* strong */, NULL);
+ &error, &exit_code, NULL);
if (exit_code == 0) {
return Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size);
} else if (exit_code == kCompilationErrorExitCode) {
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index caf82ee..5531dd5 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -351,7 +351,7 @@
intptr_t application_kernel_buffer_size = 0;
dfe.CompileAndReadScript(script_uri, &application_kernel_buffer,
&application_kernel_buffer_size, error, exit_code,
- flags->strong, resolved_packages_config);
+ resolved_packages_config);
if (application_kernel_buffer == NULL) {
Dart_ExitScope();
Dart_ShutdownIsolate();
@@ -578,7 +578,7 @@
// from kernel only if we can.
const uint8_t* kernel_buffer = NULL;
intptr_t kernel_buffer_size = 0;
- dfe.LoadPlatform(&kernel_buffer, &kernel_buffer_size, flags->strong);
+ dfe.LoadPlatform(&kernel_buffer, &kernel_buffer_size);
if (kernel_buffer == NULL) {
dfe.application_kernel_buffer(&kernel_buffer, &kernel_buffer_size);
}
@@ -699,8 +699,7 @@
if (Options::preview_dart_2() && !isolate_run_app_snapshot) {
const uint8_t* platform_kernel_buffer = NULL;
intptr_t platform_kernel_buffer_size = 0;
- dfe.LoadPlatform(&platform_kernel_buffer, &platform_kernel_buffer_size,
- flags->strong);
+ dfe.LoadPlatform(&platform_kernel_buffer, &platform_kernel_buffer_size);
if (platform_kernel_buffer == NULL) {
platform_kernel_buffer = kernel_buffer;
platform_kernel_buffer_size = kernel_buffer_size;
@@ -971,7 +970,6 @@
}
if (Options::preview_dart_2()) {
Snapshot::GenerateKernel(Options::snapshot_filename(), script_name,
- flags.strong,
isolate_data->resolved_packages_config());
} else {
Snapshot::GenerateScript(Options::snapshot_filename());
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index 7f11ffa..2ff01c2 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -334,7 +334,6 @@
void Snapshot::GenerateKernel(const char* snapshot_filename,
const char* script_name,
- bool strong,
const char* package_config) {
#if !defined(EXCLUDE_CFE_AND_KERNEL_PLATFORM) && !defined(TESTING)
uint8_t* kernel_buffer = NULL;
@@ -344,7 +343,7 @@
WriteSnapshotFile(snapshot_filename, kernel_buffer, kernel_buffer_size);
} else {
Dart_KernelCompilationResult result =
- dfe.CompileScript(script_name, strong, false, package_config);
+ dfe.CompileScript(script_name, false, package_config);
if (result.status != Dart_KernelCompilationStatus_Ok) {
ErrorExit(kErrorExitCode, "%s\n", result.error);
}
diff --git a/runtime/bin/snapshot_utils.h b/runtime/bin/snapshot_utils.h
index 5f935b5..c1d6edf 100644
--- a/runtime/bin/snapshot_utils.h
+++ b/runtime/bin/snapshot_utils.h
@@ -30,7 +30,6 @@
public:
static void GenerateKernel(const char* snapshot_filename,
const char* script_name,
- bool strong,
const char* package_config);
static void GenerateScript(const char* snapshot_filename);
static void GenerateAppJIT(const char* snapshot_filename);
diff --git a/runtime/runtime_args.gni b/runtime/runtime_args.gni
index 91cb9cd..ba24461 100644
--- a/runtime/runtime_args.gni
+++ b/runtime/runtime_args.gni
@@ -91,7 +91,7 @@
# We create a kernel service app-jit snapshot only for when the target
# architecture is x64 for other cases we will use the '.dill' file
# which is already linked in the VM.
- if (dart_target_arch == "x64") {
+ if (dart_target_arch == "x64" && !dart_use_interpreter) {
create_kernel_service_snapshot = true
} else {
create_kernel_service_snapshot = false
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff.dart b/runtime/tests/vm/dart/entrypoints/tearoff.dart
new file mode 100644
index 0000000..cdebd3a
--- /dev/null
+++ b/runtime/tests/vm/dart/entrypoints/tearoff.dart
@@ -0,0 +1,37 @@
+// 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.
+
+// Test that typed calls against tearoffs go into the unchecked entrypoint.
+
+import "package:expect/expect.dart";
+import "common.dart";
+
+class C<T> {
+ @NeverInline
+ @pragma("vm:testing.unsafe.trace-entrypoints-fn", validateTearoff)
+ void target1(T x, String y) {
+ Expect.notEquals(x, -1);
+ Expect.equals(y, "foo");
+ }
+}
+
+test(List<String> args) {
+ var f = (new C<int>()).target1;
+
+ // Warmup.
+ expectedEntryPoint = -1;
+ expectedTearoffEntryPoint = -1;
+ for (int i = 0; i < 100; ++i) {
+ f(i, "foo");
+ }
+
+ expectedEntryPoint = 0;
+ expectedTearoffEntryPoint = 1;
+ const int iterations = benchmarkMode ? 100000000 : 100;
+ for (int i = 0; i < iterations; ++i) {
+ f(i, "foo");
+ }
+
+ Expect.isTrue(validateRan);
+}
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_inline_test.dart b/runtime/tests/vm/dart/entrypoints/tearoff_inline_test.dart
new file mode 100644
index 0000000..843324a
--- /dev/null
+++ b/runtime/tests/vm/dart/entrypoints/tearoff_inline_test.dart
@@ -0,0 +1,9 @@
+// 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.
+
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
+
+import "tearoff.dart";
+
+main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_noinline_test.dart b/runtime/tests/vm/dart/entrypoints/tearoff_noinline_test.dart
new file mode 100644
index 0000000..aac3f75
--- /dev/null
+++ b/runtime/tests/vm/dart/entrypoints/tearoff_noinline_test.dart
@@ -0,0 +1,9 @@
+// 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.
+
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
+
+import "tearoff.dart";
+
+main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_prologue.dart b/runtime/tests/vm/dart/entrypoints/tearoff_prologue.dart
new file mode 100644
index 0000000..8ce9916
--- /dev/null
+++ b/runtime/tests/vm/dart/entrypoints/tearoff_prologue.dart
@@ -0,0 +1,35 @@
+// No type checks are removed here, but we can skip the argument count check.
+
+import "package:expect/expect.dart";
+import "common.dart";
+
+class C<T> {
+ @NeverInline
+ @pragma("vm:testing.unsafe.trace-entrypoints-fn", validateTearoff)
+ void samir1(T x) {
+ if (x == -1) {
+ throw "oh no";
+ }
+ }
+}
+
+test(List<String> args) {
+ var c = new C<int>();
+ var f = c.samir1;
+
+ // Warmup.
+ expectedEntryPoint = -1;
+ expectedTearoffEntryPoint = -1;
+ for (int i = 0; i < 100; ++i) {
+ f(i);
+ }
+
+ expectedEntryPoint = 0;
+ expectedTearoffEntryPoint = 1;
+ int iterations = benchmarkMode ? 100000000 : 100;
+ for (int i = 0; i < iterations; ++i) {
+ f(i);
+ }
+
+ Expect.isTrue(validateRan);
+}
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_prologue_inline_test.dart b/runtime/tests/vm/dart/entrypoints/tearoff_prologue_inline_test.dart
new file mode 100644
index 0000000..3ccf462
--- /dev/null
+++ b/runtime/tests/vm/dart/entrypoints/tearoff_prologue_inline_test.dart
@@ -0,0 +1,5 @@
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10 -Denable_inlining=true
+
+import "tearoff_prologue.dart";
+
+main(args) => test(args);
diff --git a/runtime/tests/vm/dart/entrypoints/tearoff_prologue_noinline_test.dart b/runtime/tests/vm/dart/entrypoints/tearoff_prologue_noinline_test.dart
new file mode 100644
index 0000000..4f1bbcd
--- /dev/null
+++ b/runtime/tests/vm/dart/entrypoints/tearoff_prologue_noinline_test.dart
@@ -0,0 +1,5 @@
+// VMOptions=--enable-testing-pragmas --no-background-compilation --enable-inlining-annotations --optimization-counter-threshold=10
+
+import "tearoff_prologue.dart";
+
+main(args) => test(args);
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 48294f4..f41388e 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -143,6 +143,9 @@
cc/Profiler_BasicSourcePosition: Fail # http://dartbug.com/33224
cc/Profiler_CodeTicks: Fail # dartbug.com/33337
+[ $arch == ia32 && $compiler != dartk && $compiler != dartkp && $compiler != dartkb && $system == windows && $runtime == vm && $mode == debug ]
+cc/BitTestImmediate: Crash # dartbug.com/34252
+
[ $arch == x64 && $system == windows ]
cc/Profiler_BinaryOperatorSourcePositionOptimized: Pass, Fail # Issue 31137
cc/Profiler_ClosureAllocation: Pass, Fail # Issue 31137
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index c52f150..a8e852a 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1589,7 +1589,7 @@
if (type.IsType() && !type.IsFunctionType() && !type.IsDartFunctionType() &&
type.IsInstantiated()) {
const Class& cls = Class::Handle(type.type_class());
- return cls.IsGeneric();
+ return cls.IsGeneric() && !cls.IsFutureOrClass();
}
return false;
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 9b5a4be..d9232fa 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1860,10 +1860,9 @@
objects_.Add(pool);
intptr_t length = pool->ptr()->length_;
- uint8_t* entry_types = pool->ptr()->entry_types();
+ uint8_t* entry_bits = pool->ptr()->entry_bits();
for (intptr_t i = 0; i < length; i++) {
- ObjectPool::EntryType entry_type =
- static_cast<ObjectPool::EntryType>(entry_types[i]);
+ auto entry_type = ObjectPool::TypeBits::decode(entry_bits[i]);
if (entry_type == ObjectPool::kTaggedObject) {
s->Push(pool->ptr()->data()[i].raw_obj_);
}
@@ -1888,13 +1887,11 @@
RawObjectPool* pool = objects_[i];
intptr_t length = pool->ptr()->length_;
s->WriteUnsigned(length);
- uint8_t* entry_types = pool->ptr()->entry_types();
+ uint8_t* entry_bits = pool->ptr()->entry_bits();
for (intptr_t j = 0; j < length; j++) {
- ObjectPool::EntryType entry_type =
- static_cast<ObjectPool::EntryType>(entry_types[j]);
- s->Write<int8_t>(entry_type);
+ s->Write<uint8_t>(entry_bits[j]);
RawObjectPool::Entry& entry = pool->ptr()->data()[j];
- switch (entry_type) {
+ switch (ObjectPool::TypeBits::decode(entry_bits[j])) {
case ObjectPool::kTaggedObject: {
#if !defined(TARGET_ARCH_DBC)
if ((entry.raw_obj_ ==
@@ -1958,11 +1955,10 @@
pool, kObjectPoolCid, ObjectPool::InstanceSize(length), is_vm_object);
pool->ptr()->length_ = length;
for (intptr_t j = 0; j < length; j++) {
- ObjectPool::EntryType entry_type =
- static_cast<ObjectPool::EntryType>(d->Read<int8_t>());
- pool->ptr()->entry_types()[j] = entry_type;
+ const uint8_t entry_bits = d->Read<uint8_t>();
+ pool->ptr()->entry_bits()[j] = entry_bits;
RawObjectPool::Entry& entry = pool->ptr()->data()[j];
- switch (entry_type) {
+ switch (ObjectPool::TypeBits::decode(entry_bits)) {
case ObjectPool::kTaggedObject:
entry.raw_obj_ = d->ReadRef();
break;
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 71c6410..e3b3919 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -85,7 +85,8 @@
DECLARE_FLAG(int, inlining_constant_arguments_min_size_threshold);
DECLARE_FLAG(bool, print_instruction_stats);
-#ifdef DART_PRECOMPILER
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ !defined(TARGET_ARCH_IA32)
class DartPrecompilationPipeline : public DartCompilationPipeline {
public:
@@ -2901,7 +2902,9 @@
ASSERT(pass_state.inline_id_to_function.length() ==
pass_state.caller_inline_id.length());
- Assembler assembler(use_far_branches);
+
+ ObjectPoolWrapper object_pool;
+ Assembler assembler(&object_pool, use_far_branches);
CodeStatistics* function_stats = NULL;
if (FLAG_print_instruction_stats) {
@@ -3508,6 +3511,7 @@
return result;
}
-#endif // DART_PRECOMPILER
+#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ // !defined(TARGET_ARCH_IA32)
} // namespace dart
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index ccbac6c..671e4bd 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -466,7 +466,8 @@
typedef UnorderedHashSet<FunctionsTraits> UniqueFunctionsSet;
-#if defined(DART_PRECOMPILER)
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ !defined(TARGET_ARCH_IA32)
// ObfuscationMap maps Strings to Strings.
class ObfuscationMapTraits {
public:
@@ -670,7 +671,8 @@
static void Deobfuscate(Thread* thread, const GrowableObjectArray& pieces) {}
};
-#endif // DART_PRECOMPILER
+#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ // !defined(TARGET_ARCH_IA32)
} // namespace dart
diff --git a/runtime/vm/compiler/assembler/assembler.cc b/runtime/vm/compiler/assembler/assembler.cc
index 7b7a2ff..8c94874 100644
--- a/runtime/vm/compiler/assembler/assembler.cc
+++ b/runtime/vm/compiler/assembler/assembler.cc
@@ -228,24 +228,23 @@
}
intptr_t ObjectPoolWrapper::AddObject(const Object& obj,
- Patchability patchable) {
+ ObjectPool::Patchability patchable) {
ASSERT(obj.IsNotTemporaryScopedHandle());
- return AddObject(ObjectPoolWrapperEntry(&obj), patchable);
+ return AddObject(ObjectPoolWrapperEntry(&obj, patchable));
}
intptr_t ObjectPoolWrapper::AddImmediate(uword imm) {
- return AddObject(ObjectPoolWrapperEntry(imm, ObjectPool::kImmediate),
- kNotPatchable);
+ return AddObject(ObjectPoolWrapperEntry(imm, ObjectPool::kImmediate,
+ ObjectPool::kNotPatchable));
}
-intptr_t ObjectPoolWrapper::AddObject(ObjectPoolWrapperEntry entry,
- Patchability patchable) {
- ASSERT((entry.type_ != ObjectPool::kTaggedObject) ||
+intptr_t ObjectPoolWrapper::AddObject(ObjectPoolWrapperEntry entry) {
+ ASSERT((entry.type() != ObjectPool::kTaggedObject) ||
(entry.obj_->IsNotTemporaryScopedHandle() &&
(entry.equivalence_ == NULL ||
entry.equivalence_->IsNotTemporaryScopedHandle())));
object_pool_.Add(entry);
- if (patchable == kNotPatchable) {
+ if (entry.patchable() == ObjectPool::kNotPatchable) {
// The object isn't patchable. Record the index for fast lookup.
object_pool_index_table_.Insert(
ObjIndexPair(entry, object_pool_.length() - 1));
@@ -253,47 +252,46 @@
return object_pool_.length() - 1;
}
-intptr_t ObjectPoolWrapper::FindObject(ObjectPoolWrapperEntry entry,
- Patchability patchable) {
+intptr_t ObjectPoolWrapper::FindObject(ObjectPoolWrapperEntry entry) {
// If the object is not patchable, check if we've already got it in the
// object pool.
- if (patchable == kNotPatchable) {
+ if (entry.patchable() == ObjectPool::kNotPatchable) {
intptr_t idx = object_pool_index_table_.LookupValue(entry);
if (idx != ObjIndexPair::kNoIndex) {
return idx;
}
}
- return AddObject(entry, patchable);
+ return AddObject(entry);
}
intptr_t ObjectPoolWrapper::FindObject(const Object& obj,
- Patchability patchable) {
- return FindObject(ObjectPoolWrapperEntry(&obj), patchable);
+ ObjectPool::Patchability patchable) {
+ return FindObject(ObjectPoolWrapperEntry(&obj, patchable));
}
intptr_t ObjectPoolWrapper::FindObject(const Object& obj,
const Object& equivalence) {
- return FindObject(ObjectPoolWrapperEntry(&obj, &equivalence), kNotPatchable);
+ return FindObject(
+ ObjectPoolWrapperEntry(&obj, &equivalence, ObjectPool::kNotPatchable));
}
intptr_t ObjectPoolWrapper::FindImmediate(uword imm) {
- return FindObject(ObjectPoolWrapperEntry(imm, ObjectPool::kImmediate),
- kNotPatchable);
+ return FindObject(ObjectPoolWrapperEntry(imm, ObjectPool::kImmediate,
+ ObjectPool::kNotPatchable));
}
-intptr_t ObjectPoolWrapper::FindNativeFunction(const ExternalLabel* label,
- Patchability patchable) {
- return FindObject(
- ObjectPoolWrapperEntry(label->address(), ObjectPool::kNativeFunction),
- patchable);
+intptr_t ObjectPoolWrapper::FindNativeFunction(
+ const ExternalLabel* label,
+ ObjectPool::Patchability patchable) {
+ return FindObject(ObjectPoolWrapperEntry(
+ label->address(), ObjectPool::kNativeFunction, patchable));
}
intptr_t ObjectPoolWrapper::FindNativeFunctionWrapper(
const ExternalLabel* label,
- Patchability patchable) {
- return FindObject(ObjectPoolWrapperEntry(label->address(),
- ObjectPool::kNativeFunctionWrapper),
- patchable);
+ ObjectPool::Patchability patchable) {
+ return FindObject(ObjectPoolWrapperEntry(
+ label->address(), ObjectPool::kNativeFunctionWrapper, patchable));
}
RawObjectPool* ObjectPoolWrapper::MakeObjectPool() {
@@ -303,8 +301,9 @@
}
const ObjectPool& result = ObjectPool::Handle(ObjectPool::New(len));
for (intptr_t i = 0; i < len; ++i) {
- ObjectPool::EntryType type = object_pool_[i].type_;
- result.SetTypeAt(i, type);
+ auto type = object_pool_[i].type();
+ auto patchable = object_pool_[i].patchable();
+ result.SetTypeAt(i, type, patchable);
if (type == ObjectPool::kTaggedObject) {
result.SetObjectAt(i, *object_pool_[i].obj_);
} else {
diff --git a/runtime/vm/compiler/assembler/assembler.h b/runtime/vm/compiler/assembler/assembler.h
index 3eddf5d..90d106d 100644
--- a/runtime/vm/compiler/assembler/assembler.h
+++ b/runtime/vm/compiler/assembler/assembler.h
@@ -285,19 +285,40 @@
};
struct ObjectPoolWrapperEntry {
- ObjectPoolWrapperEntry() : raw_value_(), type_(), equivalence_() {}
- explicit ObjectPoolWrapperEntry(const Object* obj)
- : obj_(obj), type_(ObjectPool::kTaggedObject), equivalence_(obj) {}
- explicit ObjectPoolWrapperEntry(const Object* obj, const Object* eqv)
- : obj_(obj), type_(ObjectPool::kTaggedObject), equivalence_(eqv) {}
- ObjectPoolWrapperEntry(uword value, ObjectPool::EntryType info)
- : raw_value_(value), type_(info), equivalence_() {}
+ ObjectPoolWrapperEntry() : raw_value_(), entry_bits_(0), equivalence_() {}
+ ObjectPoolWrapperEntry(const Object* obj, ObjectPool::Patchability patchable)
+ : obj_(obj),
+ entry_bits_(ObjectPool::TypeBits::encode(ObjectPool::kTaggedObject) |
+ ObjectPool::PatchableBit::encode(patchable)),
+ equivalence_(obj) {}
+ ObjectPoolWrapperEntry(const Object* obj,
+ const Object* eqv,
+ ObjectPool::Patchability patchable)
+ : obj_(obj),
+ entry_bits_(ObjectPool::TypeBits::encode(ObjectPool::kTaggedObject) |
+ ObjectPool::PatchableBit::encode(patchable)),
+ equivalence_(eqv) {}
+ ObjectPoolWrapperEntry(uword value,
+ ObjectPool::EntryType info,
+ ObjectPool::Patchability patchable)
+ : raw_value_(value),
+ entry_bits_(ObjectPool::TypeBits::encode(info) |
+ ObjectPool::PatchableBit::encode(patchable)),
+ equivalence_() {}
+
+ ObjectPool::EntryType type() const {
+ return ObjectPool::TypeBits::decode(entry_bits_);
+ }
+
+ ObjectPool::Patchability patchable() const {
+ return ObjectPool::PatchableBit::decode(entry_bits_);
+ }
union {
const Object* obj_;
uword raw_value_;
};
- ObjectPool::EntryType type_;
+ uint8_t entry_bits_;
const Object* equivalence_;
};
@@ -312,12 +333,14 @@
static const intptr_t kNoIndex = -1;
ObjIndexPair()
- : key_(static_cast<uword>(NULL), ObjectPool::kTaggedObject),
+ : key_(static_cast<uword>(NULL),
+ ObjectPool::kTaggedObject,
+ ObjectPool::kPatchable),
value_(kNoIndex) {}
ObjIndexPair(Key key, Value value) : value_(value) {
- key_.type_ = key.type_;
- if (key.type_ == ObjectPool::kTaggedObject) {
+ key_.entry_bits_ = key.entry_bits_;
+ if (key.type() == ObjectPool::kTaggedObject) {
key_.obj_ = key.obj_;
key_.equivalence_ = key.equivalence_;
} else {
@@ -330,7 +353,7 @@
static Value ValueOf(Pair kv) { return kv.value_; }
static intptr_t Hashcode(Key key) {
- if (key.type_ != ObjectPool::kTaggedObject) {
+ if (key.type() != ObjectPool::kTaggedObject) {
return key.raw_value_;
}
if (key.obj_->IsSmi()) {
@@ -345,8 +368,8 @@
}
static inline bool IsKeyEqual(Pair kv, Key key) {
- if (kv.key_.type_ != key.type_) return false;
- if (kv.key_.type_ == ObjectPool::kTaggedObject) {
+ if (kv.key_.entry_bits_ != key.entry_bits_) return false;
+ if (kv.key_.type() == ObjectPool::kTaggedObject) {
return (kv.key_.obj_->raw() == key.obj_->raw()) &&
(kv.key_.equivalence_->raw() == key.equivalence_->raw());
}
@@ -358,30 +381,27 @@
Value value_;
};
-enum Patchability {
- kPatchable,
- kNotPatchable,
-};
-
class ObjectPoolWrapper : public ValueObject {
public:
- intptr_t AddObject(const Object& obj, Patchability patchable = kNotPatchable);
+ intptr_t AddObject(
+ const Object& obj,
+ ObjectPool::Patchability patchable = ObjectPool::kNotPatchable);
intptr_t AddImmediate(uword imm);
-
- intptr_t FindObject(const Object& obj,
- Patchability patchable = kNotPatchable);
+ intptr_t FindObject(
+ const Object& obj,
+ ObjectPool::Patchability patchable = ObjectPool::kNotPatchable);
intptr_t FindObject(const Object& obj, const Object& equivalence);
intptr_t FindImmediate(uword imm);
intptr_t FindNativeFunction(const ExternalLabel* label,
- Patchability patchable);
+ ObjectPool::Patchability patchable);
intptr_t FindNativeFunctionWrapper(const ExternalLabel* label,
- Patchability patchable);
+ ObjectPool::Patchability patchable);
RawObjectPool* MakeObjectPool();
private:
- intptr_t AddObject(ObjectPoolWrapperEntry entry, Patchability patchable);
- intptr_t FindObject(ObjectPoolWrapperEntry entry, Patchability patchable);
+ intptr_t AddObject(ObjectPoolWrapperEntry entry);
+ intptr_t FindObject(ObjectPoolWrapperEntry entry);
// Objects and jump targets.
GrowableArray<ObjectPoolWrapperEntry> object_pool_;
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 1893e92..6f6ffce 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -1377,7 +1377,7 @@
}
intptr_t Assembler::FindImmediate(int32_t imm) {
- return object_pool_wrapper_.FindImmediate(imm);
+ return object_pool_wrapper().FindImmediate(imm);
}
// Uses a code sequence that can easily be decoded.
@@ -1480,8 +1480,8 @@
// Make sure that class CallPattern is able to decode this load from the
// object pool.
const int32_t offset = ObjectPool::element_offset(
- is_unique ? object_pool_wrapper_.AddObject(object)
- : object_pool_wrapper_.FindObject(object));
+ is_unique ? object_pool_wrapper().AddObject(object)
+ : object_pool_wrapper().FindObject(object));
LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, pp, cond);
} else {
UNREACHABLE();
@@ -1502,16 +1502,16 @@
const Function& function,
Register new_pp) {
const int32_t offset =
- ObjectPool::element_offset(object_pool_wrapper_.FindObject(function));
+ ObjectPool::element_offset(object_pool_wrapper().FindObject(function));
LoadWordFromPoolOffset(dst, offset - kHeapObjectTag, new_pp, AL);
}
void Assembler::LoadNativeEntry(Register rd,
const ExternalLabel* label,
- Patchability patchable,
+ ObjectPool::Patchability patchable,
Condition cond) {
const int32_t offset = ObjectPool::element_offset(
- object_pool_wrapper_.FindNativeFunction(label, patchable));
+ object_pool_wrapper().FindNativeFunction(label, patchable));
LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP, cond);
}
@@ -2449,40 +2449,40 @@
}
void Assembler::Branch(const StubEntry& stub_entry,
- Patchability patchable,
+ ObjectPool::Patchability patchable,
Register pp,
Condition cond) {
const Code& target_code = Code::ZoneHandle(stub_entry.code());
const int32_t offset = ObjectPool::element_offset(
- object_pool_wrapper_.FindObject(target_code, patchable));
+ object_pool_wrapper().FindObject(target_code, patchable));
LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, pp, cond);
ldr(IP, FieldAddress(CODE_REG, Code::entry_point_offset()), cond);
bx(IP, cond);
}
void Assembler::BranchLink(const Code& target,
- Patchability patchable,
+ ObjectPool::Patchability patchable,
Code::EntryKind entry_kind) {
// Make sure that class CallPattern is able to patch the label referred
// to by this code sequence.
// For added code robustness, use 'blx lr' in a patchable sequence and
// use 'blx ip' in a non-patchable sequence (see other BranchLink flavors).
const int32_t offset = ObjectPool::element_offset(
- object_pool_wrapper_.FindObject(target, patchable));
+ object_pool_wrapper().FindObject(target, patchable));
LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, PP, AL);
ldr(LR, FieldAddress(CODE_REG, Code::entry_point_offset(entry_kind)));
blx(LR); // Use blx instruction so that the return branch prediction works.
}
void Assembler::BranchLink(const StubEntry& stub_entry,
- Patchability patchable) {
+ ObjectPool::Patchability patchable) {
const Code& code = Code::ZoneHandle(stub_entry.code());
BranchLink(code, patchable);
}
void Assembler::BranchLinkPatchable(const Code& target,
Code::EntryKind entry_kind) {
- BranchLink(target, kPatchable, entry_kind);
+ BranchLink(target, ObjectPool::kPatchable, entry_kind);
}
void Assembler::BranchLinkToRuntime() {
@@ -2509,7 +2509,7 @@
// For added code robustness, use 'blx lr' in a patchable sequence and
// use 'blx ip' in a non-patchable sequence (see other BranchLink flavors).
const int32_t offset = ObjectPool::element_offset(
- object_pool_wrapper_.FindObject(target, equivalence));
+ object_pool_wrapper().FindObject(target, equivalence));
LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, PP, AL);
ldr(LR, FieldAddress(CODE_REG, Code::entry_point_offset(entry_kind)));
blx(LR); // Use blx instruction so that the return branch prediction works.
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index de2fa1f..90d554c 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -338,8 +338,10 @@
class Assembler : public ValueObject {
public:
- explicit Assembler(bool use_far_branches = false)
+ explicit Assembler(ObjectPoolWrapper* object_pool_wrapper,
+ bool use_far_branches = false)
: buffer_(),
+ object_pool_wrapper_(object_pool_wrapper),
prologue_offset_(-1),
has_single_entry_point_(true),
use_far_branches_(use_far_branches),
@@ -375,10 +377,10 @@
return buffer_.pointer_offsets();
}
- ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
+ ObjectPoolWrapper& object_pool_wrapper() { return *object_pool_wrapper_; }
RawObjectPool* MakeObjectPool() {
- return object_pool_wrapper_.MakeObjectPool();
+ return object_pool_wrapper_->MakeObjectPool();
}
bool use_far_branches() const {
@@ -690,14 +692,15 @@
void blx(Register rm, Condition cond = AL);
void Branch(const StubEntry& stub_entry,
- Patchability patchable = kNotPatchable,
+ ObjectPool::Patchability patchable = ObjectPool::kNotPatchable,
Register pp = PP,
Condition cond = AL);
- void BranchLink(const StubEntry& stub_entry,
- Patchability patchable = kNotPatchable);
+ void BranchLink(
+ const StubEntry& stub_entry,
+ ObjectPool::Patchability patchable = ObjectPool::kNotPatchable);
void BranchLink(const Code& code,
- Patchability patchable,
+ ObjectPool::Patchability patchable,
Code::EntryKind entry_kind = Code::EntryKind::kNormal);
void BranchLinkToRuntime();
@@ -793,7 +796,7 @@
Register new_pp);
void LoadNativeEntry(Register dst,
const ExternalLabel* label,
- Patchability patchable,
+ ObjectPool::Patchability patchable,
Condition cond = AL);
void PushObject(const Object& object);
void CompareObject(Register rn, const Object& object);
@@ -1137,7 +1140,7 @@
private:
AssemblerBuffer buffer_; // Contains position independent code.
- ObjectPoolWrapper object_pool_wrapper_;
+ ObjectPoolWrapper* object_pool_wrapper_;
int32_t prologue_offset_;
bool has_single_entry_point_;
bool use_far_branches_;
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index cd2b856..0d6db19 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -21,8 +21,10 @@
DEFINE_FLAG(bool, use_far_branches, false, "Always use far branches");
-Assembler::Assembler(bool use_far_branches)
+Assembler::Assembler(ObjectPoolWrapper* object_pool_wrapper,
+ bool use_far_branches)
: buffer_(),
+ object_pool_wrapper_(object_pool_wrapper),
prologue_offset_(-1),
has_single_entry_point_(true),
use_far_branches_(use_far_branches),
@@ -407,7 +409,7 @@
}
intptr_t Assembler::FindImmediate(int64_t imm) {
- return object_pool_wrapper_.FindImmediate(imm);
+ return object_pool_wrapper().FindImmediate(imm);
}
bool Assembler::CanLoadFromObjectPool(const Object& object) const {
@@ -433,9 +435,9 @@
void Assembler::LoadNativeEntry(Register dst,
const ExternalLabel* label,
- Patchability patchable) {
+ ObjectPool::Patchability patchable) {
const int32_t offset = ObjectPool::element_offset(
- object_pool_wrapper_.FindNativeFunction(label, patchable));
+ object_pool_wrapper().FindNativeFunction(label, patchable));
LoadWordFromPoolOffset(dst, offset);
}
@@ -452,8 +454,8 @@
ldr(dst, Address(THR, Thread::OffsetFromThread(object)));
} else if (CanLoadFromObjectPool(object)) {
const int32_t offset = ObjectPool::element_offset(
- is_unique ? object_pool_wrapper_.AddObject(object)
- : object_pool_wrapper_.FindObject(object));
+ is_unique ? object_pool_wrapper().AddObject(object)
+ : object_pool_wrapper().FindObject(object));
LoadWordFromPoolOffset(dst, offset);
} else {
ASSERT(object.IsSmi());
@@ -467,7 +469,7 @@
ASSERT(!constant_pool_allowed());
ASSERT(new_pp != PP);
const int32_t offset =
- ObjectPool::element_offset(object_pool_wrapper_.FindObject(function));
+ ObjectPool::element_offset(object_pool_wrapper().FindObject(function));
ASSERT(Address::CanHoldOffset(offset));
ldr(dst, Address(new_pp, offset));
}
@@ -615,31 +617,31 @@
void Assembler::Branch(const StubEntry& stub_entry,
Register pp,
- Patchability patchable) {
+ ObjectPool::Patchability patchable) {
const Code& target = Code::ZoneHandle(stub_entry.code());
const int32_t offset = ObjectPool::element_offset(
- object_pool_wrapper_.FindObject(target, patchable));
+ object_pool_wrapper().FindObject(target, patchable));
LoadWordFromPoolOffset(CODE_REG, offset, pp);
ldr(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
br(TMP);
}
void Assembler::BranchPatchable(const StubEntry& stub_entry) {
- Branch(stub_entry, PP, kPatchable);
+ Branch(stub_entry, PP, ObjectPool::kPatchable);
}
void Assembler::BranchLink(const StubEntry& stub_entry,
- Patchability patchable) {
+ ObjectPool::Patchability patchable) {
const Code& target = Code::ZoneHandle(stub_entry.code());
const int32_t offset = ObjectPool::element_offset(
- object_pool_wrapper_.FindObject(target, patchable));
+ object_pool_wrapper().FindObject(target, patchable));
LoadWordFromPoolOffset(CODE_REG, offset);
ldr(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
blr(TMP);
}
void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) {
- BranchLink(stub_entry, kPatchable);
+ BranchLink(stub_entry, ObjectPool::kPatchable);
}
void Assembler::BranchLinkToRuntime() {
@@ -652,7 +654,7 @@
const Object& equivalence) {
const Code& target = Code::ZoneHandle(stub_entry.code());
const int32_t offset = ObjectPool::element_offset(
- object_pool_wrapper_.FindObject(target, equivalence));
+ object_pool_wrapper().FindObject(target, equivalence));
LoadWordFromPoolOffset(CODE_REG, offset);
ldr(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
blr(TMP);
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index bd5bb86..3cbafae 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -425,7 +425,8 @@
class Assembler : public ValueObject {
public:
- explicit Assembler(bool use_far_branches = false);
+ explicit Assembler(ObjectPoolWrapper* object_pool_wrapper,
+ bool use_far_branches = false);
~Assembler() {}
void PushRegister(Register r) { Push(r); }
@@ -462,10 +463,10 @@
return buffer_.pointer_offsets();
}
- ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
+ ObjectPoolWrapper& object_pool_wrapper() { return *object_pool_wrapper_; }
RawObjectPool* MakeObjectPool() {
- return object_pool_wrapper_.MakeObjectPool();
+ return object_pool_wrapper_->MakeObjectPool();
}
bool use_far_branches() const {
@@ -1374,11 +1375,12 @@
void Branch(const StubEntry& stub_entry,
Register pp,
- Patchability patchable = kNotPatchable);
+ ObjectPool::Patchability patchable = ObjectPool::kNotPatchable);
void BranchPatchable(const StubEntry& stub_entry);
- void BranchLink(const StubEntry& stub_entry,
- Patchability patchable = kNotPatchable);
+ void BranchLink(
+ const StubEntry& stub_entry,
+ ObjectPool::Patchability patchable = ObjectPool::kNotPatchable);
void BranchLinkPatchable(const StubEntry& stub_entry);
void BranchLinkToRuntime();
@@ -1490,7 +1492,7 @@
bool CanLoadFromObjectPool(const Object& object) const;
void LoadNativeEntry(Register dst,
const ExternalLabel* label,
- Patchability patchable);
+ ObjectPool::Patchability patchable);
void LoadFunctionFromCalleePool(Register dst,
const Function& function,
Register new_pp);
@@ -1607,7 +1609,7 @@
private:
AssemblerBuffer buffer_; // Contains position independent code.
- ObjectPoolWrapper object_pool_wrapper_;
+ ObjectPoolWrapper* object_pool_wrapper_;
int32_t prologue_offset_;
bool has_single_entry_point_;
bool use_far_branches_;
diff --git a/runtime/vm/compiler/assembler/assembler_dbc.h b/runtime/vm/compiler/assembler/assembler_dbc.h
index 45bdb9e..7642b4b7 100644
--- a/runtime/vm/compiler/assembler/assembler_dbc.h
+++ b/runtime/vm/compiler/assembler/assembler_dbc.h
@@ -27,7 +27,9 @@
class Assembler : public ValueObject {
public:
- explicit Assembler(bool use_far_branches = false) : buffer_(), comments_() {}
+ explicit Assembler(ObjectPoolWrapper* object_pool_wrapper,
+ bool use_far_branches = false)
+ : buffer_(), object_pool_wrapper_(object_pool_wrapper), comments_() {}
~Assembler() {}
@@ -48,10 +50,10 @@
return buffer_.pointer_offsets();
}
- ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
+ ObjectPoolWrapper& object_pool_wrapper() { return *object_pool_wrapper_; }
RawObjectPool* MakeObjectPool() {
- return object_pool_wrapper_.MakeObjectPool();
+ return object_pool_wrapper_->MakeObjectPool();
}
void FinalizeInstructions(const MemoryRegion& region) {
@@ -124,7 +126,7 @@
private:
AssemblerBuffer buffer_; // Contains position independent code.
- ObjectPoolWrapper object_pool_wrapper_;
+ ObjectPoolWrapper* object_pool_wrapper_;
class CodeComment : public ZoneAllocated {
public:
diff --git a/runtime/vm/compiler/assembler/assembler_dbc_test.cc b/runtime/vm/compiler/assembler/assembler_dbc_test.cc
index ef3d7c6..fba04bd 100644
--- a/runtime/vm/compiler/assembler/assembler_dbc_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_dbc_test.cc
@@ -65,7 +65,8 @@
static void MakeDummyInstanceCall(Assembler* assembler, const Object& result) {
// Make a dummy function.
- Assembler _assembler_;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler _assembler_(&object_pool_wrapper);
GenerateDummyCode(&_assembler_, result);
const char* dummy_function_name = "dummy_instance_function";
const Function& dummy_instance_function =
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 19a00b4..1684bb6 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -223,12 +223,16 @@
class Assembler : public ValueObject {
public:
- explicit Assembler(bool use_far_branches = false)
+ explicit Assembler(ObjectPoolWrapper* object_pool_wrapper,
+ bool use_far_branches = false)
: buffer_(),
prologue_offset_(-1),
jit_cookie_(0),
comments_(),
code_(Code::ZoneHandle()) {
+ // On ia32 we don't use object pools.
+ USE(object_pool_wrapper);
+
// This mode is only needed and implemented for ARM.
ASSERT(!use_far_branches);
}
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index bee1638..5ce6565 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -22,8 +22,10 @@
DECLARE_FLAG(bool, check_code_pointer);
DECLARE_FLAG(bool, inline_alloc);
-Assembler::Assembler(bool use_far_branches)
+Assembler::Assembler(ObjectPoolWrapper* object_pool_wrapper,
+ bool use_far_branches)
: buffer_(),
+ object_pool_wrapper_(object_pool_wrapper),
prologue_offset_(-1),
has_single_entry_point_(true),
comments_(),
@@ -45,9 +47,9 @@
void Assembler::LoadNativeEntry(Register dst,
const ExternalLabel* label,
- Patchability patchable) {
+ ObjectPool::Patchability patchable) {
const int32_t offset = ObjectPool::element_offset(
- object_pool_wrapper_.FindNativeFunction(label, patchable));
+ object_pool_wrapper().FindNativeFunction(label, patchable));
LoadWordFromPoolOffset(dst, offset - kHeapObjectTag);
}
@@ -66,7 +68,8 @@
ASSERT(constant_pool_allowed());
const Code& target = Code::ZoneHandle(stub_entry.code());
intptr_t call_start = buffer_.GetPosition();
- const intptr_t idx = object_pool_wrapper_.AddObject(target, kPatchable);
+ const intptr_t idx =
+ object_pool_wrapper().AddObject(target, ObjectPool::kPatchable);
const int32_t offset = ObjectPool::element_offset(idx);
LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag);
movq(TMP, FieldAddress(CODE_REG, Code::entry_point_offset(entry_kind)));
@@ -79,7 +82,7 @@
Code::EntryKind entry_kind) {
ASSERT(constant_pool_allowed());
const Code& target = Code::ZoneHandle(stub_entry.code());
- const intptr_t idx = object_pool_wrapper_.FindObject(target, equivalence);
+ const intptr_t idx = object_pool_wrapper().FindObject(target, equivalence);
const int32_t offset = ObjectPool::element_offset(idx);
LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag);
movq(TMP, FieldAddress(CODE_REG, Code::entry_point_offset(entry_kind)));
@@ -89,7 +92,8 @@
void Assembler::Call(const StubEntry& stub_entry) {
ASSERT(constant_pool_allowed());
const Code& target = Code::ZoneHandle(stub_entry.code());
- const intptr_t idx = object_pool_wrapper_.FindObject(target, kNotPatchable);
+ const intptr_t idx =
+ object_pool_wrapper().FindObject(target, ObjectPool::kNotPatchable);
const int32_t offset = ObjectPool::element_offset(idx);
LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag);
movq(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
@@ -464,6 +468,13 @@
EmitUint8(imm.value() & 0xFF);
}
+void Assembler::testb(const Address& address, Register reg) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitOperandREX(reg, address, REX_NONE);
+ EmitUint8(0x84);
+ EmitOperand(reg & 7, address);
+}
+
void Assembler::testq(Register reg, const Immediate& imm) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
if (imm.is_uint8()) {
@@ -925,7 +936,8 @@
void Assembler::JmpPatchable(const StubEntry& stub_entry, Register pp) {
ASSERT((pp != PP) || constant_pool_allowed());
const Code& target = Code::ZoneHandle(stub_entry.code());
- const intptr_t idx = object_pool_wrapper_.AddObject(target, kPatchable);
+ const intptr_t idx =
+ object_pool_wrapper().AddObject(target, ObjectPool::kPatchable);
const int32_t offset = ObjectPool::element_offset(idx);
movq(CODE_REG, Address::AddressBaseImm32(pp, offset - kHeapObjectTag));
movq(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
@@ -935,7 +947,8 @@
void Assembler::Jmp(const StubEntry& stub_entry, Register pp) {
ASSERT((pp != PP) || constant_pool_allowed());
const Code& target = Code::ZoneHandle(stub_entry.code());
- const intptr_t idx = object_pool_wrapper_.FindObject(target, kNotPatchable);
+ const intptr_t idx =
+ object_pool_wrapper().FindObject(target, ObjectPool::kNotPatchable);
const int32_t offset = ObjectPool::element_offset(idx);
movq(CODE_REG, FieldAddress(pp, offset));
movq(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
@@ -1120,8 +1133,8 @@
if (Thread::CanLoadFromThread(object)) {
movq(dst, Address(THR, Thread::OffsetFromThread(object)));
} else if (CanLoadFromObjectPool(object)) {
- const intptr_t idx = is_unique ? object_pool_wrapper_.AddObject(object)
- : object_pool_wrapper_.FindObject(object);
+ const intptr_t idx = is_unique ? object_pool_wrapper().AddObject(object)
+ : object_pool_wrapper().FindObject(object);
const int32_t offset = ObjectPool::element_offset(idx);
LoadWordFromPoolOffset(dst, offset - kHeapObjectTag);
} else {
@@ -1135,7 +1148,8 @@
Register new_pp) {
ASSERT(!constant_pool_allowed());
ASSERT(new_pp != PP);
- const intptr_t idx = object_pool_wrapper_.FindObject(function, kNotPatchable);
+ const intptr_t idx =
+ object_pool_wrapper().FindObject(function, ObjectPool::kNotPatchable);
const int32_t offset = ObjectPool::element_offset(idx);
movq(dst, Address::AddressBaseImm32(new_pp, offset - kHeapObjectTag));
}
@@ -1183,7 +1197,8 @@
if (Thread::CanLoadFromThread(object)) {
cmpq(reg, Address(THR, Thread::OffsetFromThread(object)));
} else if (CanLoadFromObjectPool(object)) {
- const intptr_t idx = object_pool_wrapper_.FindObject(object, kNotPatchable);
+ const intptr_t idx =
+ object_pool_wrapper().FindObject(object, ObjectPool::kNotPatchable);
const int32_t offset = ObjectPool::element_offset(idx);
cmpq(reg, Address(PP, offset - kHeapObjectTag));
} else {
@@ -1193,7 +1208,7 @@
}
intptr_t Assembler::FindImmediate(int64_t imm) {
- return object_pool_wrapper_.FindImmediate(imm);
+ return object_pool_wrapper().FindImmediate(imm);
}
void Assembler::LoadImmediate(Register reg, const Immediate& imm) {
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 5b86aca..bec61ed 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -277,7 +277,8 @@
class Assembler : public ValueObject {
public:
- explicit Assembler(bool use_far_branches = false);
+ explicit Assembler(ObjectPoolWrapper* object_pool_wrapper,
+ bool use_far_branches = false);
~Assembler() {}
@@ -523,6 +524,7 @@
void testl(Register reg, const Immediate& imm) { testq(reg, imm); }
void testb(const Address& address, const Immediate& imm);
+ void testb(const Address& address, Register reg);
void testq(Register reg, const Immediate& imm);
void TestImmediate(Register dst, const Immediate& imm);
@@ -685,7 +687,7 @@
void LoadUniqueObject(Register dst, const Object& obj);
void LoadNativeEntry(Register dst,
const ExternalLabel* label,
- Patchability patchable);
+ ObjectPool::Patchability patchable);
void LoadFunctionFromCalleePool(Register dst,
const Function& function,
Register new_pp);
@@ -836,10 +838,10 @@
return buffer_.pointer_offsets();
}
- ObjectPoolWrapper& object_pool_wrapper() { return object_pool_wrapper_; }
+ ObjectPoolWrapper& object_pool_wrapper() { return *object_pool_wrapper_; }
RawObjectPool* MakeObjectPool() {
- return object_pool_wrapper_.MakeObjectPool();
+ return object_pool_wrapper_->MakeObjectPool();
}
void FinalizeInstructions(const MemoryRegion& region) {
@@ -961,7 +963,7 @@
private:
AssemblerBuffer buffer_;
- ObjectPoolWrapper object_pool_wrapper_;
+ ObjectPoolWrapper* object_pool_wrapper_;
intptr_t prologue_offset_;
bool has_single_entry_point_;
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index e478f97..a478cf7 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -637,6 +637,38 @@
"ret\n");
}
+ASSEMBLER_TEST_GENERATE(Testb3, assembler) {
+ Label zero;
+ __ pushq(CallingConventions::kArg1Reg);
+ __ movq(RDX, Immediate(0x10));
+ __ testb(Address(RSP, 0), RDX);
+ __ j(ZERO, &zero);
+ __ movq(RAX, Immediate(1));
+ __ popq(RCX);
+ __ ret();
+ __ Bind(&zero);
+ __ movq(RAX, Immediate(0));
+ __ popq(RCX);
+ __ ret();
+}
+
+ASSEMBLER_TEST_RUN(Testb3, test) {
+ typedef int (*TestbCode)(int);
+ EXPECT_EQ(1, reinterpret_cast<TestbCode>(test->entry())(0x11));
+ EXPECT_EQ(0, reinterpret_cast<TestbCode>(test->entry())(0x101));
+ EXPECT_DISASSEMBLY_NOT_WINDOWS(
+ "push rdi\n"
+ "movl rdx,0x10\n"
+ "testb rdx,[rsp]\n"
+ "jz 0x................\n"
+ "movl rax,1\n"
+ "pop rcx\n"
+ "ret\n"
+ "movl rax,0\n"
+ "pop rcx\n"
+ "ret\n");
+}
+
ASSEMBLER_TEST_GENERATE(Increment, assembler) {
__ movq(RAX, Immediate(0));
__ pushq(RAX);
diff --git a/runtime/vm/compiler/assembler/disassembler_test.cc b/runtime/vm/compiler/assembler/disassembler_test.cc
index a55a3b8..86f6371 100644
--- a/runtime/vm/compiler/assembler/disassembler_test.cc
+++ b/runtime/vm/compiler/assembler/disassembler_test.cc
@@ -14,7 +14,9 @@
#if !defined(PRODUCT) && !defined(TARGET_ARCH_DBC)
TEST_CASE(Disassembler) {
- Assembler assembler;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper);
+
// The used instructions work on all platforms.
Register reg = static_cast<Register>(0);
assembler.PopRegister(reg);
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index dc2d982..a6f8c52 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1407,7 +1407,7 @@
void FlowGraph::RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis) {
// Augment live_phis with those that have implicit real used at
// potentially throwing instructions if there is a try-catch in this graph.
- if (graph_entry()->SuccessorCount() > 1) {
+ if (!graph_entry()->catch_entries().is_empty()) {
for (BlockIterator it(postorder_iterator()); !it.Done(); it.Advance()) {
JoinEntryInstr* join = it.Current()->AsJoinEntry();
if (join == NULL) continue;
@@ -1693,7 +1693,7 @@
ConvertUse(it.Current(), from_rep);
}
- if (graph_entry()->SuccessorCount() > 1) {
+ if (!graph_entry()->catch_entries().is_empty()) {
for (Value::Iterator it(def->env_use_list()); !it.Done(); it.Advance()) {
Value* use = it.Current();
if (use->instruction()->MayThrow() &&
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index d79134d..8762e1b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -765,11 +765,11 @@
// on the call site to find out at which pool index the destination name is
// located.
const intptr_t sub_type_cache_index = __ object_pool_wrapper().AddObject(
- Object::null_object(), Patchability::kPatchable);
+ Object::null_object(), ObjectPool::Patchability::kPatchable);
const intptr_t sub_type_cache_offset =
ObjectPool::element_offset(sub_type_cache_index) - kHeapObjectTag;
- const intptr_t dst_name_index =
- __ object_pool_wrapper().AddObject(dst_name, Patchability::kPatchable);
+ const intptr_t dst_name_index = __ object_pool_wrapper().AddObject(
+ dst_name, ObjectPool::Patchability::kPatchable);
ASSERT((sub_type_cache_index + 1) == dst_name_index);
ASSERT(__ constant_pool_allowed());
@@ -839,7 +839,8 @@
}
__ CompareImmediate(R3, GetOptimizationThreshold());
ASSERT(function_reg == R8);
- __ Branch(*StubCode::OptimizeFunction_entry(), kNotPatchable, new_pp, GE);
+ __ Branch(*StubCode::OptimizeFunction_entry(), ObjectPool::kNotPatchable,
+ new_pp, GE);
}
__ Comment("Enter frame");
if (flow_graph().IsCompiledForOsr()) {
@@ -912,6 +913,7 @@
LocationSummary* locs) {
__ BranchLink(stub_entry);
EmitCallsiteMetadata(token_pos, Thread::kNoDeoptId, kind, locs);
+ AddStubCallTarget(Code::ZoneHandle(stub_entry.code()));
}
void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index ddd491f..358afcf 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -742,11 +742,11 @@
// on the call site to find out at which pool index the destination name is
// located.
const intptr_t sub_type_cache_index = __ object_pool_wrapper().AddObject(
- Object::null_object(), Patchability::kPatchable);
+ Object::null_object(), ObjectPool::Patchability::kPatchable);
const intptr_t sub_type_cache_offset =
ObjectPool::element_offset(sub_type_cache_index);
- const intptr_t dst_name_index =
- __ object_pool_wrapper().AddObject(dst_name, Patchability::kPatchable);
+ const intptr_t dst_name_index = __ object_pool_wrapper().AddObject(
+ dst_name, ObjectPool::Patchability::kPatchable);
ASSERT((sub_type_cache_index + 1) == dst_name_index);
ASSERT(__ constant_pool_allowed());
@@ -893,6 +893,7 @@
LocationSummary* locs) {
__ BranchLink(stub_entry);
EmitCallsiteMetadata(token_pos, Thread::kNoDeoptId, kind, locs);
+ AddStubCallTarget(Code::ZoneHandle(stub_entry.code()));
}
void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 821d8c3..69dae4c 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -852,6 +852,7 @@
LocationSummary* locs) {
__ Call(stub_entry);
EmitCallsiteMetadata(token_pos, Thread::kNoDeoptId, kind, locs);
+ AddStubCallTarget(Code::ZoneHandle(stub_entry.code()));
}
void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index c96b0a1..3259e3e 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -756,11 +756,11 @@
// on the call site to find out at which pool index the destination name is
// located.
const intptr_t sub_type_cache_index = __ object_pool_wrapper().AddObject(
- Object::null_object(), Patchability::kPatchable);
+ Object::null_object(), ObjectPool::Patchability::kPatchable);
const intptr_t sub_type_cache_offset =
ObjectPool::element_offset(sub_type_cache_index) - kHeapObjectTag;
- const intptr_t dst_name_index =
- __ object_pool_wrapper().AddObject(dst_name, Patchability::kPatchable);
+ const intptr_t dst_name_index = __ object_pool_wrapper().AddObject(
+ dst_name, ObjectPool::Patchability::kPatchable);
ASSERT((sub_type_cache_index + 1) == dst_name_index);
ASSERT(__ constant_pool_allowed());
@@ -902,6 +902,7 @@
LocationSummary* locs) {
__ Call(stub_entry);
EmitCallsiteMetadata(token_pos, Thread::kNoDeoptId, kind, locs);
+ AddStubCallTarget(Code::ZoneHandle(stub_entry.code()));
}
void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index e4fc014..d767ec2 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -3193,12 +3193,15 @@
ClosureCallInstr(Value* function,
ClosureCallNode* node,
PushArgumentsArray* arguments,
- intptr_t deopt_id)
+ intptr_t deopt_id,
+ Code::EntryKind entry_kind = Code::EntryKind::kNormal)
: TemplateDartCall(deopt_id,
node->arguments()->type_args_len(),
node->arguments()->names(),
arguments,
- node->token_pos()) {
+ node->token_pos()),
+ entry_kind_(entry_kind) {
+ ASSERT(entry_kind != Code::EntryKind::kMonomorphic);
ASSERT(!arguments->is_empty());
SetInputAt(0, function);
}
@@ -3208,12 +3211,14 @@
intptr_t type_args_len,
const Array& argument_names,
TokenPosition token_pos,
- intptr_t deopt_id)
+ intptr_t deopt_id,
+ Code::EntryKind entry_kind = Code::EntryKind::kNormal)
: TemplateDartCall(deopt_id,
type_args_len,
argument_names,
arguments,
- token_pos) {
+ token_pos),
+ entry_kind_(entry_kind) {
ASSERT(!arguments->is_empty());
SetInputAt(0, function);
}
@@ -3227,9 +3232,13 @@
virtual bool HasUnknownSideEffects() const { return true; }
+ Code::EntryKind entry_kind() const { return entry_kind_; }
+
PRINT_OPERANDS_TO_SUPPORT
private:
+ const Code::EntryKind entry_kind_;
+
DISALLOW_COPY_AND_ASSIGN(ClosureCallInstr);
};
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 3d550e2..44982d3 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -265,25 +265,14 @@
// R0: Function.
ASSERT(locs()->in(0).reg() == R0);
__ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
- __ ldr(R2, FieldAddress(R0, Function::entry_point_offset()));
+ __ ldr(R2, FieldAddress(R0, Code::function_entry_point_offset(entry_kind())));
// R2: instructions entry point.
// R9: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
__ LoadImmediate(R9, 0);
__ blx(R2);
- compiler->RecordSafepoint(locs());
- compiler->EmitCatchEntryState();
- // Marks either the continuation point in unoptimized code or the
- // deoptimization point in optimized code, after call.
- const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
- if (compiler->is_optimizing()) {
- compiler->AddDeoptIndexAtCall(deopt_id_after);
- }
- // Add deoptimization continuation point after the call and before the
- // arguments are removed.
- // In optimized code this descriptor is needed for exception handling.
- compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after,
- token_pos());
+ compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
+ RawPcDescriptors::kOther, locs());
__ Drop(argument_count);
}
@@ -992,7 +981,9 @@
}
__ LoadImmediate(R1, argc_tag);
ExternalLabel label(entry);
- __ LoadNativeEntry(R9, &label, link_lazily() ? kPatchable : kNotPatchable);
+ __ LoadNativeEntry(
+ R9, &label,
+ link_lazily() ? ObjectPool::kPatchable : ObjectPool::kNotPatchable);
if (link_lazily()) {
compiler->GeneratePatchableCall(token_pos(), *stub_entry,
RawPcDescriptors::kOther, locs());
@@ -2052,7 +2043,6 @@
compiler->SaveLiveRegisters(locs);
compiler->GenerateCall(TokenPosition::kNoSource, // No token position.
stub_entry, RawPcDescriptors::kOther, locs);
- compiler->AddStubCallTarget(stub);
__ MoveRegister(result_, R0);
compiler->RestoreLiveRegisters(locs);
__ b(exit_label());
@@ -2578,9 +2568,6 @@
return;
}
}
- const Code& stub = Code::ZoneHandle(compiler->zone(),
- StubCode::AllocateArray_entry()->code());
- compiler->AddStubCallTarget(stub);
compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
*StubCode::AllocateArray_entry(),
RawPcDescriptors::kOther, locs());
@@ -2858,9 +2845,6 @@
compiler->SaveLiveRegisters(locs);
__ LoadImmediate(R1, instruction()->num_context_variables());
- const Code& stub = Code::ZoneHandle(
- compiler->zone(), StubCode::AllocateContext_entry()->code());
- compiler->AddStubCallTarget(stub);
compiler->GenerateCall(instruction()->token_pos(),
*StubCode::AllocateContext_entry(),
RawPcDescriptors::kOther, locs);
@@ -6759,7 +6743,6 @@
const StubEntry stub_entry(stub);
compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther,
locs());
- compiler->AddStubCallTarget(stub);
__ Drop(ArgumentCount()); // Discard arguments.
}
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index dfe94b4..6fb2171 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -268,19 +268,8 @@
__ LoadImmediate(R5, 0);
//??
__ blr(R2);
- compiler->RecordSafepoint(locs());
- compiler->EmitCatchEntryState();
- // Marks either the continuation point in unoptimized code or the
- // deoptimization point in optimized code, after call.
- const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
- if (compiler->is_optimizing()) {
- compiler->AddDeoptIndexAtCall(deopt_id_after);
- }
- // Add deoptimization continuation point after the call and before the
- // arguments are removed.
- // In optimized code this descriptor is needed for exception handling.
- compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after,
- token_pos());
+ compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
+ RawPcDescriptors::kOther, locs());
__ Drop(argument_count);
}
@@ -878,7 +867,9 @@
}
__ LoadImmediate(R1, argc_tag);
ExternalLabel label(entry);
- __ LoadNativeEntry(R5, &label, link_lazily() ? kPatchable : kNotPatchable);
+ __ LoadNativeEntry(
+ R5, &label,
+ link_lazily() ? ObjectPool::kPatchable : ObjectPool::kNotPatchable);
if (link_lazily()) {
compiler->GeneratePatchableCall(token_pos(), *stub_entry,
RawPcDescriptors::kOther, locs());
@@ -1877,7 +1868,6 @@
compiler->SaveLiveRegisters(locs);
compiler->GenerateCall(TokenPosition::kNoSource, // No token position.
stub_entry, RawPcDescriptors::kOther, locs);
- compiler->AddStubCallTarget(stub);
__ mov(result_, R0);
compiler->RestoreLiveRegisters(locs);
__ b(exit_label());
@@ -2280,9 +2270,6 @@
return;
}
}
- const Code& stub = Code::ZoneHandle(compiler->zone(),
- StubCode::AllocateArray_entry()->code());
- compiler->AddStubCallTarget(stub);
compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
*StubCode::AllocateArray_entry(),
RawPcDescriptors::kOther, locs());
@@ -2552,9 +2539,6 @@
compiler->SaveLiveRegisters(locs);
__ LoadImmediate(R1, instruction()->num_context_variables());
- const Code& stub = Code::ZoneHandle(
- compiler->zone(), StubCode::AllocateContext_entry()->code());
- compiler->AddStubCallTarget(stub);
compiler->GenerateCall(instruction()->token_pos(),
*StubCode::AllocateContext_entry(),
RawPcDescriptors::kOther, locs);
@@ -6002,7 +5986,6 @@
const StubEntry stub_entry(stub);
compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther,
locs());
- compiler->AddStubCallTarget(stub);
__ Drop(ArgumentCount()); // Discard arguments.
}
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index 848346f..ec66ff9 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -981,11 +981,11 @@
const ExternalLabel trampoline_label(reinterpret_cast<uword>(trampoline));
const intptr_t trampoline_kidx =
- __ object_pool_wrapper().FindNativeFunctionWrapper(&trampoline_label,
- kPatchable);
+ __ object_pool_wrapper().FindNativeFunctionWrapper(
+ &trampoline_label, ObjectPool::kPatchable);
const ExternalLabel label(reinterpret_cast<uword>(function));
- const intptr_t target_kidx =
- __ object_pool_wrapper().FindNativeFunction(&label, kPatchable);
+ const intptr_t target_kidx = __ object_pool_wrapper().FindNativeFunction(
+ &label, ObjectPool::kPatchable);
const intptr_t argc_tag_kidx =
__ object_pool_wrapper().FindImmediate(static_cast<uword>(argc_tag));
__ NativeCall(trampoline_kidx, target_kidx, argc_tag_kidx);
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index b6d4586..e6d79eb 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -1744,7 +1744,6 @@
compiler->SaveLiveRegisters(locs);
compiler->GenerateCall(TokenPosition::kNoSource, stub_entry,
RawPcDescriptors::kOther, locs);
- compiler->AddStubCallTarget(stub);
__ MoveRegister(result_, EAX);
compiler->RestoreLiveRegisters(locs);
__ jmp(exit_label());
@@ -2146,9 +2145,6 @@
}
__ Bind(&slow_path);
- const Code& stub = Code::ZoneHandle(compiler->zone(),
- StubCode::AllocateArray_entry()->code());
- compiler->AddStubCallTarget(stub);
compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
*StubCode::AllocateArray_entry(),
RawPcDescriptors::kOther, locs());
@@ -2422,9 +2418,6 @@
compiler->SaveLiveRegisters(locs);
__ movl(EDX, Immediate(instruction()->num_context_variables()));
- const Code& stub = Code::ZoneHandle(
- compiler->zone(), StubCode::AllocateContext_entry()->code());
- compiler->AddStubCallTarget(stub);
compiler->GenerateCall(instruction()->token_pos(),
*StubCode::AllocateContext_entry(),
RawPcDescriptors::kOther, locs);
@@ -6147,18 +6140,8 @@
// ECX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
__ xorl(ECX, ECX);
__ call(EBX);
- compiler->RecordSafepoint(locs());
- // Marks either the continuation point in unoptimized code or the
- // deoptimization point in optimized code, after call.
- const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
- if (compiler->is_optimizing()) {
- compiler->AddDeoptIndexAtCall(deopt_id_after);
- }
- // Add deoptimization continuation point after the call and before the
- // arguments are removed.
- // In optimized code this descriptor is needed for exception handling.
- compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after,
- token_pos());
+ compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
+ RawPcDescriptors::kOther, locs());
__ Drop(argument_count);
}
@@ -6191,7 +6174,6 @@
const StubEntry stub_entry(stub);
compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther,
locs());
- compiler->AddStubCallTarget(stub);
__ Drop(ArgumentCount()); // Discard arguments.
}
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index b1570d7..322e888 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -489,6 +489,9 @@
f->Print(", ");
PushArgumentAt(i)->value()->PrintTo(f);
}
+ if (entry_kind() == Code::EntryKind::kUnchecked) {
+ f->Print(" using unchecked entrypoint");
+ }
}
void InstanceCallInstr::PrintOperandsTo(BufferFormatter* f) const {
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index d214aef..b6fbb07 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -864,7 +864,7 @@
if (link_lazily()) {
stub_entry = StubCode::CallBootstrapNative_entry();
ExternalLabel label(NativeEntry::LinkNativeCallEntry());
- __ LoadNativeEntry(RBX, &label, kPatchable);
+ __ LoadNativeEntry(RBX, &label, ObjectPool::kPatchable);
compiler->GeneratePatchableCall(token_pos(), *stub_entry,
RawPcDescriptors::kOther, locs());
} else {
@@ -876,7 +876,7 @@
stub_entry = StubCode::CallNoScopeNative_entry();
}
const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
- __ LoadNativeEntry(RBX, &label, kNotPatchable);
+ __ LoadNativeEntry(RBX, &label, ObjectPool::kNotPatchable);
compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
locs());
}
@@ -1037,7 +1037,6 @@
compiler->SaveLiveRegisters(locs);
compiler->GenerateCall(TokenPosition::kNoSource, // No token position.
stub_entry, RawPcDescriptors::kOther, locs);
- compiler->AddStubCallTarget(stub);
__ MoveRegister(result_, RAX);
compiler->RestoreLiveRegisters(locs);
__ jmp(exit_label());
@@ -2267,9 +2266,6 @@
}
__ Bind(&slow_path);
- const Code& stub = Code::ZoneHandle(compiler->zone(),
- StubCode::AllocateArray_entry()->code());
- compiler->AddStubCallTarget(stub);
compiler->GenerateCallWithDeopt(token_pos(), deopt_id(),
*StubCode::AllocateArray_entry(),
RawPcDescriptors::kOther, locs());
@@ -2539,9 +2535,6 @@
compiler->SaveLiveRegisters(locs);
__ LoadImmediate(R10, Immediate(instruction()->num_context_variables()));
- const Code& stub = Code::ZoneHandle(
- compiler->zone(), StubCode::AllocateContext_entry()->code());
- compiler->AddStubCallTarget(stub);
compiler->GenerateCall(instruction()->token_pos(),
*StubCode::AllocateContext_entry(),
RawPcDescriptors::kOther, locs);
@@ -6238,26 +6231,16 @@
// Function in RAX.
ASSERT(locs()->in(0).reg() == RAX);
__ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
- __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
+ __ movq(RCX,
+ FieldAddress(RAX, Code::function_entry_point_offset(entry_kind())));
// RAX: Function.
// R10: Arguments descriptor array.
// RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value).
__ xorq(RBX, RBX);
__ call(RCX);
- compiler->RecordSafepoint(locs());
- compiler->EmitCatchEntryState();
- // Marks either the continuation point in unoptimized code or the
- // deoptimization point in optimized code, after call.
- const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id());
- if (compiler->is_optimizing()) {
- compiler->AddDeoptIndexAtCall(deopt_id_after);
- }
- // Add deoptimization continuation point after the call and before the
- // arguments are removed.
- // In optimized code this descriptor is needed for exception handling.
- compiler->AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after,
- token_pos());
+ compiler->EmitCallsiteMetadata(token_pos(), deopt_id(),
+ RawPcDescriptors::kOther, locs());
__ Drop(argument_count);
}
@@ -6297,7 +6280,6 @@
const StubEntry stub_entry(stub);
compiler->GenerateCall(token_pos(), stub_entry, RawPcDescriptors::kOther,
locs());
- compiler->AddStubCallTarget(stub);
__ Drop(ArgumentCount()); // Discard arguments.
}
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 0752327..6988601 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -971,6 +971,9 @@
} else if (PolymorphicInstanceCallInstr* instr =
call_data->call->AsPolymorphicInstanceCall()) {
entry_kind = instr->instance_call()->entry_kind();
+ } else if (ClosureCallInstr* instr =
+ call_data->call->AsClosureCall()) {
+ entry_kind = instr->entry_kind();
}
kernel::FlowGraphBuilder builder(
parsed_function, *ic_data_array, /* not building var desc */ NULL,
@@ -996,12 +999,14 @@
CalleeGraphValidator::Validate(callee_graph);
}
}
-#ifdef DART_PRECOMPILER
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ !defined(TARGET_ARCH_IA32)
if (FLAG_precompiled_mode) {
Precompiler::PopulateWithICData(parsed_function->function(),
callee_graph);
}
-#endif
+#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ // !defined(TARGET_ARCH_IA32)
// The parameter stubs are a copy of the actual arguments providing
// concrete information about the values, for example constant values,
@@ -1080,7 +1085,8 @@
// TODO(fschneider): Improve suppression of speculative inlining.
// Deopt-ids overlap between caller and callee.
if (FLAG_precompiled_mode) {
-#ifdef DART_PRECOMPILER
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ !defined(TARGET_ARCH_IA32)
AotCallSpecializer call_specializer(inliner_->precompiler_,
callee_graph,
inliner_->speculative_policy_);
@@ -1102,7 +1108,8 @@
callee_graph->Canonicalize();
#else
UNREACHABLE();
-#endif // DART_PRECOMPILER
+#endif // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ // !defined(TARGET_ARCH_IA32)
} else {
JitCallSpecializer call_specializer(callee_graph,
inliner_->speculative_policy_);
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index 0e4eea8..e74aaff 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -2613,7 +2613,6 @@
// Right now we are attempting to sink allocation only into
// deoptimization exit. So candidate should only be used in StoreInstanceField
// instructions that write into fields of the allocated object.
-// We do not support materialization of the object that has type arguments.
static bool IsAllocationSinkingCandidate(Definition* alloc,
SafeUseCheck check_type) {
for (Value* use = alloc->input_use_list(); use != NULL;
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index b81e5c6..b33a4cb 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -374,7 +374,7 @@
COMPILER_PASS(AllocationSinking_Sink, {
// TODO(vegorov): Support allocation sinking with try-catch.
- if (flow_graph->graph_entry()->SuccessorCount() == 1) {
+ if (flow_graph->graph_entry()->catch_entries().is_empty()) {
state->sinking = new AllocationSinking(flow_graph);
state->sinking->Optimize();
}
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index d92b3df..aab0242 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -271,7 +271,7 @@
// InstanceField constant occupies 2 entries.
// The first entry is used for field offset.
obj = Smi::New(field.Offset() / kWordSize);
- pool.SetTypeAt(i, ObjectPool::kTaggedObject);
+ pool.SetTypeAt(i, ObjectPool::kTaggedObject, ObjectPool::kNotPatchable);
pool.SetObjectAt(i, obj);
++i;
ASSERT(i < obj_count);
@@ -449,7 +449,7 @@
signature_type);
closure.SetSignatureType(signature_type);
- pool.SetTypeAt(i, ObjectPool::kTaggedObject);
+ pool.SetTypeAt(i, ObjectPool::kTaggedObject, ObjectPool::kNotPatchable);
pool.SetObjectAt(i, closure);
// Continue reading the constant pool entries inside the opened
@@ -464,7 +464,7 @@
case ConstantPoolTag::kEndClosureFunctionScope: {
// Entry is not used and set to null.
obj = Object::null();
- pool.SetTypeAt(i, ObjectPool::kTaggedObject);
+ pool.SetTypeAt(i, ObjectPool::kTaggedObject, ObjectPool::kNotPatchable);
pool.SetObjectAt(i, obj);
return i; // The caller will close the scope.
} break;
@@ -500,7 +500,7 @@
default:
UNREACHABLE();
}
- pool.SetTypeAt(i, ObjectPool::kTaggedObject);
+ pool.SetTypeAt(i, ObjectPool::kTaggedObject, ObjectPool::kNotPatchable);
pool.SetObjectAt(i, obj);
}
// Return the index of the last read pool entry.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index b7124b2..0cac1db 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -1624,7 +1624,8 @@
call_hook += LoadLocal(entry_point_num);
call_hook += PushArgument();
call_hook += Constant(Function::ZoneHandle(Z, closure.function()));
- call_hook += B->ClosureCall(/*type_args_len=*/0, /*argument_count=*/3,
+ call_hook += B->ClosureCall(TokenPosition::kNoSource,
+ /*type_args_len=*/0, /*argument_count=*/3,
/*argument_names=*/Array::Handle());
call_hook += Drop(); // result of closure call
call_hook += Drop(); // entrypoint number
@@ -2388,10 +2389,13 @@
return flow_graph_builder_->LoadStaticField();
}
-Fragment StreamingFlowGraphBuilder::CheckNull(TokenPosition position,
- LocalVariable* receiver,
- const String& function_name) {
- return flow_graph_builder_->CheckNull(position, receiver, function_name);
+Fragment StreamingFlowGraphBuilder::CheckNull(
+ TokenPosition position,
+ LocalVariable* receiver,
+ const String& function_name,
+ bool clear_the_temp /* = true */) {
+ return flow_graph_builder_->CheckNull(position, receiver, function_name,
+ clear_the_temp);
}
Fragment StreamingFlowGraphBuilder::StaticCall(TokenPosition position,
@@ -2840,8 +2844,8 @@
}
for (intptr_t i = 0; i < list_length; ++i) {
String& name =
- H.DartSymbolObfuscate(ReadStringReference()); // read ith name index.
- instructions += BuildExpression(); // read ith expression.
+ H.DartSymbolObfuscate(ReadStringReference()); // read ith name index.
+ instructions += BuildExpression(); // read ith expression.
if (!skip_push_arguments) instructions += PushArgument();
if (do_drop) instructions += Drop();
if (argument_names != NULL) {
@@ -3452,6 +3456,11 @@
const InferredTypeMetadata result_type =
inferred_type_metadata_helper_.GetInferredType(offset);
+#ifndef TARGET_ARCH_DBC
+ const CallSiteAttributesMetadata call_site_attributes =
+ call_site_attributes_metadata_helper_.GetCallSiteAttributes(offset);
+#endif
+
const Tag receiver_tag = PeekTag(); // peek tag for receiver.
if (IsNumberLiteral(receiver_tag) &&
(!optimizing() || constant_evaluator_.IsCached(offset))) {
@@ -3487,6 +3496,16 @@
SetOffset(before_branch_offset);
}
+ bool is_unchecked_closure_call = false;
+#ifndef TARGET_ARCH_DBC
+ if (call_site_attributes.receiver_type != nullptr &&
+ call_site_attributes.receiver_type->IsFunctionType()) {
+ AlternativeReadingScope alt(&reader_);
+ SkipExpression(); // skip receiver
+ is_unchecked_closure_call = ReadNameAsMethodName().Equals(Symbols::Call());
+ }
+#endif
+
Fragment instructions;
intptr_t type_args_len = 0;
@@ -3501,7 +3520,7 @@
const TypeArguments& type_arguments =
T.BuildTypeArguments(list_length); // read types.
instructions += TranslateInstantiatedTypeArguments(type_arguments);
- if (direct_call.check_receiver_for_null_) {
+ if (direct_call.check_receiver_for_null_ || is_unchecked_closure_call) {
// Don't yet push type arguments if we need to check receiver for null.
// In this case receiver will be duplicated so instead of pushing
// type arguments here we need to push it between receiver_temp
@@ -3538,7 +3557,7 @@
}
LocalVariable* receiver_temp = NULL;
- if (direct_call.check_receiver_for_null_) {
+ if (direct_call.check_receiver_for_null_ || is_unchecked_closure_call) {
// Duplicate receiver for CheckNull before it is consumed by PushArgument.
receiver_temp = MakeTemporary();
if (type_arguments_temp != NULL) {
@@ -3583,11 +3602,26 @@
Field::GetterSymbol(name) == interface_target->name()));
}
- if (direct_call.check_receiver_for_null_) {
- instructions += CheckNull(position, receiver_temp, name);
+ // TODO(sjindel): Avoid the check for null on unchecked closure calls if TFA
+ // allows.
+ if (direct_call.check_receiver_for_null_ || is_unchecked_closure_call) {
+ // Receiver temp is needed to load the function to call from the closure.
+ instructions += CheckNull(position, receiver_temp, name,
+ /*clear_temp=*/!is_unchecked_closure_call);
}
- if (!direct_call.target_.IsNull()) {
+ if (is_unchecked_closure_call) {
+ // Lookup the function in the closure.
+ instructions += LoadLocal(receiver_temp);
+ instructions += LoadField(Closure::function_offset());
+ if (parsed_function()->function().is_debuggable()) {
+ ASSERT(!parsed_function()->function().is_native());
+ instructions += DebugStepCheck(position);
+ }
+ instructions +=
+ B->ClosureCall(position, type_args_len, argument_count, argument_names,
+ /*use_unchecked_entry=*/true);
+ } else if (!direct_call.target_.IsNull()) {
ASSERT(FLAG_precompiled_mode);
instructions += StaticCall(position, direct_call.target_, argument_count,
argument_names, ICData::kNoRebind, &result_type,
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index ebdf3a0..c4aecce 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -209,7 +209,8 @@
Fragment LoadStaticField();
Fragment CheckNull(TokenPosition position,
LocalVariable* receiver,
- const String& function_name);
+ const String& function_name,
+ bool clear_the_temp = true);
Fragment StaticCall(TokenPosition position,
const Function& target,
intptr_t argument_count,
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 769f2a9..53d17b4 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -356,10 +356,10 @@
const InferredTypeMetadata* result_type) {
const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0);
ArgumentArray arguments = GetArguments(total_count);
- InstanceCallInstr* call = new (Z) InstanceCallInstr(
- position, name, kind, arguments, type_args_len, argument_names,
- checked_argument_count, ic_data_array_, GetNextDeoptId(),
- interface_target);
+ InstanceCallInstr* call = new (Z)
+ InstanceCallInstr(position, name, kind, arguments, type_args_len,
+ argument_names, checked_argument_count, ic_data_array_,
+ GetNextDeoptId(), interface_target);
if ((result_type != NULL) && !result_type->IsTrivial()) {
call->SetResultType(Z, result_type->ToCompileType(Z));
}
@@ -367,15 +367,19 @@
return Fragment(call);
}
-Fragment FlowGraphBuilder::ClosureCall(intptr_t type_args_len,
+Fragment FlowGraphBuilder::ClosureCall(TokenPosition position,
+ intptr_t type_args_len,
intptr_t argument_count,
- const Array& argument_names) {
+ const Array& argument_names,
+ bool is_statically_checked) {
Value* function = Pop();
const intptr_t total_count = argument_count + (type_args_len > 0 ? 1 : 0);
ArgumentArray arguments = GetArguments(total_count);
ClosureCallInstr* call = new (Z)
ClosureCallInstr(function, arguments, type_args_len, argument_names,
- TokenPosition::kNoSource, GetNextDeoptId());
+ position, GetNextDeoptId(),
+ is_statically_checked ? Code::EntryKind::kUnchecked
+ : Code::EntryKind::kNormal);
Push(call);
return Fragment(call);
}
@@ -486,7 +490,8 @@
Fragment FlowGraphBuilder::CheckNull(TokenPosition position,
LocalVariable* receiver,
- const String& function_name) {
+ const String& function_name,
+ bool clear_the_temp /* = true */) {
Fragment instructions = LoadLocal(receiver);
CheckNullInstr* check_null =
@@ -494,11 +499,13 @@
instructions <<= check_null;
- // Null out receiver to make sure it is not saved into the frame before
- // doing the call.
- instructions += NullConstant();
- instructions += StoreLocal(TokenPosition::kNoSource, receiver);
- instructions += Drop();
+ if (clear_the_temp) {
+ // Null out receiver to make sure it is not saved into the frame before
+ // doing the call.
+ instructions += NullConstant();
+ instructions += StoreLocal(TokenPosition::kNoSource, receiver);
+ instructions += Drop();
+ }
return instructions;
}
@@ -1352,8 +1359,8 @@
body += LoadLocal(closure);
body += LoadField(Closure::function_offset());
- body += ClosureCall(descriptor.TypeArgsLen(), descriptor.Count(),
- argument_names);
+ body += ClosureCall(TokenPosition::kNoSource, descriptor.TypeArgsLen(),
+ descriptor.Count(), argument_names);
} else {
const intptr_t kNumArgsChecked = 1;
body += InstanceCall(TokenPosition::kMinSource, Symbols::Call(),
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index ee8efe8..49332d5 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -101,9 +101,11 @@
intptr_t checked_argument_count,
const Function& interface_target,
const InferredTypeMetadata* result_type = NULL);
- Fragment ClosureCall(intptr_t type_args_len,
+ Fragment ClosureCall(TokenPosition position,
+ intptr_t type_args_len,
intptr_t argument_count,
- const Array& argument_names);
+ const Array& argument_names,
+ bool use_unchecked_entry = false);
Fragment RethrowException(TokenPosition position, int catch_try_index);
Fragment LoadClassId();
Fragment LoadField(intptr_t offset, intptr_t class_id = kDynamicCid);
@@ -114,7 +116,8 @@
Fragment Return(TokenPosition position, bool omit_result_type_check = false);
Fragment CheckNull(TokenPosition position,
LocalVariable* receiver,
- const String& function_name);
+ const String& function_name,
+ bool clear_the_temp = true);
void SetResultTypeForStaticCall(StaticCallInstr* call,
const Function& target,
intptr_t argument_count,
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index e14578b..aad6e73 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -896,7 +896,8 @@
ASSERT(pass_state.inline_id_to_function.length() ==
pass_state.caller_inline_id.length());
- Assembler assembler(use_far_branches);
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper, use_far_branches);
FlowGraphCompiler graph_compiler(
&assembler, flow_graph, *parsed_function(), optimized(),
&speculative_policy, pass_state.inline_id_to_function,
@@ -1220,7 +1221,8 @@
}
RawObject* Compiler::CompileFunction(Thread* thread, const Function& function) {
-#ifdef DART_PRECOMPILER
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ !defined(TARGET_ARCH_IA32)
if (FLAG_precompiled_mode) {
return Precompiler::CompileFunction(
/* precompiler = */ NULL, thread, thread->zone(), function);
@@ -1416,8 +1418,13 @@
for (int i = 0; i < functions.Length(); i++) {
func ^= functions.At(i);
ASSERT(!func.IsNull());
- if (!func.HasCode() && !func.is_abstract() &&
- !func.IsRedirectingFactory()) {
+ if (!func.HasCode() &&
+#if defined(DART_USE_INTERPRETER)
+ // TODO(regis): Revisit.
+ // Do not compile function if its bytecode is already loaded.
+ !func.HasBytecode() &&
+#endif
+ !func.is_abstract() && !func.IsRedirectingFactory()) {
if ((cls.is_mixin_app_alias() || cls.IsMixinApplication()) &&
func.HasOptionalParameters()) {
// Skipping optional parameters in mixin application.
@@ -1427,7 +1434,13 @@
if (result.IsError()) {
return Error::Cast(result).raw();
}
+#if defined(DART_USE_INTERPRETER)
+ // TODO(regis): Revisit.
+ // The compiler may load bytecode and return Code::null().
+ ASSERT(!result.IsNull() || func.HasBytecode());
+#else
ASSERT(!result.IsNull());
+#endif
}
}
return Error::null();
@@ -1467,7 +1480,8 @@
}
RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
-#ifdef DART_PRECOMPILER
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ !defined(TARGET_ARCH_IA32)
if (FLAG_precompiled_mode) {
return Precompiler::EvaluateStaticInitializer(field);
}
@@ -1535,7 +1549,8 @@
}
RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) {
-#ifdef DART_PRECOMPILER
+#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) && \
+ !defined(TARGET_ARCH_IA32)
if (FLAG_precompiled_mode) {
return Precompiler::ExecuteOnce(fragment);
}
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 9beae96..a7b8922 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -118,6 +118,12 @@
// Jump to the given target if assertions are not enabled.
// Target is specified as offset from the PC of the jump instruction.
//
+// - JumpIfNotZeroTypeArgs target
+//
+// Jump to the given target if number of passed function type
+// arguments is not zero.
+// Target is specified as offset from the PC of the jump instruction.
+//
// - Return R; ReturnTOS
//
// Return to the caller using either a value from the given register or a
@@ -563,6 +569,13 @@
// Function prologue for the function
// rD - number of local slots to reserve;
//
+// - EntryFixed A, D
+//
+// Function prologue for functions without optional arguments.
+// Checks number of arguments.
+// A - expected number of positional arguments;
+// D - number of local slots to reserve;
+//
// - EntryOptional A, B, C
//
// Function prologue for the function with optional or named arguments:
@@ -808,6 +821,7 @@
V(Drop, A, num, ___, ___) \
V(Jump, T, tgt, ___, ___) \
V(JumpIfNoAsserts, T, tgt, ___, ___) \
+ V(JumpIfNotZeroTypeArgs, T, tgt, ___, ___) \
V(Return, A, reg, ___, ___) \
V(ReturnTOS, 0, ___, ___, ___) \
V(Move, A_X, reg, xeg, ___) \
@@ -969,6 +983,7 @@
V(BooleanNegate, A_D, reg, reg, ___) \
V(Throw, A, num, ___, ___) \
V(Entry, D, num, ___, ___) \
+ V(EntryFixed, A_D, num, num, ___) \
V(EntryOptional, A_B_C, num, num, num) \
V(EntryOptimized, A_D, num, num, ___) \
V(Frame, D, num, ___, ___) \
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 1c2c099..7563e2a 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -1841,6 +1841,26 @@
}
{
+ BYTECODE(EntryFixed, A_D);
+ const uint16_t num_fixed_params = rA;
+ const uint16_t num_locals = rD;
+
+ const intptr_t arg_count = InterpreterHelpers::ArgDescArgCount(argdesc_);
+ const intptr_t pos_count = InterpreterHelpers::ArgDescPosCount(argdesc_);
+ if ((arg_count != num_fixed_params) || (pos_count != num_fixed_params)) {
+ goto ClosureNoSuchMethod;
+ }
+
+ // Initialize locals with null & set SP.
+ for (intptr_t i = 0; i < num_locals; i++) {
+ FP[i] = null_value;
+ }
+ SP = FP + num_locals - 1;
+
+ DISPATCH();
+ }
+
+ {
BYTECODE(EntryOptional, A_B_C);
const uint16_t num_fixed_params = rA;
const uint16_t num_opt_pos_params = rB;
@@ -4437,6 +4457,15 @@
}
{
+ BYTECODE(JumpIfNotZeroTypeArgs, 0);
+ if (InterpreterHelpers::ArgDescTypeArgsLen(argdesc_) != 0) {
+ const int32_t target = static_cast<int32_t>(op) >> 8;
+ pc += (target - 1);
+ }
+ DISPATCH();
+ }
+
+ {
BYTECODE(LoadClassId, A_D);
const uint16_t object_reg = rD;
RawObject* obj = static_cast<RawObject*>(FP[object_reg]);
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index 2005f9a..d832205 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -53,9 +53,8 @@
uword stack_limit() const { return stack_limit_; }
// Returns true if the interpreter's stack contains the given frame.
- // TODO(regis): Once the interpreter shares the native stack, we may rely on
- // a new thread vm_tag to identify an interpreter frame and we will not need
- // this HasFrame() method.
+ // TODO(regis): We should rely on a new thread vm_tag to identify an
+ // interpreter frame and not need this HasFrame() method.
bool HasFrame(uword frame) const {
return frame >= stack_base() && frame <= get_fp();
}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 38fdde9..d6fd7cb 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -5959,7 +5959,7 @@
StorePointer(&raw_ptr()->code_, value.raw());
StoreNonPointer(&raw_ptr()->entry_point_, value.EntryPoint());
StoreNonPointer(&raw_ptr()->unchecked_entry_point_,
- value.unchecked_entry_point());
+ value.UncheckedEntryPoint());
}
void Function::AttachCode(const Code& value) const {
@@ -13487,7 +13487,7 @@
result ^= raw;
result.SetLength(len);
for (intptr_t i = 0; i < len; i++) {
- result.SetTypeAt(i, ObjectPool::kImmediate);
+ result.SetTypeAt(i, ObjectPool::kImmediate, ObjectPool::kPatchable);
}
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index af38d51..9628163 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4356,6 +4356,15 @@
kNativeFunctionWrapper,
};
+ enum Patchability {
+ kPatchable,
+ kNotPatchable,
+ };
+
+ class TypeBits : public BitField<uint8_t, EntryType, 0, 7> {};
+ class PatchableBit
+ : public BitField<uint8_t, Patchability, TypeBits::kNextBit, 1> {};
+
struct Entry {
Entry() : raw_value_(), type_() {}
explicit Entry(const Object* obj) : obj_(obj), type_(kTaggedObject) {}
@@ -4382,11 +4391,17 @@
}
EntryType TypeAt(intptr_t index) const {
- return static_cast<EntryType>(raw_ptr()->entry_types()[index]);
+ return TypeBits::decode(raw_ptr()->entry_bits()[index]);
}
- void SetTypeAt(intptr_t index, EntryType type) const {
- StoreNonPointer(&raw_ptr()->entry_types()[index],
- static_cast<uint8_t>(type));
+
+ Patchability PatchableAt(intptr_t index) const {
+ return PatchableBit::decode(raw_ptr()->entry_bits()[index]);
+ }
+
+ void SetTypeAt(intptr_t index, EntryType type, Patchability patchable) const {
+ const uint8_t bits =
+ PatchableBit::encode(patchable) | TypeBits::encode(type);
+ StoreNonPointer(&raw_ptr()->entry_bits()[index], bits);
}
RawObject* ObjectAt(intptr_t index) const {
@@ -4990,6 +5005,18 @@
}
}
+ static intptr_t function_entry_point_offset(EntryKind kind) {
+ switch (kind) {
+ case Code::EntryKind::kNormal:
+ return Function::entry_point_offset();
+ case Code::EntryKind::kUnchecked:
+ return Function::unchecked_entry_point_offset();
+ default:
+ ASSERT(false && "Invalid entry kind.");
+ UNREACHABLE();
+ }
+ }
+
RawObjectPool* object_pool() const { return raw_ptr()->object_pool_; }
static intptr_t object_pool_offset() {
return OFFSET_OF(RawCode, object_pool_);
@@ -5009,9 +5036,9 @@
uword PayloadStart() const {
return Instructions::PayloadStart(instructions());
}
- uword EntryPoint() const {
- const Instructions& instr = Instructions::Handle(instructions());
- return instr.EntryPoint();
+ uword EntryPoint() const { return Instructions::EntryPoint(instructions()); }
+ uword UncheckedEntryPoint() const {
+ return Instructions::UncheckedEntryPoint(instructions());
}
uword MonomorphicEntryPoint() const {
const Instructions& instr = Instructions::Handle(instructions());
@@ -5306,14 +5333,6 @@
bool IsDisabled() const { return instructions() != active_instructions(); }
- uword unchecked_entry_point() const {
- return raw_ptr()->unchecked_entry_point_;
- }
-
- void set_unchecked_entry_point(uword value) const {
- StoreNonPointer(&raw_ptr()->unchecked_entry_point_, value);
- }
-
private:
void set_state_bits(intptr_t bits) const;
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 060c1c5..35bc8dd 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2618,7 +2618,8 @@
// Test for Code and Instruction object creation.
ISOLATE_UNIT_TEST_CASE(Code) {
extern void GenerateIncrement(Assembler * assembler);
- Assembler _assembler_;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler _assembler_(&object_pool_wrapper);
GenerateIncrement(&_assembler_);
const Function& function = Function::Handle(CreateFunction("Test_Code"));
Code& code =
@@ -2639,7 +2640,8 @@
MallocHooks::stack_trace_collection_enabled();
MallocHooks::set_stack_trace_collection_enabled(false);
extern void GenerateIncrement(Assembler * assembler);
- Assembler _assembler_;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler _assembler_(&object_pool_wrapper);
GenerateIncrement(&_assembler_);
const Function& function = Function::Handle(CreateFunction("Test_Code"));
Code& code =
@@ -2665,7 +2667,8 @@
extern void GenerateEmbedStringInCode(Assembler * assembler, const char* str);
const char* kHello = "Hello World!";
word expected_length = static_cast<word>(strlen(kHello));
- Assembler _assembler_;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler _assembler_(&object_pool_wrapper);
GenerateEmbedStringInCode(&_assembler_, kHello);
const Function& function =
Function::Handle(CreateFunction("Test_EmbedStringInCode"));
@@ -2687,7 +2690,8 @@
ISOLATE_UNIT_TEST_CASE(EmbedSmiInCode) {
extern void GenerateEmbedSmiInCode(Assembler * assembler, intptr_t value);
const intptr_t kSmiTestValue = 5;
- Assembler _assembler_;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler _assembler_(&object_pool_wrapper);
GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
const Function& function =
Function::Handle(CreateFunction("Test_EmbedSmiInCode"));
@@ -2704,7 +2708,8 @@
ISOLATE_UNIT_TEST_CASE(EmbedSmiIn64BitCode) {
extern void GenerateEmbedSmiInCode(Assembler * assembler, intptr_t value);
const intptr_t kSmiTestValue = DART_INT64_C(5) << 32;
- Assembler _assembler_;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler _assembler_(&object_pool_wrapper);
GenerateEmbedSmiInCode(&_assembler_, kSmiTestValue);
const Function& function =
Function::Handle(CreateFunction("Test_EmbedSmiIn64BitCode"));
@@ -2734,7 +2739,8 @@
TokenPosition::kNoSource, true);
extern void GenerateIncrement(Assembler * assembler);
- Assembler _assembler_;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler _assembler_(&object_pool_wrapper);
GenerateIncrement(&_assembler_);
Code& code = Code::Handle(Code::FinalizeCode(
Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_));
@@ -2774,7 +2780,8 @@
descriptors ^= builder->FinalizePcDescriptors(0);
extern void GenerateIncrement(Assembler * assembler);
- Assembler _assembler_;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler _assembler_(&object_pool_wrapper);
GenerateIncrement(&_assembler_);
Code& code = Code::Handle(Code::FinalizeCode(
Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_));
@@ -2835,7 +2842,8 @@
descriptors ^= builder->FinalizePcDescriptors(0);
extern void GenerateIncrement(Assembler * assembler);
- Assembler _assembler_;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler _assembler_(&object_pool_wrapper);
GenerateIncrement(&_assembler_);
Code& code = Code::Handle(Code::FinalizeCode(
Function::Handle(CreateFunction("Test_Code")), nullptr, &_assembler_));
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 92833a5..71442f9 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -529,10 +529,10 @@
ObjectPointerVisitor* visitor) {
const intptr_t length = raw_obj->ptr()->length_;
RawObjectPool::Entry* entries = raw_obj->ptr()->data();
- uint8_t* entry_types = raw_obj->ptr()->entry_types();
+ uint8_t* entry_bits = raw_obj->ptr()->entry_bits();
for (intptr_t i = 0; i < length; ++i) {
ObjectPool::EntryType entry_type =
- static_cast<ObjectPool::EntryType>(entry_types[i]);
+ ObjectPool::TypeBits::decode(entry_bits[i]);
if (entry_type == ObjectPool::kTaggedObject) {
visitor->VisitPointer(&entries[i].raw_obj_);
}
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index dc6bcc9..1738a30 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1368,12 +1368,10 @@
Entry* data() { OPEN_ARRAY_START(Entry, Entry); }
Entry const* data() const { OPEN_ARRAY_START(Entry, Entry); }
- // The entry types are located after the last entry. They are interpreted
- // as ObjectPool::EntryType.
- uint8_t* entry_types() {
- return reinterpret_cast<uint8_t*>(&data()[length_]);
- }
- uint8_t const* entry_types() const {
+ // The entry bits are located after the last entry. They are encoded versions
+ // of `ObjectPool::TypeBits() | ObjectPool::PatchabililtyBit()`.
+ uint8_t* entry_bits() { return reinterpret_cast<uint8_t*>(&data()[length_]); }
+ uint8_t const* entry_bits() const {
return reinterpret_cast<uint8_t const*>(&data()[length_]);
}
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index ee2f77c..8535bcd 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -578,9 +578,10 @@
#if defined(DART_USE_INTERPRETER)
void StackFrameIterator::FrameSetIterator::CheckIfInterpreted(
uword exit_marker) {
- // TODO(regis): Once the interpreter shares the native stack, we may rely on
- // a new thread vm_tag to identify an interpreter frame.
- Interpreter* interpreter = thread_->isolate()->interpreter();
+ // TODO(regis): We should rely on a new thread vm_tag to identify an
+ // interpreter frame and not need the HasFrame() method.
+ Isolate* isolate = thread_->isolate();
+ Interpreter* interpreter = isolate != NULL ? isolate->interpreter() : NULL;
is_interpreted_ = (interpreter != NULL) && interpreter->HasFrame(exit_marker);
}
#endif
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 6ee2181..82e4767 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -60,7 +60,8 @@
RawCode* StubCode::Generate(const char* name,
void (*GenerateStub)(Assembler* assembler)) {
- Assembler assembler;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper);
GenerateStub(&assembler);
const Code& code = Code::Handle(
Code::FinalizeCode(name, nullptr, &assembler, false /* optimized */));
@@ -139,7 +140,8 @@
Code& stub = Code::Handle(zone, cls.allocation_stub());
#if !defined(DART_PRECOMPILED_RUNTIME)
if (stub.IsNull()) {
- Assembler assembler;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper);
const char* name = cls.ToCString();
StubCode::GenerateAllocationStubForClass(&assembler, cls);
diff --git a/runtime/vm/stub_code_arm64_test.cc b/runtime/vm/stub_code_arm64_test.cc
index 2f2495e..091cb42 100644
--- a/runtime/vm/stub_code_arm64_test.cc
+++ b/runtime/vm/stub_code_arm64_test.cc
@@ -55,7 +55,8 @@
const Code& code);
const int length = 10;
const char* kName = "Test_CallRuntimeStubCode";
- Assembler assembler;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper);
GenerateCallToCallRuntimeStub(&assembler, length);
const Code& code = Code::Handle(Code::FinalizeCode(
*CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler));
@@ -94,7 +95,8 @@
intptr_t rhs_index_value = 2;
intptr_t length_value = 2;
const char* kName = "Test_CallLeafRuntimeStubCode";
- Assembler assembler;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper);
GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
rhs_index_value, length_value);
const Code& code = Code::Handle(Code::FinalizeCode(
diff --git a/runtime/vm/stub_code_arm_test.cc b/runtime/vm/stub_code_arm_test.cc
index d7f44bc..e717208 100644
--- a/runtime/vm/stub_code_arm_test.cc
+++ b/runtime/vm/stub_code_arm_test.cc
@@ -55,7 +55,8 @@
const Code& code);
const int length = 10;
const char* kName = "Test_CallRuntimeStubCode";
- Assembler assembler;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper);
GenerateCallToCallRuntimeStub(&assembler, length);
const Code& code = Code::Handle(Code::FinalizeCode(
*CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler));
@@ -94,7 +95,8 @@
intptr_t rhs_index_value = 2;
intptr_t length_value = 2;
const char* kName = "Test_CallLeafRuntimeStubCode";
- Assembler assembler;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper);
GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
rhs_index_value, length_value);
const Code& code = Code::Handle(Code::FinalizeCode(
diff --git a/runtime/vm/stub_code_ia32_test.cc b/runtime/vm/stub_code_ia32_test.cc
index 4e1df07..e00932a 100644
--- a/runtime/vm/stub_code_ia32_test.cc
+++ b/runtime/vm/stub_code_ia32_test.cc
@@ -55,7 +55,7 @@
const Code& code);
const int length = 10;
const char* kName = "Test_CallRuntimeStubCode";
- Assembler assembler;
+ Assembler assembler(nullptr);
GenerateCallToCallRuntimeStub(&assembler, length);
const Code& code = Code::Handle(Code::FinalizeCode(
*CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler));
@@ -98,7 +98,7 @@
intptr_t rhs_index_value = 2;
intptr_t length_value = 2;
const char* kName = "Test_CallLeafRuntimeStubCode";
- Assembler assembler;
+ Assembler assembler(nullptr);
GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
rhs_index_value, length_value);
const Code& code = Code::Handle(Code::FinalizeCode(
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc
index cc108ae..b460282 100644
--- a/runtime/vm/stub_code_x64_test.cc
+++ b/runtime/vm/stub_code_x64_test.cc
@@ -55,7 +55,8 @@
const Code& code);
const int length = 10;
const char* kName = "Test_CallRuntimeStubCode";
- Assembler assembler;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper);
GenerateCallToCallRuntimeStub(&assembler, length);
const Code& code = Code::Handle(Code::FinalizeCode(
*CreateFunction("Test_CallRuntimeStubCode"), nullptr, &assembler));
@@ -94,7 +95,8 @@
intptr_t rhs_index_value = 2;
intptr_t length_value = 2;
const char* kName = "Test_CallLeafRuntimeStubCode";
- Assembler assembler;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper);
GenerateCallToCallLeafRuntimeStub(&assembler, str_value, lhs_index_value,
rhs_index_value, length_value);
const Code& code = Code::Handle(Code::FinalizeCode(
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 92e04a1..07200fb 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -496,11 +496,11 @@
// to get their verification done and exit. Use a specific UserTag
// to enable the helpers to verify that the main thread is
// successfully interrupted in the pure Dart loop.
-#if defined(USING_SIMULATOR)
+#if defined(USING_SIMULATOR) || defined(DART_USE_INTERPRETER)
const intptr_t kLoopCount = 12345678;
#else
const intptr_t kLoopCount = 1234567890;
-#endif // USING_SIMULATOR
+#endif // defined(USING_SIMULATOR) || defined(DART_USE_INTERPRETER)
char buffer[1024];
Utils::SNPrint(buffer, sizeof(buffer),
"import 'dart:developer';\n"
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index da216ee..2e635c1 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -345,7 +345,8 @@
ASSERT(!type_class.IsNull());
// To use the already-defined __ Macro !
- Assembler assembler;
+ ObjectPoolWrapper object_pool_wrapper;
+ Assembler assembler(&object_pool_wrapper);
BuildOptimizedTypeTestStub(&assembler, hi, type, type_class);
const char* name = namer_.StubNameForType(type);
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 1d125a0..7ff72fd 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -28,17 +28,13 @@
using dart::bin::DartUtils;
extern "C" {
-extern const uint8_t kPlatformDill[];
extern const uint8_t kPlatformStrongDill[];
-extern intptr_t kPlatformDillSize;
extern intptr_t kPlatformStrongDillSize;
}
namespace dart {
-const uint8_t* platform_dill = kPlatformDill;
const uint8_t* platform_strong_dill = kPlatformStrongDill;
-const intptr_t platform_dill_size = kPlatformDillSize;
const intptr_t platform_strong_dill_size = kPlatformStrongDillSize;
DEFINE_FLAG(bool,
@@ -109,8 +105,7 @@
Dart_Isolate TestCase::CreateTestIsolate(const char* name, void* data) {
if (FLAG_use_dart_frontend) {
return CreateIsolate(
- FLAG_strong ? platform_strong_dill : platform_dill,
- FLAG_strong ? platform_strong_dill_size : platform_dill_size,
+ platform_strong_dill, platform_strong_dill_size,
NULL, /* There is no instr buffer in case of dill buffers. */
name, data);
} else {
@@ -261,8 +256,7 @@
bool allow_compile_errors) {
Zone* zone = Thread::Current()->zone();
Dart_KernelCompilationResult compilation_result = Dart_CompileSourcesToKernel(
- url, FLAG_strong ? platform_strong_dill : platform_dill,
- FLAG_strong ? platform_strong_dill_size : platform_dill_size,
+ url, platform_strong_dill, platform_strong_dill_size,
sourcefiles_count, sourcefiles, incrementally, NULL);
return ValidateCompilationResult(zone, compilation_result, kernel_pgm);
}
@@ -311,10 +305,8 @@
const char* multiroot_scheme) {
Zone* zone = Thread::Current()->zone();
Dart_KernelCompilationResult compilation_result = Dart_CompileSourcesToKernel(
- url, FLAG_strong ? platform_strong_dill : platform_dill,
- FLAG_strong ? platform_strong_dill_size : platform_dill_size,
- sourcefiles_count, sourcefiles, incrementally, NULL, multiroot_filepaths,
- multiroot_scheme);
+ url, platform_strong_dill, platform_strong_dill_size, sourcefiles_count,
+ sourcefiles, incrementally, NULL, multiroot_filepaths, multiroot_scheme);
return ValidateCompilationResult(zone, compilation_result, kernel_buffer,
kernel_buffer_size, allow_compile_errors);
}
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index 928489f..1115f6d 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -90,7 +90,8 @@
bool use_far_branches = false; \
LongJumpScope jump; \
if (setjmp(*jump.Set()) == 0) { \
- Assembler assembler(use_far_branches); \
+ ObjectPoolWrapper object_pool_wrapper; \
+ Assembler assembler(&object_pool_wrapper, use_far_branches); \
AssemblerTest test("" #name, &assembler); \
AssemblerTestGenerate##name(test.assembler()); \
test.Assemble(); \
@@ -102,7 +103,8 @@
const Error& error = Error::Handle(Thread::Current()->sticky_error()); \
if (error.raw() == Object::branch_offset_error().raw()) { \
bool use_far_branches = true; \
- Assembler assembler(use_far_branches); \
+ ObjectPoolWrapper object_pool_wrapper; \
+ Assembler assembler(&object_pool_wrapper, use_far_branches); \
AssemblerTest test("" #name, &assembler); \
AssemblerTestGenerate##name(test.assembler()); \
test.Assemble(); \
diff --git a/sdk/lib/async/async.dart b/sdk/lib/async/async.dart
index 2fa3f1df8..b5354bb 100644
--- a/sdk/lib/async/async.dart
+++ b/sdk/lib/async/async.dart
@@ -98,6 +98,7 @@
show
CastStream,
CastStreamTransformer,
+ EmptyIterator,
printToZone,
printToConsole,
IterableElementError;
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 33a7ac4..f8ef8ed 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -159,19 +159,21 @@
}
/**
- * Creates a single-subscription stream that gets its data from [data].
+ * Creates a single-subscription stream that gets its data from [elements].
*
* The iterable is iterated when the stream receives a listener, and stops
- * iterating if the listener cancels the subscription.
+ * iterating if the listener cancels the subscription, or if the
+ * [Iterator.moveNext] method returns `false` or throws.
+ * Iteration is suspended whild the stream subscription is paused.
*
- * If iterating [data] throws an error, the stream ends immediately with
- * that error. No done event will be sent (iteration is not complete), but no
- * further data events will be generated either, since iteration cannot
- * continue.
+ * If calling [Iterator.moveNext] on `elements.iterator` throws,
+ * the stream emits that error and then it closes.
+ * If reading [Iterator.current] on `elements.iterator` throws,
+ * the stream emits that error, but keeps iterating.
*/
- factory Stream.fromIterable(Iterable<T> data) {
+ factory Stream.fromIterable(Iterable<T> elements) {
return new _GeneratedStreamImpl<T>(
- () => new _IterablePendingEvents<T>(data));
+ () => new _IterablePendingEvents<T>(elements));
}
/**
@@ -967,11 +969,18 @@
/**
* Collects the data of this stream in a [Set].
*
+ * Creates a `Set<T>` and adds all elements of the stream to the set.
+ * in the order they arrive.
+ * When the stream ends, the returned future is completed with that set.
+ *
* The returned set is the same type as returned by `new Set<T>()`.
* If another type of set is needed, either use [forEach] to add each
* element to the set, or use
* `toList().then((list) => new SomeOtherSet.from(list))`
* to create the set.
+ *
+ * If the stream contains an error, the returned future is completed
+ * with that error, and processing stops.
*/
Future<Set<T>> toSet() {
Set<T> result = new Set<T>();
@@ -1626,6 +1635,13 @@
*
* If the subscription is paused more than once, an equal number
* of resumes must be performed to resume the stream.
+ * Calls to [resume] and the completion of a [resumeSignal] are
+ * interchangeable - the [pause] which was passed a [resumeSignal] may be
+ * ended by a call to [resume], and completing the [resumeSignal] may end a
+ * different [pause].
+ *
+ * It is safe to [resume] or complete a [resumeSignal] even when the
+ * subscription is not paused, and the resume will have no effect.
*
* Currently DOM streams silently drop events when the stream is paused. This
* is a bug and will be fixed.
@@ -1639,6 +1655,9 @@
* When all previously calls to [pause] have been matched by a calls to
* [resume], possibly through a `resumeSignal` passed to [pause],
* the stream subscription may emit events again.
+ *
+ * It is safe to [resume] even when the subscription is not paused, and the
+ * resume will have no effect.
*/
void resume();
diff --git a/sdk/lib/async/stream_impl.dart b/sdk/lib/async/stream_impl.dart
index 310ec37..9750478 100644
--- a/sdk/lib/async/stream_impl.dart
+++ b/sdk/lib/async/stream_impl.dart
@@ -526,22 +526,29 @@
}
// Send one event per call to moveNext.
// If moveNext returns true, send the current element as data.
+ // If current throws, send that error, but keep iterating.
// If moveNext returns false, send a done event and clear the _iterator.
- // If moveNext throws an error, send an error and clear the _iterator.
- // After an error, no further events will be sent.
- bool isDone;
+ // If moveNext throws an error, send an error and prepare to send a done
+ // event afterwards.
+ bool hasMore;
try {
- isDone = !_iterator.moveNext();
+ hasMore = _iterator.moveNext();
+ if (hasMore) {
+ dispatch._sendData(_iterator.current);
+ } else {
+ _iterator = null;
+ dispatch._sendDone();
+ }
} catch (e, s) {
- _iterator = null;
- dispatch._sendError(e, s);
- return;
- }
- if (!isDone) {
- dispatch._sendData(_iterator.current);
- } else {
- _iterator = null;
- dispatch._sendDone();
+ if (hasMore == null) {
+ // Threw in .moveNext().
+ // Ensure that we send a done afterwards.
+ _iterator = const EmptyIterator<Null>();
+ dispatch._sendError(e, s);
+ } else {
+ // Threw in .current.
+ dispatch._sendError(e, s);
+ }
}
}
diff --git a/sdk/lib/io/process.dart b/sdk/lib/io/process.dart
index 3c7e1c2..b6c616a 100644
--- a/sdk/lib/io/process.dart
+++ b/sdk/lib/io/process.dart
@@ -288,6 +288,11 @@
* which will be returned as the negative number `-1073741819`. To
* get the original 32-bit value use `(0x100000000 + exitCode) &
* 0xffffffff`.
+ *
+ * There is no guarantee that [stdout] and [stderr] have finished reporting
+ * the buffered output of the process when the returned future completes.
+ * To be sure that all output is captured,
+ * wait for the done event on the streams.
*/
Future<int> get exitCode;
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 0a66fd4..b3d404f 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -907,6 +907,7 @@
Utils/tests/Expect/setEquals_A01_t02: CompileTimeError # Uses Dart 1 constants
[ !$strong ]
+LibTest/async/Stream/Stream.fromIterable_A02_t01: RuntimeError # Assumes no close after error.
LibTest/async/Stream/firstWhere_A01_t01: RuntimeError # co19 issue 137
LibTest/async/Stream/firstWhere_A02_t01: RuntimeError # co19 issue 137
LibTest/async/Stream/lastWhere_A01_t01: RuntimeError # co19 issue 137
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index 1dfba79..95caf2c 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -4,7 +4,6 @@
[ $compiler == fasta ]
Language/Classes/Constructors/Generative_Constructors/final_variables_t01: CompileTimeError # Expects a warning, but this is an error in Dart 2
-Language/Classes/definition_t24: MissingCompileTimeError
Language/Functions/Formal_Parameters/Optional_Formals/default_value_t01: MissingCompileTimeError
Language/Functions/Formal_Parameters/Optional_Formals/default_value_t02: MissingCompileTimeError
Language/Types/Type_Void/syntax_t08: MissingCompileTimeError
@@ -74,8 +73,6 @@
Language/Classes/Setters/static_setter_t05: CompileTimeError
Language/Classes/Setters/static_setter_t06: CompileTimeError
Language/Classes/Static_Methods/same_name_method_and_setter_t01: CompileTimeError
-Language/Classes/Superinterfaces/more_than_once_t01: MissingCompileTimeError
-Language/Classes/Superinterfaces/superclass_as_superinterface_t01: MissingCompileTimeError
Language/Classes/same_name_instance_and_static_members_t02: MissingCompileTimeError
Language/Classes/same_name_instance_and_static_members_t04: MissingCompileTimeError
Language/Expressions/Constants/exception_t01: MissingCompileTimeError
@@ -104,8 +101,6 @@
Language/Classes/Getters/same_name_method_t04: MissingCompileTimeError
Language/Classes/Getters/same_name_method_t05: MissingCompileTimeError
Language/Classes/Getters/same_name_method_t07: MissingCompileTimeError
-Language/Classes/Superinterfaces/more_than_once_t01: MissingCompileTimeError
-Language/Classes/Superinterfaces/superclass_as_superinterface_t01: MissingCompileTimeError
Language/Classes/same_name_instance_and_static_members_t02: MissingCompileTimeError
Language/Classes/same_name_instance_and_static_members_t04: MissingCompileTimeError
Language/Expressions/Constants/bitwise_operators_t05: MissingCompileTimeError
@@ -226,7 +221,6 @@
Language/Classes/Superinterfaces/no_member_t02: CompileTimeError
Language/Classes/Superinterfaces/no_member_t05: CompileTimeError
Language/Classes/Superinterfaces/wrong_type_t05: MissingCompileTimeError
-Language/Classes/definition_t24: MissingCompileTimeError
Language/Classes/method_definition_t03: CompileTimeError
Language/Classes/method_definition_t04: CompileTimeError
Language/Classes/method_definition_t05: CompileTimeError
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 055c317..3e28235 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -57,12 +57,9 @@
Language/Classes/Setters/name_t06: CompileTimeError
Language/Classes/Setters/name_t07: CompileTimeError
Language/Classes/Static_Methods/same_name_method_and_setter_t01: CompileTimeError
-Language/Classes/Superclasses/wrong_superclass_t08: MissingCompileTimeError
-Language/Classes/Superinterfaces/more_than_once_t01: MissingCompileTimeError
-Language/Classes/Superinterfaces/superclass_as_superinterface_t01: MissingCompileTimeError
-Language/Classes/Superinterfaces/wrong_type_t05: MissingCompileTimeError
-Language/Classes/definition_t24: MissingCompileTimeError
-Language/Classes/method_definition_t06: MissingCompileTimeError
+Language/Classes/Superclasses/wrong_superclass_t08: MissingCompileTimeError # Issue 30273
+Language/Classes/Superinterfaces/wrong_type_t05: MissingCompileTimeError # Issue 30273
+Language/Classes/method_definition_t06: MissingCompileTimeError # Legal
Language/Enums/syntax_t08: CompileTimeError
Language/Enums/syntax_t09: CompileTimeError
Language/Expressions/Assignable_Expressions/syntax_t01: CompileTimeError
@@ -257,7 +254,6 @@
LanguageFeatures/Instantiate-to-bound/function/function_ret_extends_neg_l1_t02: MissingCompileTimeError
LanguageFeatures/Instantiate-to-bound/interface/interface_neg_assign_l2_t01: MissingCompileTimeError
LanguageFeatures/Instantiate-to-bound/interface/interface_neg_assign_l2_t02: MissingCompileTimeError
-LanguageFeatures/Instantiate-to-bound/interface/interface_neg_l1_t06: MissingCompileTimeError
LanguageFeatures/Instantiate-to-bound/mixin/mixin_extends_neg_l1_t01: MissingCompileTimeError
LanguageFeatures/Instantiate-to-bound/mixin/mixin_neg_assign_l2_t01: MissingCompileTimeError
LanguageFeatures/Instantiate-to-bound/mixin/mixin_neg_l1_t02: MissingCompileTimeError
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 150a79c..2c3682a 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -33,7 +33,7 @@
model/subtype_test: Pass, Slow
no_such_method_enabled_test: Pass, Slow
packages/*: Skip # Skip packages folder
-rti/rti_emission_test: RuntimeError, Slow # Issue 34095
+rti/rti_emission_test: Pass, Slow
rti/rti_need0_test: Pass, Slow
rti/rti_need1_test: Pass, Slow
show_package_warnings_test: RuntimeError # missing errors from the FE
diff --git a/tests/compiler/dart2js/rti/emission/constructor_argument_static_strong.dart b/tests/compiler/dart2js/rti/emission/constructor_argument_static_strong.dart
index 37dfefe..0725a31 100644
--- a/tests/compiler/dart2js/rti/emission/constructor_argument_static_strong.dart
+++ b/tests/compiler/dart2js/rti/emission/constructor_argument_static_strong.dart
@@ -4,12 +4,14 @@
import 'package:meta/dart2js.dart';
-/*class: A1:checks=[],instance*/
+/*strong.class: A1:checkedInstance,checks=[],instance*/
+/*omit.class: A1:checks=[],instance*/
class A1 {}
// Constructor calls are always statically invoked, so there is no checks at the
// entry and the `Test1` constructor does not cause any checks.
-/*class: B1:checks=[],instance*/
+/*strong.class: B1:checks=[$isA1],instance*/
+/*omit.class: B1:checks=[],instance*/
class B1 implements A1 {}
/*class: Test1:checks=[],instance*/
diff --git a/tests/compiler/dart2js/rti/emission/self.dart b/tests/compiler/dart2js/rti/emission/self.dart
index a6aa4a6..2777989 100644
--- a/tests/compiler/dart2js/rti/emission/self.dart
+++ b/tests/compiler/dart2js/rti/emission/self.dart
@@ -4,7 +4,7 @@
import 'package:meta/dart2js.dart';
-/*class: C:checkedInstance,checks=[],instance*/
+/*class: C:checkedInstance,checks=[],instance,typeLiteral*/
class C {}
@noInline
diff --git a/tests/compiler/dart2js/rti/emission/superclass.dart b/tests/compiler/dart2js/rti/emission/superclass.dart
index e0427de..7af0de0 100644
--- a/tests/compiler/dart2js/rti/emission/superclass.dart
+++ b/tests/compiler/dart2js/rti/emission/superclass.dart
@@ -4,7 +4,7 @@
import 'package:meta/dart2js.dart';
-/*class: B:checkedInstance,checks=[],instance*/
+/*class: B:checkedInstance,checks=[],typeLiteral*/
class B {}
/*class: C:checks=[],instance*/
diff --git a/tests/compiler/dart2js/rti/rti_emission_test.dart b/tests/compiler/dart2js/rti/rti_emission_test.dart
index d7f6b65..9659eb6 100644
--- a/tests/compiler/dart2js/rti/rti_emission_test.dart
+++ b/tests/compiler/dart2js/rti/rti_emission_test.dart
@@ -38,6 +38,12 @@
'map_literal_checked.dart',
// TODO(johnniwinther): Optimize local function type signature need.
'subtype_named_args.dart',
+
+ // TODO(johnniwinther): Fix crash.
+ 'call_strong.dart',
+
+ // TODO(34095):
+ 'list.dart',
],
);
});
diff --git a/tests/compiler/dart2js_extra/deferred/34219_bounds_lib1.dart b/tests/compiler/dart2js_extra/deferred/34219_bounds_lib1.dart
new file mode 100644
index 0000000..81bf0ae
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred/34219_bounds_lib1.dart
@@ -0,0 +1,16 @@
+// 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.
+
+// Part of 34219_bounds_test.dart
+
+import '34219_bounds_lib2.dart';
+
+class SystemMessage extends GeneratedMessage {}
+
+var g;
+
+test1() {
+ new GeneratedMessage();
+ g = (<T extends SystemMessage>(T a, T b) => a == b);
+}
diff --git a/tests/compiler/dart2js_extra/deferred/34219_bounds_lib2.dart b/tests/compiler/dart2js_extra/deferred/34219_bounds_lib2.dart
new file mode 100644
index 0000000..7726460
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred/34219_bounds_lib2.dart
@@ -0,0 +1,7 @@
+// 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.
+
+// Part of 34219_bounds_test.dart
+
+class GeneratedMessage {}
diff --git a/tests/compiler/dart2js_extra/deferred/34219_bounds_lib3.dart b/tests/compiler/dart2js_extra/deferred/34219_bounds_lib3.dart
new file mode 100644
index 0000000..a567162
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred/34219_bounds_lib3.dart
@@ -0,0 +1,14 @@
+// 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.
+
+// Part of 34219_bounds_test.dart
+//
+// This library places GeneratedMessage into a different partition to
+// SystemMessage.
+
+import '34219_bounds_lib2.dart';
+
+test3() {
+ new GeneratedMessage();
+}
diff --git a/tests/compiler/dart2js_extra/deferred/34219_bounds_test.dart b/tests/compiler/dart2js_extra/deferred/34219_bounds_test.dart
new file mode 100644
index 0000000..67b77d9
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred/34219_bounds_test.dart
@@ -0,0 +1,20 @@
+// 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.
+// dart2jsOptions=--omit-implicit-checks
+
+// Tests that generic function type bounds are walked as dependencies of a
+// closure. If the generic function bounds are not visited, SystemMessage is
+// placed in the main unit while it's superclass GeneratedMessage is placed in a
+// deferred part.
+
+import '34219_bounds_lib1.dart' deferred as lib1;
+import '34219_bounds_lib3.dart' deferred as lib3;
+
+main() async {
+ await lib1.loadLibrary();
+ lib1.test1();
+ await lib3.loadLibrary();
+ lib3.test3();
+ if (lib1.g is bool Function(Object, Object)) print('!');
+}
diff --git a/tests/compiler/dart2js_extra/deferred/34219_signature_lib1.dart b/tests/compiler/dart2js_extra/deferred/34219_signature_lib1.dart
new file mode 100644
index 0000000..b3493bd
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred/34219_signature_lib1.dart
@@ -0,0 +1,16 @@
+// 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.
+
+// Part of 34219_signature_test.dart
+
+import '34219_signature_lib2.dart';
+
+class SystemMessage extends GeneratedMessage {}
+
+var g;
+
+test1() {
+ new GeneratedMessage();
+ g = (SystemMessage a, SystemMessage b) => a == b;
+}
diff --git a/tests/compiler/dart2js_extra/deferred/34219_signature_lib2.dart b/tests/compiler/dart2js_extra/deferred/34219_signature_lib2.dart
new file mode 100644
index 0000000..e702fe6
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred/34219_signature_lib2.dart
@@ -0,0 +1,7 @@
+// 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.
+
+// Part of 34219_signature_test.dart
+
+class GeneratedMessage {}
diff --git a/tests/compiler/dart2js_extra/deferred/34219_signature_lib3.dart b/tests/compiler/dart2js_extra/deferred/34219_signature_lib3.dart
new file mode 100644
index 0000000..35915d5
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred/34219_signature_lib3.dart
@@ -0,0 +1,14 @@
+// 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.
+
+// Part of 34219_signature_test.dart
+//
+// This library places GeneratedMessage into a different partition to
+// SystemMessage.
+
+import '34219_signature_lib2.dart';
+
+test3() {
+ new GeneratedMessage();
+}
diff --git a/tests/compiler/dart2js_extra/deferred/34219_signature_test.dart b/tests/compiler/dart2js_extra/deferred/34219_signature_test.dart
new file mode 100644
index 0000000..d6c2c05
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred/34219_signature_test.dart
@@ -0,0 +1,19 @@
+// 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.
+// dart2jsOptions=--omit-implicit-checks
+
+// Tests that closure signatures are walked as dependencies of a closure. If the
+// signature of the closure is not visited, SystemMessage is placed in the main
+// unit while it's superclass GeneratedMessage is placed in a deferred part.
+
+import '34219_signature_lib1.dart' deferred as lib1;
+import '34219_signature_lib3.dart' deferred as lib3;
+
+main() async {
+ await lib1.loadLibrary();
+ lib1.test1();
+ await lib3.loadLibrary();
+ lib3.test3();
+ if (lib1.g is bool Function(Object, Object)) print('!');
+}
diff --git a/tests/language_2/bug34235_test.dart b/tests/language_2/bug34235_test.dart
new file mode 100644
index 0000000..69011ff
--- /dev/null
+++ b/tests/language_2/bug34235_test.dart
@@ -0,0 +1,26 @@
+// 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.
+
+class Base {
+ void foo() {}
+}
+
+class M1 {
+ void foo(
+ // Prevent formatter from joining the line below to the one above
+ {x} //# 01: compile-time error
+ ) {}
+}
+
+class BaseWithM1 = Base with M1;
+
+class M2 {
+ void foo() {}
+}
+
+class Derived extends BaseWithM1 with M2 {}
+
+main() {
+ new Derived().foo();
+}
diff --git a/tests/language_2/implements_futureor_test.dart b/tests/language_2/implements_futureor_test.dart
new file mode 100644
index 0000000..4e878ff
--- /dev/null
+++ b/tests/language_2/implements_futureor_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+class A<T>
+ implements FutureOr<T> //# 01: compile-time error
+{}
+
+void main() {
+ A a = new A();
+}
diff --git a/tests/language_2/invalid_assignment_to_postfix_increment_test.dart b/tests/language_2/invalid_assignment_to_postfix_increment_test.dart
new file mode 100644
index 0000000..329ea3c
--- /dev/null
+++ b/tests/language_2/invalid_assignment_to_postfix_increment_test.dart
@@ -0,0 +1,13 @@
+// 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.
+
+void f(int x, int y) {
+ x++ = y; //# 01: compile-time error
+ x++ += y; //# 02: compile-time error
+ x++ ??= y; //# 03: compile-time error
+}
+
+main() {
+ f(1, 2);
+}
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index 52840b1..1b1cc15 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -2,6 +2,7 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
+bug34235_test/01: MissingCompileTimeError # Issue 34235
mixin_constructor_forwarding/const_constructor_test/none: CompileTimeError # Issue 32223
mixin_constructor_forwarding/const_constructor_with_field_test/none: CompileTimeError # Issue 32223
mixin_constructor_forwarding/optional_named_parameters_test/none: CompileTimeError # Issue 31543
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 469f479..83f9f80 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -27,11 +27,6 @@
[ $compiler == dart2analyzer && $fasta ]
arg_param_trailing_comma_test/100: Crash # Issue #34043 - Error recovery in outline (extraneous comma before formal parameter)
-arg_param_trailing_comma_test/138: Crash # Error recovery in method body (synthetic argument)
-arg_param_trailing_comma_test/147: Crash # Error recovery in method body (synthetic argument)
-arg_param_trailing_comma_test/156: Crash # Error recovery in method body (synthetic argument)
-arg_param_trailing_comma_test/165: Crash # Error recovery in method body (synthetic argument)
-arg_param_trailing_comma_test/166: Crash # Error recovery in method body (invalid assignment)
arg_param_trailing_comma_test/24: Crash # Issue #34043 - Error recovery in outline (extraneous comma before formal parameter)
arg_param_trailing_comma_test/25: Crash # Issue #34043 - Error recovery in outline (extraneous comma before formal parameter)
arg_param_trailing_comma_test/26: Crash # Issue #34043 - Error recovery in outline (extraneous comma before formal parameter)
@@ -50,6 +45,7 @@
built_in_identifier_illegal_test/implements: Crash # Issue #34043 - Error recovery in outline (synthetic token used where type expected)
built_in_identifier_illegal_test/part: Crash # No resolution for a file
built_in_identifier_illegal_test/typedef: Crash # Issue 33686 - No core library found
+built_in_identifier_type_annotation_test/mixin: Crash # Issue 34164 - mixin support
built_in_identifier_type_annotation_test/part: Crash # No resolution for a file
built_in_identifier_type_annotation_test/set: Crash # Issue #34043 - Error recovery in outline
built_in_identifier_type_annotation_test/set-funret: Crash # Issue #34043 - Error recovery in outline
@@ -58,8 +54,6 @@
class_cycle2_test/02: Crash # Issue #34043 - Error recovery in outline (class hierarchy cycle - see also #33756)
class_cycle_test/00: Crash # Issue #34043 - Error recovery in outline (class hierarchy cycle - see also #33756)
class_cycle_test/01: Crash # Issue #34043 - Error recovery in outline (class hierarchy cycle - see also #33756)
-class_cycle_test/02: MissingCompileTimeError
-class_cycle_test/03: MissingCompileTimeError
compile_time_constant_static5_test/11: CompileTimeError # Issue 31537
compile_time_constant_static5_test/16: CompileTimeError # Issue 31537
compile_time_constant_static5_test/21: CompileTimeError # Issue 31537
@@ -82,9 +76,6 @@
deferred_load_library_wrong_args_test/01: CompileTimeError # Issue 34047
duplicate_constructor_test/01: Crash # Issue 33686 - No core library found
duplicate_field_with_initializer_test/01: Crash # Issue 33686 - No core library found
-duplicate_implements_test/01: MissingCompileTimeError
-duplicate_implements_test/02: MissingCompileTimeError
-duplicate_interface_implements_test/01: MissingCompileTimeError
dynamic_prefix_core_test/none: CompileTimeError # Issue 34047
emit_const_fields_test: CompileTimeError # Issue 34047
enum_syntax_test/02: Crash # Issue #34043 - Error recovery in outline (duplicate enum name)
@@ -139,6 +130,7 @@
hidden_import_test/02: MissingStaticWarning
illegal_initializer_test/02: Crash # Issue #33771 - Error recovery in method body (error in constructor initializer)
illegal_initializer_test/04: Crash # Issue #33771 - Error recovery in method body (error in constructor initializer)
+implements_futureor_test/01: Crash
import_nonexisting_dart_uri_test/01: Crash # Issue 33686 - No core library found
instantiate_tearoff_of_call_test: CompileTimeError # Front end fails to instantiate tear-offs of `call`
instantiate_type_variable_test/01: Crash # Error recovery in method body (attempt to instantiate type variable)
@@ -251,6 +243,7 @@
prefix_variable_collision_test/01: Crash # Issue 33686 - No core library found
regress_20394_test/01: Crash # Error recovery in method body (error in super constructor call)
regress_23408_test: CompileTimeError # Issue 34047
+regress_27617_test/1: Crash # The analyzer doesn't report this error.
regress_28217_test/01: Crash # Error recovery in method body (error in constructor redirect)
regress_28217_test/none: Crash # Error recovery in method body (error in constructor redirect)
regress_29025_test: CompileTimeError # Issue 34047
@@ -278,8 +271,6 @@
string_supertype_checked_test: CompileTimeError # Issue 34047
super_bound_closure_test/none: CompileTimeError # Issue 34047
super_conditional_operator_test/01: Crash # Error recovery in method body (error in constructor redirect)
-super_conditional_operator_test/17: Crash # Error recovery in method body (nonsensical use of super)
-super_conditional_operator_test/18: Crash # Error recovery in method body (nonsensical use of super)
super_no_such_method1_test: CompileTimeError # Issue 34047
super_no_such_method2_test: CompileTimeError # Issue 34047
super_no_such_method3_test: CompileTimeError # Issue 34047
@@ -414,7 +405,6 @@
accessor_conflict_import_test: CompileTimeError # Issue 25626
additional_interface_adds_optional_args_test: CompileTimeError # Issue #30568
built_in_identifier_prefix_test: CompileTimeError
-built_in_identifier_type_annotation_test/dynamic-gen: MissingCompileTimeError # Issue 28813
cascaded_forwarding_stubs_test: CompileTimeError
check_member_static_test/01: CompileTimeError
config_import_corelib_test: CompileTimeError
@@ -422,7 +412,6 @@
conflicting_generic_interfaces_hierarchy_loop_infinite_test: Skip # Crashes or times out
const_cast2_test/01: CompileTimeError
const_cast2_test/none: CompileTimeError
-const_for_in_variable_test/01: MissingCompileTimeError # Issue 25161
constructor9_test/01: MissingCompileTimeError # CFE Issue 33022
default_implementation2_test: CompileTimeError # Issue 30855
dynamic_prefix_core_test/01: MissingCompileTimeError
@@ -446,6 +435,7 @@
generic_no_such_method_dispatcher_test: CompileTimeError
generic_tearoff_test: CompileTimeError
getter_setter_in_lib_test: Fail # Issue 23286
+implements_futureor_test/01: MissingCompileTimeError
implicit_creation/implicit_const_context_constructor_generic_named_test: CompileTimeError
implicit_creation/implicit_const_context_constructor_generic_test: CompileTimeError
implicit_creation/implicit_const_context_prefix_constructor_generic_named_test: CompileTimeError
@@ -454,10 +444,6 @@
initializing_formal_final_test: MissingCompileTimeError
interceptor6_test: CompileTimeError
interface_test/00: MissingCompileTimeError
-invalid_type_argument_count_test/01: MissingCompileTimeError
-invalid_type_argument_count_test/02: MissingCompileTimeError
-invalid_type_argument_count_test/03: MissingCompileTimeError
-invalid_type_argument_count_test/04: MissingCompileTimeError
issue13673_test: StaticWarning # Issue 31925
issue31596_implement_covariant_test: CompileTimeError
issue31596_override_test/01: CompileTimeError
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index 3b91111..ab0f9c8 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -26,7 +26,6 @@
deopt_inlined_function_lazy_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
deopt_smi_op_test: CompileTimeError, OK # Error if web int literal cannot be represented exactly, see http://dartbug.com/33351
double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in dart2js; bug #11551.
-duplicate_interface_implements_test/01: MissingCompileTimeError
external_test/10: CompileTimeError # External non-js-interop function are treated as compile-time errors.
external_test/13: CompileTimeError # External non-js-interop function are treated as compile-time errors.
external_test/20: CompileTimeError # External non-js-interop function are treated as compile-time errors.
@@ -256,10 +255,6 @@
deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
deferred_redirecting_factory_test: RuntimeError
double_int_to_string_test: RuntimeError, OK # non JS number semantics
-duplicate_implements_test/01: MissingCompileTimeError
-duplicate_implements_test/02: MissingCompileTimeError
-duplicate_implements_test/03: MissingCompileTimeError
-duplicate_implements_test/04: MissingCompileTimeError
dynamic_prefix_core_test/none: RuntimeError
enum_mirror_test: RuntimeError
expect_test: RuntimeError, OK # Issue 13080
@@ -545,8 +540,6 @@
bit_operations_test: RuntimeError
branch_canonicalization_test: RuntimeError
canonical_const2_test: RuntimeError, OK # non JS number semantics
-class_cycle_test/02: MissingCompileTimeError
-class_cycle_test/03: MissingCompileTimeError
compile_time_constant_o_test/01: MissingCompileTimeError
compile_time_constant_o_test/02: MissingCompileTimeError
compile_time_constant_static5_test/11: CompileTimeError
@@ -573,8 +566,6 @@
deferred_not_loaded_check_test: RuntimeError # Test out of date. Issue 31933
deferred_redirecting_factory_test: RuntimeError
double_int_to_string_test: RuntimeError, OK # non JS number semantics
-duplicate_implements_test/01: MissingCompileTimeError
-duplicate_implements_test/02: MissingCompileTimeError
dynamic_prefix_core_test/none: CompileTimeError
emit_const_fields_test: CompileTimeError
enum_mirror_test: RuntimeError
@@ -706,7 +697,6 @@
redirecting_factory_reflection_test: RuntimeError
regress_23408_test: CompileTimeError
regress_24283_test: RuntimeError, OK # non JS number semantics
-regress_27617_test/1: Crash # Assertion failure: Unexpected constructor j:constructor(Foo._) in ConstructorDataImpl._getConstructorConstant
regress_28255_test: RuntimeError
regress_29025_test: CompileTimeError
regress_29405_test: CompileTimeError
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 858b6af..3098bb5 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -26,7 +26,6 @@
built_in_identifier_prefix_test: CompileTimeError
built_in_identifier_type_annotation_test/dynamic-funarg: RuntimeError # Issue 28816
built_in_identifier_type_annotation_test/dynamic-funret: RuntimeError # Issue 28816
-built_in_identifier_type_annotation_test/dynamic-gen: MissingCompileTimeError # Issue 28816
built_in_identifier_type_annotation_test/dynamic-list: RuntimeError # Issue 28816
cascaded_forwarding_stubs_generic_test: RuntimeError
cascaded_forwarding_stubs_test: CompileTimeError
@@ -37,7 +36,6 @@
const_cast2_test/none: CompileTimeError
const_constructor_mixin3_test/01: MissingCompileTimeError # Issue 33644
const_constructor_mixin_test/01: MissingCompileTimeError # Issue 33644
-const_for_in_variable_test/01: MissingCompileTimeError
constructor9_test/01: MissingCompileTimeError # CFE Issue 33022
constructor_type_parameter_test/00: MissingCompileTimeError
constructor_with_type_parameters_test/03: MissingCompileTimeError
@@ -71,6 +69,7 @@
generic_no_such_method_dispatcher_test: CompileTimeError
getter_closure_execution_order_test: RuntimeError # Issue 29920
getter_setter_in_lib_test: CompileTimeError
+implements_futureor_test/01: MissingCompileTimeError
implicit_creation/implicit_const_context_constructor_generic_named_test: CompileTimeError
implicit_creation/implicit_const_context_constructor_generic_test: CompileTimeError
implicit_creation/implicit_const_context_prefix_constructor_generic_named_test: CompileTimeError
@@ -84,10 +83,6 @@
instantiate_tearoff_of_call_test: RuntimeError
interface_test/00: MissingCompileTimeError
internal_library_test/01: MissingCompileTimeError # Issue 29920
-invalid_type_argument_count_test/01: MissingCompileTimeError
-invalid_type_argument_count_test/02: MissingCompileTimeError
-invalid_type_argument_count_test/03: MissingCompileTimeError
-invalid_type_argument_count_test/04: MissingCompileTimeError
issue31596_implement_covariant_test: CompileTimeError
issue31596_override_test/01: CompileTimeError
issue31596_override_test/02: CompileTimeError
@@ -241,8 +236,8 @@
call_method_implicit_tear_off_implements_function_test/06: RuntimeError # Kernel is missing the implicit `call` tearoff for assignment `Function`
call_method_must_not_be_field_test/06: RuntimeError # Kernel does not distinguish `d()` from `d.call()`
call_method_must_not_be_getter_test/06: RuntimeError # Kernel does not distinguish `d()` from `d.call()`
-class_cycle_test/02: MissingCompileTimeError
-class_cycle_test/03: MissingCompileTimeError
+call_non_method_field_test/01: MissingCompileTimeError
+call_non_method_field_test/02: MissingCompileTimeError
compile_time_constant_c_test/02: MissingCompileTimeError
compile_time_constant_k_test/01: MissingCompileTimeError
compile_time_constant_k_test/02: MissingCompileTimeError
@@ -274,9 +269,6 @@
covariant_subtyping_test: RuntimeError
deferred_load_library_wrong_args_test/01: CompileTimeError
double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in ddk
-duplicate_implements_test/01: MissingCompileTimeError
-duplicate_implements_test/02: MissingCompileTimeError
-duplicate_interface_implements_test/01: MissingCompileTimeError
dynamic_prefix_core_test/none: CompileTimeError
emit_const_fields_test: CompileTimeError # Issue 31533
export_ambiguous_main_test: MissingCompileTimeError
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index a0a0476..76a6c49 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -156,11 +156,7 @@
web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
[ $compiler == dartkp ]
-class_cycle_test/02: MissingCompileTimeError
-class_cycle_test/03: MissingCompileTimeError
covariant_subtyping_test: RuntimeError
-duplicate_implements_test/01: MissingCompileTimeError
-duplicate_implements_test/02: MissingCompileTimeError
generic_methods_generic_function_result_test/01: MissingCompileTimeError
generic_no_such_method_dispatcher_test: RuntimeError # Issue 31424
web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
@@ -290,7 +286,6 @@
redirecting_factory_default_values_test/01: MissingCompileTimeError # Issue 34160
redirecting_factory_default_values_test/02: MissingCompileTimeError # Issue 34160
regress_22976_test/*: CompileTimeError # Issue 31935
-regress_27617_test/1: MissingCompileTimeError # Issue 34161
syntax_test/28: MissingCompileTimeError # Issue 29763 - low priority
syntax_test/29: MissingCompileTimeError # Issue 29763 - low priority
syntax_test/30: MissingCompileTimeError # Issue 29763 - low priority
@@ -721,6 +716,7 @@
const_dynamic_type_literal_test/02: Pass
map_literal3_test/01: Pass
map_literal3_test/02: Pass
+type_alias_equality_test/02: RuntimeError # Issue 31359
vm/bool_check_stack_traces_test/01: RuntimeError # No support for line numbers in stacktraces
vm/bool_check_stack_traces_test/none: RuntimeError # No support for line numbers in stacktraces
vm/causal_async_exception_stack2_test: RuntimeError # No support for line numbers in stacktraces
@@ -1053,8 +1049,6 @@
tearoff_dynamic_test: RuntimeError # Compares call to "foo" (noSuchMethod) with string "foo"
[ $compiler == fasta && $strong ]
-class_cycle_test/02: MissingCompileTimeError
-class_cycle_test/03: MissingCompileTimeError
compile_time_constant_static4_test/02: MissingCompileTimeError
compile_time_constant_static4_test/03: MissingCompileTimeError
compile_time_constant_static5_test/11: CompileTimeError
@@ -1068,8 +1062,6 @@
const_constructor3_test/04: MissingCompileTimeError
constants_test/05: MissingCompileTimeError
deferred_load_library_wrong_args_test/01: CompileTimeError
-duplicate_implements_test/01: MissingCompileTimeError
-duplicate_implements_test/02: MissingCompileTimeError
dynamic_prefix_core_test/none: CompileTimeError
emit_const_fields_test: CompileTimeError
export_ambiguous_main_test: MissingCompileTimeError
@@ -1396,7 +1388,7 @@
enum_test: Crash
[ $mode == debug && ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
-enum_duplicate_test/01: Crash
+enum_duplicate_test/01: Pass, Crash
[ $mode == product && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
deferred_load_constants_test/02: Fail
@@ -1799,8 +1791,6 @@
deferred_constraints_type_annotation_test/type_annotation_generic4: MissingCompileTimeError
deferred_constraints_type_annotation_test/type_annotation_null: MissingCompileTimeError
deferred_constraints_type_annotation_test/type_annotation_top_level: MissingCompileTimeError
-duplicate_implements_test/01: MissingCompileTimeError
-duplicate_implements_test/02: MissingCompileTimeError
duplicate_implements_test/03: MissingCompileTimeError
duplicate_implements_test/04: MissingCompileTimeError
dynamic_field_test/01: MissingCompileTimeError
@@ -2435,6 +2425,3 @@
[ $compiler == dartk || $compiler == dartkb || $compiler == dartkp ]
generic_function_bounds_test: RuntimeError # Issue 32076
generic_test/01: MissingCompileTimeError
-
-[ $compiler == dartkp || $compiler == fasta ]
-duplicate_interface_implements_test/01: MissingCompileTimeError
diff --git a/tests/language_2/vm/exactness/future_or_regression_34238_test.dart b/tests/language_2/vm/exactness/future_or_regression_34238_test.dart
new file mode 100644
index 0000000..9ee7a96
--- /dev/null
+++ b/tests/language_2/vm/exactness/future_or_regression_34238_test.dart
@@ -0,0 +1,14 @@
+import 'dart:async';
+
+class A {
+ FutureOr<int> x;
+}
+
+Future<int> foo() async => 42;
+
+main() {
+ var a = new A();
+ a.x = 33;
+ a.x = null;
+ a.x = foo();
+}
diff --git a/tests/lib_2/async/stream_from_iterable_test.dart b/tests/lib_2/async/stream_from_iterable_test.dart
index eb254c2..b8317f0 100644
--- a/tests/lib_2/async/stream_from_iterable_test.dart
+++ b/tests/lib_2/async/stream_from_iterable_test.dart
@@ -2,110 +2,127 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// Test merging streams.
-library dart.test.stream_from_iterable;
+// Test Stream.fromIterable.
import 'dart:async';
+import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
import 'package:expect/async_minitest.dart';
import 'event_helper.dart';
-class IterableTest<T> {
- static int counter = 0;
- Iterable<T> iterable;
- IterableTest(this.iterable);
- void run() {
- test("stream from iterable ${counter++}", () {
- Events expected = new Events.fromIterable(iterable);
- Stream<T> stream = new Stream<T>.fromIterable(iterable);
- Events actual = new Events.capture(stream);
- actual.onDone(expectAsync(() {
- Expect.listEquals(expected.events, actual.events);
- }));
- });
- }
+// Tests that various typed iterables that do not throw creates
+// suitable streams.
+void iterableTest<T>(Iterable<T> iterable) {
+ asyncStart();
+ List<T> expected = iterable.toList();
+ Stream<T> stream = new Stream<T>.fromIterable(iterable);
+ var events = <T>[];
+ stream.listen(events.add, onDone: () {
+ Expect.listEquals(expected, events, "fromIterable $iterable");
+ asyncEnd();
+ });
}
main() {
- new IterableTest([]).run();
- new IterableTest([1]).run();
- new IterableTest([1, "two", true, null]).run();
- new IterableTest<int>([1, 2, 3, 4]).run();
- new IterableTest<String>(["one", "two", "three", "four"]).run();
- new IterableTest<int>(new Iterable<int>.generate(1000, (i) => i)).run();
- new IterableTest<String>(
- new Iterable<int>.generate(1000, (i) => i).map((i) => "$i")).run();
+ asyncStart();
+
+ iterableTest<Object>(<Object>[]);
+ iterableTest<Null>(<Null>[]);
+ iterableTest<Object>(<int>[1]);
+ iterableTest<Object>(<Object>[1, "two", true, null]);
+ iterableTest<int>(<int>[1, 2, 3, 4]);
+ iterableTest<String>(<String>["one", "two", "three", "four"]);
+ iterableTest<int>(new Iterable<int>.generate(1000, (i) => i));
+ iterableTest<String>(
+ new Iterable<int>.generate(1000, (i) => i).map((i) => "$i"));
Iterable<int> iter = new Iterable.generate(25, (i) => i * 2);
- test("iterable-toList", () {
- new Stream.fromIterable(iter).toList().then(expectAsync((actual) {
+ {
+ // Test that the stream's .toList works.
+ asyncStart();
+ new Stream.fromIterable(iter).toList().then((actual) {
List expected = iter.toList();
Expect.equals(25, expected.length);
Expect.listEquals(expected, actual);
- }));
- });
+ asyncEnd();
+ });
+ }
- test("iterable-mapped-toList", () {
- new Stream.fromIterable(iter)
- .map((i) => i * 3)
- .toList()
- .then(expectAsync((actual) {
+ {
+ // Test that the stream's .map works.
+ asyncStart();
+ new Stream.fromIterable(iter).map((i) => i * 3).toList().then((actual) {
List expected = iter.map((i) => i * 3).toList();
Expect.listEquals(expected, actual);
- }));
- });
+ asyncEnd();
+ });
+ }
- test("iterable-paused", () {
- var stream = new Stream<int>.fromIterable(iter);
- Events actual = new Events();
+ {
+ // Test that pause works.
+ asyncStart();
+ int ctr = 0;
+
+ var stream = new Stream<int>.fromIterable(iter.map((x) {
+ ctr++;
+ return x;
+ }));
+
StreamSubscription subscription;
+ var actual = [];
subscription = stream.listen((int value) {
actual.add(value);
// Do a 10 ms pause during the playback of the iterable.
Duration duration = const Duration(milliseconds: 10);
if (value == 20) {
- subscription.pause(new Future.delayed(duration, () {}));
+ asyncStart();
+ int beforeCtr = ctr;
+ subscription.pause(new Future.delayed(duration, () {}).whenComplete(() {
+ Expect.equals(beforeCtr, ctr);
+ asyncEnd();
+ }));
}
- }, onDone: expectAsync(() {
- actual.close();
- Events expected = new Events.fromIterable(iter);
- Expect.listEquals(expected.events, actual.events);
- }));
- });
+ }, onDone: () {
+ Expect.listEquals(iter.toList(), actual);
+ asyncEnd();
+ });
+ }
- test("iterable-single-subscription", () {
+ {
+ // Test that you can't listen twice..
Stream stream = new Stream.fromIterable(iter);
- stream.listen((x) {});
- Expect.throwsStateError(() => stream.listen((x) {}));
- });
+ stream.listen((x) {}).cancel();
+ Expect.throws<StateError>(() => stream.listen((x) {}));
+ }
- test("regression-14332", () {
+ {
// Regression test for http://dartbug.com/14332.
- // This should succeede.
+ // This should succeed.
var from = new Stream.fromIterable([1, 2, 3, 4, 5]);
var c = new StreamController();
var sink = c.sink;
- var done = expectAsync(() {}, count: 2);
+ asyncStart(2);
// if this goes first, test failed (hanged). Swapping addStream and toList
// made failure go away.
sink.addStream(from).then((_) {
c.close();
- done();
+ asyncEnd();
});
c.stream.toList().then((x) {
Expect.listEquals([1, 2, 3, 4, 5], x);
- done();
+ asyncEnd();
});
- });
+ }
- test("regression-14334-b", () {
+ {
+ // Regression test for issue 14334 (#2)
var from = new Stream.fromIterable([1, 2, 3, 4, 5]);
// odd numbers as data events, even numbers as error events
@@ -113,17 +130,128 @@
var c = new StreamController();
- var done = expectAsync(() {}, count: 2);
+ asyncStart();
var data = [], errors = [];
c.stream.listen(data.add, onError: errors.add, onDone: () {
Expect.listEquals([1, 3, 5], data);
Expect.listEquals([2, 4], errors);
- done();
+ asyncEnd();
});
c.addStream(from).then((_) {
c.close();
- done();
});
+ }
+
+ {
+ // Example from issue http://dartbug.com/33431.
+ asyncStart();
+ var asyncStarStream = () async* {
+ yield 1;
+ yield 2;
+ throw "bad";
+ }();
+ collectEvents(asyncStarStream).then((events2) {
+ Expect.listEquals(["value", 1, "value", 2, "error", "bad"], events2);
+ asyncEnd();
+ });
+
+ Iterable<int> throwingIterable() sync* {
+ yield 1;
+ yield 2;
+ throw "bad";
+ }
+
+ // Sanity check behavior.
+ var it = throwingIterable().iterator;
+ Expect.isTrue(it.moveNext());
+ Expect.equals(1, it.current);
+ Expect.isTrue(it.moveNext());
+ Expect.equals(2, it.current);
+ Expect.throws(it.moveNext, (e) => e == "bad");
+
+ asyncStart();
+ var syncStarStream = new Stream<int>.fromIterable(throwingIterable());
+ collectEvents(syncStarStream).then((events1) {
+ Expect.listEquals(["value", 1, "value", 2, "error", "bad"], events1);
+ asyncEnd();
+ });
+ }
+
+ {
+ // Test error behavior. Changed when fixing issue 33431.
+ // Iterable where "current" throws for third value, moveNext on fifth call.
+ var m = new MockIterable<int>((n) {
+ return n != 5 || (throw "moveNext");
+ }, (n) {
+ return n != 3 ? n : throw "current";
+ });
+ asyncStart();
+ collectEvents(new Stream<int>.fromIterable(m)).then((events) {
+ // Error on "current" does not stop iteration.
+ // Error on "moveNext" does.
+ Expect.listEquals([
+ "value",
+ 1,
+ "value",
+ 2,
+ "error",
+ "current",
+ "value",
+ 4,
+ "error",
+ "moveNext"
+ ], events);
+ asyncEnd();
+ });
+ }
+
+ asyncEnd();
+}
+
+// Collects value and error events in a list.
+// Value events preceeded by "value", error events by "error".
+// Completes on done event.
+Future<List<Object>> collectEvents(Stream<Object> stream) {
+ var c = new Completer<List<Object>>();
+ var events = <Object>[];
+ stream.listen((value) {
+ events..add("value")..add(value);
+ }, onError: (error) {
+ events..add("error")..add(error);
+ }, onDone: () {
+ c.complete(events);
});
+ return c.future;
+}
+
+// Mock iterable.
+// A `MockIterable<T>(f1, f2)` calls `f1` on `moveNext` calls with incrementing
+// values starting from 1. Calls `f2` on `current` access, with the same integer
+// as the most recent `f1` call.
+class MockIterable<T> extends Iterable<T> {
+ final bool Function(int) _onMoveNext;
+ final T Function(int) _onCurrent;
+
+ MockIterable(this._onMoveNext, this._onCurrent);
+
+ Iterator<T> get iterator => MockIterator(_onMoveNext, _onCurrent);
+}
+
+class MockIterator<T> implements Iterator<T> {
+ final bool Function(int) _onMoveNext;
+ final T Function(int) _onCurrent;
+
+ int _counter = 0;
+
+ MockIterator(this._onMoveNext, this._onCurrent);
+
+ bool moveNext() {
+ _counter += 1;
+ return _onMoveNext(_counter);
+ }
+
+ T get current {
+ return _onCurrent(_counter);
+ }
}
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 7db464c..f7529d1 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -121,6 +121,7 @@
[ !$strong ]
async/future_test: SkipByDesign # Uses Dart 2 syntax.
async/stream_first_where_test/badType: MissingCompileTimeError
+async/stream_from_iterable_test: SkipByDesign # Uses Dart 2 syntax.
async/stream_last_where_test/badType: MissingCompileTimeError
mirrors/redirecting_factory_different_type_test/02: MissingCompileTimeError
diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status
index 485c54e..8a82ed2 100644
--- a/tests/lib_2/lib_2_vm.status
+++ b/tests/lib_2/lib_2_vm.status
@@ -59,7 +59,6 @@
async/schedule_microtask5_test: RuntimeError
async/stream_controller_async_test: RuntimeError
async/stream_first_where_test: RuntimeError
-async/stream_from_iterable_test: RuntimeError
async/stream_iterator_test: RuntimeError
async/stream_join_test: RuntimeError
async/stream_last_where_test: RuntimeError
diff --git a/tools/VERSION b/tools/VERSION
index 6f56b53..f2c3b69 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 1
PATCH 0
-PRERELEASE 2
+PRERELEASE 3
PRERELEASE_PATCH 0
diff --git a/tools/bots/try_benchmarks.sh b/tools/bots/try_benchmarks.sh
index b7c5551..9e5670f 100755
--- a/tools/bots/try_benchmarks.sh
+++ b/tools/bots/try_benchmarks.sh
@@ -77,8 +77,6 @@
-- \
third_party/d8/linux/ia32/natives_blob.bin \
third_party/d8/linux/ia32/snapshot_blob.bin \
- out/ReleaseIA32/vm_outline.dill \
- out/ReleaseIA32/vm_platform.dill \
out/ReleaseIA32/vm_outline_strong.dill \
out/ReleaseIA32/vm_platform_strong.dill \
third_party/firefox_jsshell/linux/ \
@@ -178,8 +176,6 @@
-- \
third_party/d8/linux/ia32/natives_blob.bin \
third_party/d8/linux/ia32/snapshot_blob.bin \
- out/ReleaseIA32/vm_outline.dill \
- out/ReleaseIA32/vm_platform.dill \
out/ReleaseIA32/vm_outline_strong.dill \
out/ReleaseIA32/vm_platform_strong.dill \
third_party/firefox_jsshell/linux/ \
@@ -244,8 +240,6 @@
-- \
third_party/d8/linux/x64/natives_blob.bin \
third_party/d8/linux/x64/snapshot_blob.bin \
- out/ReleaseX64/vm_outline.dill \
- out/ReleaseX64/vm_platform.dill \
out/ReleaseX64/vm_outline_strong.dill \
out/ReleaseX64/vm_platform_strong.dill \
out/ReleaseX64/dart-sdk \
@@ -367,8 +361,6 @@
-- \
third_party/d8/linux/x64/natives_blob.bin \
third_party/d8/linux/x64/snapshot_blob.bin \
- out/ReleaseX64/vm_outline.dill \
- out/ReleaseX64/vm_platform.dill \
out/ReleaseX64/vm_outline_strong.dill \
out/ReleaseX64/vm_platform_strong.dill \
out/ReleaseX64/dart-sdk \
@@ -415,12 +407,10 @@
out/ReleaseX64/dart pkg/analysis_server/benchmark/benchmarks.dart run --quick --repeat 1 analysis-server-cold
out/ReleaseX64/dart --print_metrics pkg/analyzer_cli/bin/analyzer.dart --dart-sdk=sdk hello.dart
echo '[{"name":"foo","edits":[["pkg/compiler/lib/src/dart2js.dart","2016","2017"],["pkg/compiler/lib/src/options.dart","2016","2017"]]}]' > appjit_train_edits.json
- out/ReleaseX64/dart --background-compilation=false --snapshot-kind=app-jit --snapshot=pkg/front_end/tool/incremental_perf.dart.appjit pkg/front_end/tool/incremental_perf.dart --target=vm --sdk-summary=out/ReleaseX64/vm_platform.dill --sdk-library-specification=sdk/lib/libraries.json pkg/compiler/lib/src/dart2js.dart appjit_train_edits.json
+ out/ReleaseX64/dart --background-compilation=false --snapshot-kind=app-jit --snapshot=pkg/front_end/tool/incremental_perf.dart.appjit pkg/front_end/tool/incremental_perf.dart --target=vm --sdk-summary=out/ReleaseX64/vm_platform_strong.dill --sdk-library-specification=sdk/lib/libraries.json pkg/compiler/lib/src/dart2js.dart appjit_train_edits.json
out/ReleaseX64/dart --background-compilation=false pkg/front_end/tool/incremental_perf.dart.appjit --target=vm --sdk-summary=out/ReleaseX64/vm_platform_strong.dill --sdk-library-specification=sdk/lib/libraries.json pkg/front_end/benchmarks/ikg/hello.dart pkg/front_end/benchmarks/ikg/hello.edits.json
- out/ReleaseX64/dart --background-compilation=false pkg/front_end/tool/incremental_perf.dart.appjit --target=vm --mode=legacy --sdk-summary=out/ReleaseX64/vm_platform.dill --sdk-library-specification=sdk/lib/libraries.json pkg/front_end/benchmarks/ikg/hello.dart pkg/front_end/benchmarks/ikg/hello.edits.json
out/ReleaseX64/dart --background-compilation=false pkg/front_end/tool/incremental_perf.dart.appjit --target=vm --implementation=minimal --sdk-summary=out/ReleaseX64/vm_platform_strong.dill --sdk-library-specification=sdk/lib/libraries.json pkg/front_end/benchmarks/ikg/hello.dart pkg/front_end/benchmarks/ikg/hello.edits.json
- out/ReleaseX64/dart --background-compilation=false pkg/front_end/tool/incremental_perf.dart.appjit --target=vm --mode=legacy --implementation=minimal --sdk-summary=out/ReleaseX64/vm_platform.dill --sdk-library-specification=sdk/lib/libraries.json pkg/front_end/benchmarks/ikg/hello.dart pkg/front_end/benchmarks/ikg/hello.edits.json
- out/ReleaseX64/dart --packages=.packages pkg/kernel/test/binary_bench.dart --golem AstFromBinaryLazy out/ReleaseX64/vm_platform.dill
+ out/ReleaseX64/dart --packages=.packages pkg/kernel/test/binary_bench.dart --golem AstFromBinaryLazy out/ReleaseX64/vm_platform_strong.dill
cd ..
rm -rf tmp
else
diff --git a/utils/application_snapshot.gni b/utils/application_snapshot.gni
index e8e6d35..b225d40 100644
--- a/utils/application_snapshot.gni
+++ b/utils/application_snapshot.gni
@@ -143,7 +143,7 @@
deps = []
}
deps += [
- "$_dart_root/utils/kernel-service:kernel-service_snapshot"
+ "$_dart_root/utils/kernel-service:kernel-service"
]
}
}