Version 2.15.0-99.0.dev
Merge commit 'e47850a197c5d2522e67a1b8dd11427829ce6f04' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 3857a2d..9ba9c1e 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
"constraint, update this by running tools/generate_package_config.dart."
],
"configVersion": 2,
- "generated": "2021-09-10T10:06:41.987732",
+ "generated": "2021-09-10T11:44:31.694550",
"generator": "tools/generate_package_config.dart",
"packages": [
{
@@ -112,7 +112,7 @@
"name": "async",
"rootUri": "../third_party/pkg/async",
"packageUri": "lib/",
- "languageVersion": "2.12"
+ "languageVersion": "2.14"
},
{
"name": "async_helper",
diff --git a/DEPS b/DEPS
index 5416d53..4d6d801 100644
--- a/DEPS
+++ b/DEPS
@@ -73,7 +73,7 @@
# Revisions of /third_party/* dependencies.
"args_rev": "3b3f55766af13d895d2020ec001a28e8dc147f91",
- "async_rev": "ecb3835c5b746f7762327d5f57bdc92e0a2e0450",
+ "async_rev": "c64220396e0fa2f7b380590abfedbd25635cd7a0",
"bazel_worker_rev": "0885637b037979afbf5bcd05fd748b309fd669c0",
"benchmark_harness_rev": "c546dbd9f639f75cd2f75de8df2eb9f8ea15e8e7",
"boolean_selector_rev": "665e6921ab246569420376f827bff4585dff0b14",
@@ -139,7 +139,7 @@
"process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
"protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
"pub_rev": "cd7a43f2109f7e5eb22e73c7f4e15d25fd57598e",
- "pub_semver_rev": "baeea5ac3503546269d25c66523d4334c784a4f9",
+ "pub_semver_rev": "a43ad72fb6b7869607581b5fedcb186d1e74276a",
"resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
"root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
"rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
diff --git a/pkg/analysis_server/test/integration/linter/lint_names_test.dart b/pkg/analysis_server/test/integration/linter/lint_names_test.dart
index e30881f..58031e7 100644
--- a/pkg/analysis_server/test/integration/linter/lint_names_test.dart
+++ b/pkg/analysis_server/test/integration/linter/lint_names_test.dart
@@ -2,39 +2,37 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'dart:io';
-
-import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/scanner/reader.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/lint/registry.dart';
-import 'package:analyzer/src/string_source.dart';
+import 'package:analyzer_utilities/package_root.dart';
import 'package:linter/src/rules.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
void main() {
- // Set prefix for local or bot execution.
- final pathPrefix =
- FileSystemEntity.isDirectorySync(path.join('test', 'integration'))
- ? ''
- : path.join('pkg', 'analysis_server');
-
/// Ensure server lint name representations correspond w/ actual lint rules.
/// See, e.g., https://dart-review.googlesource.com/c/sdk/+/95743.
group('lint_names', () {
- var fixFileContents = File(path.join(
- pathPrefix, 'lib', 'src', 'services', 'linter', 'lint_names.dart'))
- .readAsStringSync();
- var parser = CompilationUnitParser();
- var cu = parser.parse(contents: fixFileContents, name: 'lint_names.dart');
- var lintNamesClass = cu.declarations
+ var pkgRootPath = path.normalize(packageRoot);
+ var fixFilePath = path.join(pkgRootPath, 'analysis_server', 'lib', 'src',
+ 'services', 'linter', 'lint_names.dart');
+ var contextCollection = AnalysisContextCollection(
+ includedPaths: [fixFilePath],
+ );
+ var parseResult = contextCollection
+ .contextFor(fixFilePath)
+ .currentSession
+ .getParsedUnit(fixFilePath) as ParsedUnitResult;
+
+ if (parseResult.errors.isNotEmpty) {
+ throw Exception(parseResult.errors);
+ }
+
+ var lintNamesClass = parseResult.unit.declarations
.firstWhere((m) => m is ClassDeclaration && m.name.name == 'LintNames');
var collector = _FixCollector();
@@ -63,47 +61,6 @@
return registeredLints;
}
-class CompilationUnitParser {
- CompilationUnit parse({required String contents, required String name}) {
- var reader = CharSequenceReader(contents);
- var stringSource = StringSource(contents, name);
- var errorListener = _ErrorListener();
- var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
- var scanner = Scanner(stringSource, reader, errorListener)
- ..configureFeatures(
- featureSetForOverriding: featureSet,
- featureSet: featureSet,
- );
- var startToken = scanner.tokenize();
- errorListener.throwIfErrors();
-
- var parser = Parser(
- stringSource,
- errorListener,
- featureSet: featureSet,
- );
- var cu = parser.parseCompilationUnit(startToken);
- errorListener.throwIfErrors();
-
- return cu;
- }
-}
-
-class _ErrorListener implements AnalysisErrorListener {
- final errors = <AnalysisError>[];
-
- @override
- void onError(AnalysisError error) {
- errors.add(error);
- }
-
- void throwIfErrors() {
- if (errors.isNotEmpty) {
- throw Exception(errors);
- }
- }
-}
-
class _FixCollector extends GeneralizingAstVisitor<void> {
final List<String> lintNames = <String>[];
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index 5837c7d..da2cae0 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -216,7 +216,7 @@
/// to break the text when building edits.
List<int> _getBreakOffsets(String text) {
var breakOffsets = <int>[];
- var featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+ var featureSet = FeatureSet.latestLanguageVersion();
var scanner = Scanner(_TestSource(), CharSequenceReader(text),
error.AnalysisErrorListener.NULL_LISTENER)
..configureFeatures(
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
index f03c6aa..88ced1a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
@@ -40,12 +40,6 @@
/// The current language version.
static final Version currentVersion = Version.parse(_currentVersion);
- /// The language version to use in tests.
- static final Version testingSdkLanguageVersion = Version.parse('2.10.0');
-
- /// The latest known language version.
- static final Version latestSdkLanguageVersion = Version.parse('2.13.0');
-
/// A map containing information about all known experimental flags.
static final Map<String, ExperimentalFeature> knownFeatures = _knownFeatures;
@@ -73,7 +67,7 @@
explicitFlags.enabled[(feature as ExperimentalFeature).index] = true;
}
- var sdkLanguageVersion = latestSdkLanguageVersion;
+ var sdkLanguageVersion = currentVersion;
var flags = restrictEnableFlagsToVersion(
sdkLanguageVersion: sdkLanguageVersion,
explicitEnabledFlags: explicitFlags.enabled,
@@ -130,7 +124,7 @@
/// the flag appearing last.
factory ExperimentStatus.fromStrings(List<String> flags) {
return ExperimentStatus.fromStrings2(
- sdkLanguageVersion: latestSdkLanguageVersion,
+ sdkLanguageVersion: currentVersion,
flags: flags,
);
}
@@ -165,7 +159,7 @@
factory ExperimentStatus.latestLanguageVersion() {
return ExperimentStatus.fromStrings2(
- sdkLanguageVersion: latestSdkLanguageVersion,
+ sdkLanguageVersion: currentVersion,
flags: [],
);
}
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index f89ac53..0e1d054 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -129,6 +129,18 @@
}
@override
+ void visitGenericFunctionType(GenericFunctionType node) {
+ // TODO(srawlins): Also check interface types (TypeName?).
+ super.visitGenericFunctionType(node);
+ var parent = node.parent;
+ if ((parent is AsExpression || parent is IsExpression) &&
+ (parent as Expression).inConstantContext) {
+ _checkForConstWithTypeParameters(
+ node, CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS);
+ }
+ }
+
+ @override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
if (node.isConst) {
TypeName typeName = node.constructorName.type;
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index af1fa6f..c4f5c6a 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1093,6 +1093,8 @@
@override
DartObjectImpl? visitConstructorReference(ConstructorReference node) {
+ // TODO(srawlins): record type arguments in DartObject as well, as in
+ // [visitFunctionReference] below.
return _getConstantValue(node, node.constructorName.staticElement);
}
@@ -1106,6 +1108,47 @@
}
@override
+ DartObjectImpl? visitFunctionReference(FunctionReference node) {
+ var functionResult = node.function.accept(this);
+ if (functionResult == null) {
+ return functionResult;
+ }
+ var typeArgumentList = node.typeArguments;
+ if (typeArgumentList == null) {
+ return functionResult;
+ } else {
+ var typeArguments = <DartType>[];
+ var typeArgumentObjects = <DartObjectImpl>[];
+ for (var typeArgument in typeArgumentList.arguments) {
+ var object = typeArgument.accept(this);
+ if (object == null) {
+ return null;
+ }
+ var typeArgumentType = object.toTypeValue();
+ if (typeArgumentType == null) {
+ return null;
+ }
+ // TODO(srawlins): Test type alias types (`typedef i = int`) used as
+ // type arguments. Possibly change implementation based on
+ // canonicalization rules.
+ typeArguments.add(typeArgumentType);
+ typeArgumentObjects.add(object);
+ }
+ return _dartObjectComputer.typeInstantiate(
+ node, functionResult, typeArguments, typeArgumentObjects);
+ }
+ }
+
+ @override
+ DartObjectImpl visitGenericFunctionType(GenericFunctionType node) {
+ return DartObjectImpl(
+ typeSystem,
+ _typeProvider.typeType,
+ TypeState(node.type),
+ );
+ }
+
+ @override
DartObjectImpl? visitInstanceCreationExpression(
InstanceCreationExpression node) {
if (!node.isConst) {
@@ -2103,6 +2146,24 @@
return null;
}
+ DartObjectImpl? typeInstantiate(
+ FunctionReference node,
+ DartObjectImpl function,
+ List<DartType> typeArguments,
+ List<DartObjectImpl> typeArgumentObjects,
+ ) {
+ var rawType = function.type;
+ if (rawType is FunctionType) {
+ if (typeArguments.length != rawType.typeFormals.length) {
+ return null;
+ }
+ var type = rawType.instantiate(typeArguments);
+ return function.typeInstantiate(_typeSystem, type, typeArgumentObjects);
+ } else {
+ return null;
+ }
+ }
+
DartObjectImpl? typeTest(
IsExpression node, DartObjectImpl? expression, DartObjectImpl? type) {
if (expression != null && type != null) {
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index 14aa28c..24f2212 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -13,7 +13,9 @@
import 'package:analyzer/src/dart/constant/has_type_parameter_reference.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/utilities_general.dart';
+import 'package:meta/meta.dart';
/// The state of an object representing a boolean value.
class BoolState extends InstanceState {
@@ -209,6 +211,10 @@
/// class.
bool get isUserDefinedObject => _state is GenericState;
+ @visibleForTesting
+ List<DartObjectImpl>? get typeArguments =>
+ (_state as FunctionState)._typeArguments;
+
@override
bool operator ==(Object object) {
if (object is DartObjectImpl) {
@@ -917,6 +923,20 @@
return null;
}
+ DartObjectImpl? typeInstantiate(
+ TypeSystemImpl typeSystem,
+ FunctionType type,
+ List<DartObjectImpl> typeArguments,
+ ) {
+ var functionState = _state as FunctionState;
+ var element = functionState._element;
+ return DartObjectImpl(
+ typeSystem,
+ type,
+ FunctionState(element, typeArguments: typeArguments),
+ );
+ }
+
/// Throw an exception if the given [object]'s state does not represent a Type
/// value.
void _assertType(DartObjectImpl object) {
@@ -1232,9 +1252,12 @@
/// The element representing the function being modeled.
final ExecutableElement? _element;
+ final List<DartObjectImpl>? _typeArguments;
+
/// Initialize a newly created state to represent the function with the given
/// [element].
- FunctionState(this._element);
+ FunctionState(this._element, {List<DartObjectImpl>? typeArguments})
+ : _typeArguments = typeArguments;
@override
int get hashCode => _element == null ? 0 : _element.hashCode;
@@ -1243,8 +1266,28 @@
String get typeName => "Function";
@override
- bool operator ==(Object object) =>
- object is FunctionState && (_element == object._element);
+ bool operator ==(Object object) {
+ if (object is! FunctionState) {
+ return false;
+ }
+ if (_element != object._element) {
+ return false;
+ }
+ var typeArguments = _typeArguments;
+ var otherTypeArguments = object._typeArguments;
+ if (typeArguments == null || otherTypeArguments == null) {
+ return typeArguments == null && otherTypeArguments == null;
+ }
+ if (typeArguments.length != otherTypeArguments.length) {
+ return false;
+ }
+ for (var i = 0; i < typeArguments.length; i++) {
+ if (typeArguments[i] != otherTypeArguments[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
@override
StringState convertToString() {
@@ -1269,7 +1312,24 @@
if (rightElement == null) {
return BoolState.UNKNOWN_VALUE;
}
- return BoolState.from(_element == rightElement);
+ if (_element != rightElement) {
+ return BoolState.FALSE_STATE;
+ }
+ var typeArguments = _typeArguments;
+ var otherTypeArguments = rightOperand._typeArguments;
+ if (typeArguments == null || otherTypeArguments == null) {
+ return BoolState.from(
+ typeArguments == null && otherTypeArguments == null);
+ }
+ if (typeArguments.length != otherTypeArguments.length) {
+ return BoolState.FALSE_STATE;
+ }
+ for (var i = 0; i < typeArguments.length; i++) {
+ if (typeArguments[i] != otherTypeArguments[i]) {
+ return BoolState.FALSE_STATE;
+ }
+ }
+ return BoolState.TRUE_STATE;
}
return BoolState.FALSE_STATE;
}
diff --git a/pkg/analyzer/lib/src/error/use_result_verifier.dart b/pkg/analyzer/lib/src/error/use_result_verifier.dart
index fd0eaed..1899064 100644
--- a/pkg/analyzer/lib/src/error/use_result_verifier.dart
+++ b/pkg/analyzer/lib/src/error/use_result_verifier.dart
@@ -52,6 +52,11 @@
}
void _check(AstNode node, Element element) {
+ if (node.parent is CommentReference) {
+ // Don't flag references in comments.
+ return;
+ }
+
var annotation = _getUseResultMetadata(element);
if (annotation == null) {
return;
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index b53f44c..a33890a 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
@@ -203,8 +202,8 @@
return spec;
}
- static LibraryElementImpl library(AnalysisContext context, String libraryName,
- {bool isNonNullableByDefault = true}) {
+ static LibraryElementImpl library(
+ AnalysisContext context, String libraryName) {
String fileName = "/$libraryName.dart";
CompilationUnitElementImpl unit = compilationUnit(fileName);
LibraryElementImpl library = LibraryElementImpl(
@@ -213,10 +212,7 @@
libraryName,
0,
libraryName.length,
- FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: ExperimentStatus.testingSdkLanguageVersion,
- flags: isNonNullableByDefault ? [EnableString.non_nullable] : [],
- ),
+ FeatureSet.latestLanguageVersion(),
);
library.definingCompilationUnit = unit;
return library;
diff --git a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
index 4269b08..3c7de8d 100644
--- a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
@@ -28,6 +28,7 @@
void visitAnnotation(Annotation node) {
_token(node.atSign);
node.name.accept(this);
+ node.typeArguments?.accept(this);
_token(node.period);
node.constructorName?.accept(this);
node.arguments?.accept(this);
@@ -234,6 +235,11 @@
}
@override
+ void visitConstructorReference(ConstructorReference node) {
+ node.constructorName.accept(this);
+ }
+
+ @override
void visitContinueStatement(ContinueStatement node) {
_token(node.continueKeyword);
node.label?.accept(this);
@@ -487,6 +493,12 @@
}
@override
+ void visitFunctionReference(FunctionReference node) {
+ node.function.accept(this);
+ node.typeArguments?.accept(this);
+ }
+
+ @override
void visitFunctionTypeAlias(FunctionTypeAlias node) {
_compilationUnitMember(node);
_token(node.typedefKeyword);
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index 6a7dec8..afe00a5 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -6,7 +6,6 @@
import 'dart:collection';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
@@ -674,7 +673,7 @@
.join()
.contains('dart_package(null_safety=True');
if (hasNonNullableFlag) {
- _enabledExperiments = [EnableString.non_nullable];
+ // Enabled by default.
} else {
_languageVersion = Version.parse('2.9.0');
}
diff --git a/pkg/analyzer/test/dart/analysis/utilities_test.dart b/pkg/analyzer/test/dart/analysis/utilities_test.dart
index 2ac1bac..36bdc90 100644
--- a/pkg/analyzer/test/dart/analysis/utilities_test.dart
+++ b/pkg/analyzer/test/dart/analysis/utilities_test.dart
@@ -22,15 +22,14 @@
@reflectiveTest
class UtilitiesTest with ResourceProviderMixin {
- FeatureSet get defaultFeatureSet =>
- FeatureSet.forTesting(sdkVersion: '2.2.2');
-
test_parseFile_default_resource_provider() {
String content = '''
void main() => print('Hello, world!');
''';
- ParseStringResult result = _withTemporaryFile(content,
- (path) => parseFile(path: path, featureSet: defaultFeatureSet));
+ ParseStringResult result = _withTemporaryFile(
+ content,
+ (path) => parseFile(
+ path: path, featureSet: FeatureSet.latestLanguageVersion()));
expect(result.content, content);
expect(result.errors, isEmpty);
expect(result.lineInfo, isNotNull);
@@ -46,7 +45,7 @@
content,
(resourceProvider, path) => parseFile(
path: path,
- featureSet: defaultFeatureSet,
+ featureSet: FeatureSet.latestLanguageVersion(),
resourceProvider: resourceProvider,
throwIfDiagnostics: false));
expect(result.content, content);
@@ -66,7 +65,7 @@
expectedPath = path;
return parseFile(
path: path,
- featureSet: defaultFeatureSet,
+ featureSet: FeatureSet.latestLanguageVersion(),
resourceProvider: resourceProvider,
throwIfDiagnostics: false);
});
@@ -83,12 +82,12 @@
content,
(resourceProvider, path) => parseFile(
path: path,
- featureSet: defaultFeatureSet,
+ featureSet: FeatureSet.latestLanguageVersion(),
resourceProvider: resourceProvider)),
throwsA(const TypeMatcher<ArgumentError>()));
}
- test_parseFile_featureSet_nnbd_off() {
+ test_parseFile_featureSet_language_2_9() {
String content = '''
int? f() => 1;
''';
@@ -110,19 +109,17 @@
expect(result.unit.toString(), equals('int? f() => 1;'));
}
- test_parseFile_featureSet_nnbd_on() {
+ test_parseFile_featureSet_language_latest() {
String content = '''
int? f() => 1;
''';
- var featureSet =
- FeatureSet.forTesting(additionalFeatures: [Feature.non_nullable]);
ParseStringResult result = _withMemoryFile(
content,
(resourceProvider, path) => parseFile(
path: path,
resourceProvider: resourceProvider,
throwIfDiagnostics: false,
- featureSet: featureSet));
+ featureSet: FeatureSet.latestLanguageVersion()));
expect(result.content, content);
expect(result.errors, isEmpty);
expect(result.lineInfo, isNotNull);
@@ -137,7 +134,7 @@
content,
(resourceProvider, path) => parseFile(
path: path,
- featureSet: defaultFeatureSet,
+ featureSet: FeatureSet.latestLanguageVersion(),
resourceProvider: resourceProvider));
expect(result.content, content);
expect(result.errors, isEmpty);
@@ -200,10 +197,11 @@
String content = '''
int? f() => 1;
''';
- var featureSet =
- FeatureSet.forTesting(additionalFeatures: [Feature.non_nullable]);
ParseStringResult result = parseString(
- content: content, throwIfDiagnostics: false, featureSet: featureSet);
+ content: content,
+ throwIfDiagnostics: false,
+ featureSet: FeatureSet.latestLanguageVersion(),
+ );
expect(result.content, content);
expect(result.errors, isEmpty);
expect(result.lineInfo, isNotNull);
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index e7da3d0..4718ea0 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -2,22 +2,17 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/generated/parser.dart';
import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
-import 'package:analyzer/src/string_source.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../generated/parser_test_base.dart' show ParserTestCase;
-import '../../generated/test_support.dart';
main() {
defineReflectiveSuite(() {
@@ -943,29 +938,10 @@
E f() => g;
''';
- final featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
-
CompilationUnit? _unit;
CompilationUnit get unit {
- if (_unit == null) {
- GatheringErrorListener listener =
- GatheringErrorListener(checkRanges: true);
- var source =
- StringSource(contents, 'PreviousTokenTest_findPrevious.dart');
- var scanner = Scanner.fasta(source, listener)
- ..configureFeatures(
- featureSetForOverriding: featureSet,
- featureSet: featureSet,
- );
- Token tokens = scanner.tokenize();
- _unit = Parser(
- source,
- listener,
- featureSet: featureSet,
- ).parseCompilationUnit(tokens);
- }
- return _unit!;
+ return _unit ??= parseString(content: contents).unit;
}
Token findToken(String lexeme) {
@@ -1005,15 +981,10 @@
var body = method.body as BlockFunctionBody;
Statement statement = body.block.statements[0];
- GatheringErrorListener listener = GatheringErrorListener(checkRanges: true);
- var source = StringSource('missing', 'PreviousTokenTest_missing.dart');
- var scanner = Scanner.fasta(source, listener)
- ..configureFeatures(
- featureSetForOverriding: featureSet,
- featureSet: featureSet,
- );
- Token missing = scanner.tokenize();
-
+ var missing = parseString(
+ content: 'missing',
+ throwIfDiagnostics: false,
+ ).unit.beginToken;
expect(statement.findPrevious(missing), null);
}
diff --git a/pkg/analyzer/test/generated/class_member_parser_test.dart b/pkg/analyzer/test/generated/class_member_parser_test.dart
index 25467ad..515d419 100644
--- a/pkg/analyzer/test/generated/class_member_parser_test.dart
+++ b/pkg/analyzer/test/generated/class_member_parser_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
@@ -22,9 +21,6 @@
@reflectiveTest
class ClassMemberParserTest extends FastaParserTestCase
implements AbstractParserViaProxyTestCase {
- final tripleShift = FeatureSet.forTesting(
- sdkVersion: '2.0.0', additionalFeatures: [Feature.triple_shift]);
-
void test_parse_member_called_late() {
var unit = parseCompilationUnit(
'class C { void late() { new C().late(); } }',
@@ -1032,8 +1028,8 @@
void test_parseClassMember_operator_gtgtgt() {
var unit = parseCompilationUnit(
- 'class C { bool operator >>>(other) => false; }',
- featureSet: tripleShift);
+ 'class C { bool operator >>>(other) => false; }',
+ );
var declaration = unit.declarations[0] as ClassDeclaration;
var method = declaration.members[0] as MethodDeclaration;
@@ -1051,8 +1047,8 @@
void test_parseClassMember_operator_gtgtgteq() {
var unit = parseCompilationUnit(
- 'class C { foo(int value) { x >>>= value; } }',
- featureSet: tripleShift);
+ 'class C { foo(int value) { x >>>= value; } }',
+ );
var declaration = unit.declarations[0] as ClassDeclaration;
var method = declaration.members[0] as MethodDeclaration;
var blockFunctionBody = method.body as BlockFunctionBody;
diff --git a/pkg/analyzer/test/generated/collection_literal_parser_test.dart b/pkg/analyzer/test/generated/collection_literal_parser_test.dart
index b5b211a..7e39201 100644
--- a/pkg/analyzer/test/generated/collection_literal_parser_test.dart
+++ b/pkg/analyzer/test/generated/collection_literal_parser_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:test/test.dart';
@@ -24,17 +23,13 @@
List<ExpectedError>? errors,
int? expectedEndOffset,
bool inAsync = false}) {
- return parseExpression(source,
- codes: codes,
- errors: errors,
- expectedEndOffset: expectedEndOffset,
- inAsync: inAsync,
- featureSet: FeatureSet.forTesting(
- sdkVersion: '2.0.0',
- additionalFeatures: [
- Feature.spread_collections,
- Feature.control_flow_collections
- ]));
+ return parseExpression(
+ source,
+ codes: codes,
+ errors: errors,
+ expectedEndOffset: expectedEndOffset,
+ inAsync: inAsync,
+ );
}
void test_listLiteral_for() {
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index 4920947..4a17b0e 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -20,6 +20,19 @@
@reflectiveTest
class ConstantEvaluatorTest extends PubPackageResolutionTest {
+ void assertTypeArguments(DartObject value, List<String>? typeArgumentNames) {
+ var typeArguments = (value as DartObjectImpl).typeArguments;
+ if (typeArguments == null) {
+ expect(typeArguments, typeArgumentNames);
+ return;
+ }
+ expect(
+ typeArguments.map(
+ (arg) => arg.toTypeValue()!.getDisplayString(withNullability: false)),
+ equals(typeArgumentNames),
+ );
+ }
+
test_bitAnd_int_int() async {
await _assertValueInt(74 & 42, "74 & 42");
}
@@ -213,6 +226,100 @@
await _assertValueBool(false, "'a' == 'b'");
}
+ test_functionReference_explicitTypeArgs_badBound() async {
+ var result = await _getExpressionValue("foo<String>", context: '''
+void foo<T extends num>(T a) {}
+''');
+ expect(result.isValid, isTrue);
+ DartObject value = result.value!;
+ assertType(value.type, 'void Function(String)');
+ assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
+ assertTypeArguments(value, ['String']);
+ }
+
+ test_functionReference_explicitTypeArgs_differentElements() async {
+ var result = await _getExpressionValue("(b ? foo : bar)<int>", context: '''
+const b = true;
+void foo<T>(String a, T b) {}
+void bar<T>(T a, String b) {}
+''');
+ expect(result.isValid, isTrue);
+ DartObject value = result.value!;
+ assertType(value.type, 'void Function(String, int)');
+ assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
+ assertTypeArguments(value, ['int']);
+ }
+
+ test_functionReference_explicitTypeArgs_identifier() async {
+ // TODO(srawlins): Add test where the type argument is a type variable.
+ var result = await _getExpressionValue("foo<int>", context: '''
+void foo<T>(T a) {}
+''');
+ expect(result.isValid, isTrue);
+ var value = result.value!;
+ assertType(value.type, 'void Function(int)');
+ assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
+ assertTypeArguments(value, ['int']);
+ }
+
+ test_functionReference_explicitTypeArgs_nonIdentifier() async {
+ var result = await _getExpressionValue("(b ? foo : bar)<int>", context: '''
+const b = true;
+void foo<T>(T a) {}
+void bar<T>(T a) {}
+''');
+ expect(result.isValid, isTrue);
+ var value = result.value!;
+ assertType(value.type, 'void Function(int)');
+ assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
+ assertTypeArguments(value, ['int']);
+ }
+
+ test_functionReference_explicitTypeArgs_notAType() async {
+ var result = await _getExpressionValue("foo<true>", context: '''
+void foo<T>(T a) {}
+''');
+ expect(result.isValid, isFalse);
+ }
+
+ test_functionReference_explicitTypeArgs_tooFew() async {
+ var result = await _getExpressionValue("foo<int>", context: '''
+void foo<T, U>(T a) {}
+''');
+ expect(result.isValid, isFalse);
+ }
+
+ test_functionReference_explicitTypeArgs_tooMany() async {
+ var result = await _getExpressionValue("foo<int, int>", context: '''
+void foo<T>(T a) {}
+''');
+ expect(result.isValid, isFalse);
+ }
+
+ test_functionReference_uninstantiated_identifier() async {
+ var result = await _getExpressionValue("foo", context: '''
+void foo<T>(T a) {}
+''');
+ expect(result.isValid, isTrue);
+ DartObject value = result.value!;
+ assertType(value.type, 'void Function<T>(T)');
+ assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
+ assertTypeArguments(value, null);
+ }
+
+ test_functionReference_uninstantiated_nonIdentifier() async {
+ var result = await _getExpressionValue("b ? foo : bar", context: '''
+const b = true;
+void foo<T>(T a) {}
+void bar<T>(T a) {}
+''');
+ expect(result.isValid, isTrue);
+ DartObject value = result.value!;
+ assertType(value.type, 'void Function<T>(T)');
+ assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
+ assertTypeArguments(value, null);
+ }
+
test_greaterThan_int_int() async {
await _assertValueBool(false, "2 > 3");
}
@@ -221,6 +328,51 @@
await _assertValueBool(false, "2 >= 3");
}
+ test_identical_functionReference_explicitTypeArgs_differentElements() async {
+ var result =
+ await _getExpressionValue("identical(foo<int>, bar<int>)", context: '''
+void foo<T>(T a) {}
+void bar<T>(T a) {}
+''');
+ expect(result.isValid, isTrue);
+ DartObject value = result.value!;
+ assertType(value.type, 'bool');
+ expect(value.toBoolValue(), false);
+ }
+
+ test_identical_functionReference_explicitTypeArgs_differentTypeArgs() async {
+ var result = await _getExpressionValue("identical(foo<int>, foo<String>)",
+ context: '''
+void foo<T>(T a) {}
+''');
+ expect(result.isValid, isTrue);
+ DartObject value = result.value!;
+ assertType(value.type, 'bool');
+ expect(value.toBoolValue(), false);
+ }
+
+ test_identical_functionReference_explicitTypeArgs_sameElement() async {
+ var result =
+ await _getExpressionValue("identical(foo<int>, foo<int>)", context: '''
+void foo<T>(T a) {}
+''');
+ expect(result.isValid, isTrue);
+ DartObject value = result.value!;
+ assertType(value.type, 'bool');
+ expect(value.toBoolValue(), true);
+ }
+
+ test_identical_functionReference_onlyOneHasTypeArgs() async {
+ var result =
+ await _getExpressionValue("identical(foo<int>, foo)", context: '''
+void foo<T>(T a) {}
+''');
+ expect(result.isValid, isTrue);
+ DartObject value = result.value!;
+ assertType(value.type, 'bool');
+ expect(value.toBoolValue(), false);
+ }
+
@failingTest
test_identifier_class() async {
var result = await _getExpressionValue("?");
@@ -294,6 +446,16 @@
expect(result.isValid, isTrue);
}
+ test_literal_list_explicitType() async {
+ var result = await _getExpressionValue("const <String>['a', 'b', 'c']");
+ expect(result.isValid, isTrue);
+ }
+
+ test_literal_list_explicitType_functionType() async {
+ var result = await _getExpressionValue("const <void Function()>[]");
+ expect(result.isValid, isTrue);
+ }
+
test_literal_list_forElement() async {
var result = await _getExpressionValue('''
const [for (var i = 0; i < 4; i++) i]
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index 1d3df59..074ada9 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -716,15 +716,14 @@
Source source = FileSource(getFile("/test.dart"));
CompilationUnitElementImpl unit = CompilationUnitElementImpl();
unit.librarySource = unit.source = source;
- _definingLibrary =
- ElementFactory.library(context, "test", isNonNullableByDefault: false);
+ _definingLibrary = ElementFactory.library(context, "test");
_definingLibrary.definingCompilationUnit = unit;
_definingLibrary.typeProvider = context.typeProviderLegacy;
_definingLibrary.typeSystem = context.typeSystemLegacy;
var inheritance = InheritanceManager3();
- var featureSet = FeatureSet.forTesting();
+ var featureSet = FeatureSet.latestLanguageVersion();
_visitor = ResolverVisitor(
inheritance, _definingLibrary, source, _typeProvider, _listener,
featureSet: featureSet,
diff --git a/pkg/analyzer/test/generated/elements_types_mixin.dart b/pkg/analyzer/test/generated/elements_types_mixin.dart
index c201074..8c01ffe 100644
--- a/pkg/analyzer/test/generated/elements_types_mixin.dart
+++ b/pkg/analyzer/test/generated/elements_types_mixin.dart
@@ -7,7 +7,6 @@
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
@@ -374,12 +373,7 @@
uriStr,
-1,
0,
- FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: ExperimentStatus.testingSdkLanguageVersion,
- flags: typeSystem.isNonNullableByDefault
- ? [EnableString.non_nullable]
- : [],
- ),
+ FeatureSet.latestLanguageVersion(),
);
library.typeSystem = typeSystem;
library.typeProvider = typeSystem.typeProvider;
diff --git a/pkg/analyzer/test/generated/generic_metadata_parser_test.dart b/pkg/analyzer/test/generated/generic_metadata_parser_test.dart
index 05e1c6d..c4627d1 100644
--- a/pkg/analyzer/test/generated/generic_metadata_parser_test.dart
+++ b/pkg/analyzer/test/generated/generic_metadata_parser_test.dart
@@ -5,6 +5,7 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -26,9 +27,14 @@
{List<ExpectedError>? errors, required ExpectedError? disabledError}) {
var combinedErrors =
disabledError == null ? errors : [disabledError, ...?errors];
- return parseCompilationUnit(content,
- errors: combinedErrors,
- featureSet: FeatureSet.forTesting(sdkVersion: '2.12'));
+ return parseCompilationUnit(
+ content,
+ errors: combinedErrors,
+ featureSet: FeatureSet.fromEnableFlags2(
+ sdkLanguageVersion: Version.parse('2.12.0'),
+ flags: [],
+ ),
+ );
}
}
@@ -39,11 +45,7 @@
CompilationUnit _parseCompilationUnit(String content,
{List<ExpectedError>? errors,
required ExpectedError? disabledError}) =>
- parseCompilationUnit(content,
- errors: errors,
- featureSet: FeatureSet.forTesting(
- sdkVersion: '2.12',
- additionalFeatures: [Feature.generic_metadata]));
+ parseCompilationUnit(content, errors: errors);
}
mixin GenericMetadataParserTest on FastaParserTestCase {
diff --git a/pkg/analyzer/test/generated/parser_test_base.dart b/pkg/analyzer/test/generated/parser_test_base.dart
index 956e4ae..aa56d56 100644
--- a/pkg/analyzer/test/generated/parser_test_base.dart
+++ b/pkg/analyzer/test/generated/parser_test_base.dart
@@ -14,6 +14,7 @@
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart' show CompilationUnitImpl;
import 'package:analyzer/src/dart/ast/ast_factory.dart';
import 'package:analyzer/src/dart/ast/token.dart';
@@ -220,8 +221,10 @@
implements AbstractParserTestCase {
static final List<ErrorCode> NO_ERROR_COMPARISON = <ErrorCode>[];
- final constructorTearoffs = FeatureSet.forTesting(
- sdkVersion: '2.14.0', additionalFeatures: [Feature.constructor_tearoffs]);
+ final constructorTearoffs = FeatureSet.fromEnableFlags2(
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
+ flags: [EnableString.constructor_tearoffs],
+ );
final controlFlow = FeatureSet.latestLanguageVersion();
@@ -289,7 +292,7 @@
@override
void createParser(String content,
{int? expectedEndOffset, FeatureSet? featureSet}) {
- featureSet ??= FeatureSet.forTesting();
+ featureSet ??= FeatureSet.latestLanguageVersion();
var result = scanString(content,
configuration: featureSet.isEnabled(Feature.non_nullable)
? ScannerConfiguration.nonNullable
@@ -407,8 +410,8 @@
CompilationUnitImpl parseCompilationUnit2(
String content, GatheringErrorListener listener,
- {LanguageVersionToken? languageVersion, FeatureSet? featureSet}) {
- featureSet ??= FeatureSet.forTesting();
+ {FeatureSet? featureSet}) {
+ featureSet ??= FeatureSet.latestLanguageVersion();
var source = StringSource(content, 'parser_test_StringSource.dart');
// Adjust the feature set based on language version comment.
@@ -1166,7 +1169,7 @@
analyzer.Parser parser = analyzer.Parser(
source,
listener,
- featureSet: FeatureSet.forTesting(),
+ featureSet: FeatureSet.latestLanguageVersion(),
);
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
CompilationUnit unit = parser.parseCompilationUnit(result.tokens);
@@ -1193,7 +1196,7 @@
analyzer.Parser parser = analyzer.Parser(
source,
listener,
- featureSet: FeatureSet.forTesting(),
+ featureSet: FeatureSet.latestLanguageVersion(),
);
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
var unit = parser.parseCompilationUnit(result.tokens);
@@ -1471,7 +1474,7 @@
analyzer.Parser parser = analyzer.Parser(
source,
listener,
- featureSet: FeatureSet.forTesting(),
+ featureSet: FeatureSet.latestLanguageVersion(),
);
parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
Statement statement = parser.parseStatement(result.tokens);
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index ed20e1a..08cf6ac 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -82,7 +82,7 @@
@reflectiveTest
class LineInfoTest {
- final featureSet = FeatureSet.forTesting(sdkVersion: '2.2.2');
+ final featureSet = FeatureSet.latestLanguageVersion();
void test_lineInfo_multilineComment() {
String source = "/*\r\n *\r\n */";
@@ -208,8 +208,8 @@
expect(defaultFeatureSet.isEnabled(Feature.extension_methods), isTrue);
scanner.configureFeatures(
- featureSetForOverriding: FeatureSet.forTesting(),
- featureSet: FeatureSet.forTesting(),
+ featureSetForOverriding: FeatureSet.latestLanguageVersion(),
+ featureSet: FeatureSet.latestLanguageVersion(),
);
scanner.tokenize();
@@ -221,7 +221,7 @@
var scanner = _createScanner(r'''
// @dart = 99999999999999999999999999999999.0
''');
- var featureSet = FeatureSet.forTesting();
+ var featureSet = FeatureSet.latestLanguageVersion();
scanner.configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
@@ -234,7 +234,7 @@
var scanner = _createScanner(r'''
// @dart = 2.99999999999999999999999999999999
''');
- var featureSet = FeatureSet.forTesting();
+ var featureSet = FeatureSet.latestLanguageVersion();
scanner.configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet,
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 0e2c9d5..affcebc 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -503,7 +503,7 @@
CompilationUnitElementImpl();
definingCompilationUnit.librarySource =
definingCompilationUnit.source = source;
- var featureSet = FeatureSet.forTesting();
+ var featureSet = FeatureSet.latestLanguageVersion();
_definingLibrary = LibraryElementImpl(
context, _AnalysisSessionMock(), 'name', -1, 0, featureSet);
diff --git a/pkg/analyzer/test/generated/test_analysis_context.dart b/pkg/analyzer/test/generated/test_analysis_context.dart
index 473c34a..6702b63 100644
--- a/pkg/analyzer/test/generated/test_analysis_context.dart
+++ b/pkg/analyzer/test/generated/test_analysis_context.dart
@@ -28,7 +28,7 @@
TestAnalysisContext({FeatureSet? featureSet}) {
_analysisOptions = AnalysisOptionsImpl()
- ..contextFeatures = featureSet ?? FeatureSet.forTesting();
+ ..contextFeatures = featureSet ?? FeatureSet.latestLanguageVersion();
var sdkElements = MockSdkElements(this, _analysisSession);
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index 492236c..b0d0ce9 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -24,7 +24,7 @@
});
}
-abstract class AbstractTypeSystemNullSafetyTest with ElementsTypesMixin {
+abstract class AbstractTypeSystemTest with ElementsTypesMixin {
late TestAnalysisContext analysisContext;
@override
@@ -36,9 +36,7 @@
late TypeSystemImpl typeSystem;
FeatureSet get testFeatureSet {
- return FeatureSet.forTesting(
- additionalFeatures: [Feature.non_nullable],
- );
+ return FeatureSet.latestLanguageVersion();
}
void setUp() {
@@ -57,7 +55,7 @@
}
}
-abstract class AbstractTypeSystemTest with ElementsTypesMixin {
+abstract class AbstractTypeSystemWithoutNullSafetyTest with ElementsTypesMixin {
late TestAnalysisContext analysisContext;
@override
@@ -69,7 +67,7 @@
late TypeSystemImpl typeSystem;
FeatureSet get testFeatureSet {
- return FeatureSet.forTesting();
+ return FeatureSet.latestLanguageVersion();
}
void setUp() {
@@ -89,7 +87,7 @@
}
@reflectiveTest
-class AssignabilityTest extends AbstractTypeSystemTest {
+class AssignabilityTest extends AbstractTypeSystemWithoutNullSafetyTest {
void test_isAssignableTo_bottom_isBottom() {
var A = class_(name: 'A');
List<DartType> interassignable = <DartType>[
@@ -437,14 +435,7 @@
}
@reflectiveTest
-class TryPromoteToTest extends AbstractTypeSystemTest {
- @override
- FeatureSet get testFeatureSet {
- return FeatureSet.forTesting(
- additionalFeatures: [Feature.non_nullable],
- );
- }
-
+class TryPromoteToTest extends AbstractTypeSystemWithoutNullSafetyTest {
void notPromotes(DartType from, DartType to) {
var result = typeSystem.tryPromoteToType(to, from);
expect(result, isNull);
diff --git a/pkg/analyzer/test/generated/variance_parser_test.dart b/pkg/analyzer/test/generated/variance_parser_test.dart
index 1208056..37c8af3 100644
--- a/pkg/analyzer/test/generated/variance_parser_test.dart
+++ b/pkg/analyzer/test/generated/variance_parser_test.dart
@@ -5,6 +5,7 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:test/test.dart';
@@ -21,19 +22,24 @@
@reflectiveTest
class VarianceParserTest extends FastaParserTestCase {
+ final FeatureSet _disabledFeatureSet = FeatureSet.latestLanguageVersion();
+
+ final FeatureSet _enabledFeatureSet = FeatureSet.fromEnableFlags2(
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
+ flags: [EnableString.variance],
+ );
+
@override
CompilationUnitImpl parseCompilationUnit(String content,
{List<ErrorCode>? codes,
List<ExpectedError>? errors,
FeatureSet? featureSet}) {
- return super.parseCompilationUnit(content,
- codes: codes,
- errors: errors,
- featureSet: featureSet ??
- FeatureSet.forTesting(
- sdkVersion: '2.5.0',
- additionalFeatures: [Feature.variance],
- ));
+ return super.parseCompilationUnit(
+ content,
+ codes: codes,
+ errors: errors,
+ featureSet: featureSet ?? _enabledFeatureSet,
+ );
}
void test_class_disabled_multiple() {
@@ -43,7 +49,7 @@
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 14, 5),
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 23, 3)
],
- featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+ featureSet: _disabledFeatureSet);
}
void test_class_disabled_single() {
@@ -51,7 +57,7 @@
errors: [
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 3),
],
- featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+ featureSet: _disabledFeatureSet);
}
void test_class_enabled_multiple() {
@@ -124,7 +130,7 @@
ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 2),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 3),
],
- featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+ featureSet: _disabledFeatureSet);
}
void test_function_enabled() {
@@ -139,7 +145,7 @@
errors: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 6),
],
- featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+ featureSet: _disabledFeatureSet);
}
void test_list_enabled() {
@@ -154,7 +160,7 @@
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 5),
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 17, 3),
],
- featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+ featureSet: _disabledFeatureSet);
}
void test_mixin_disabled_single() {
@@ -162,7 +168,7 @@
errors: [
expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 8, 5),
],
- featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+ featureSet: _disabledFeatureSet);
}
void test_mixin_enabled_single() {
@@ -181,7 +187,7 @@
errors: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
],
- featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
+ featureSet: _disabledFeatureSet);
}
void test_typedef_enabled() {
diff --git a/pkg/analyzer/test/id_tests/nullability_test.dart b/pkg/analyzer/test/id_tests/nullability_test.dart
index c74f028..72fd2ef 100644
--- a/pkg/analyzer/test/id_tests/nullability_test.dart
+++ b/pkg/analyzer/test/id_tests/nullability_test.dart
@@ -35,11 +35,8 @@
/// Resolve the given [code] and track nullability in the unit.
Future<void> trackCode(String code) async {
- TestResult<String> testResult = await checkTests(
- code,
- const _NullabilityDataComputer(),
- FeatureSet.forTesting(
- sdkVersion: '2.2.2', additionalFeatures: [Feature.non_nullable]));
+ TestResult<String> testResult = await checkTests(code,
+ const _NullabilityDataComputer(), FeatureSet.latestLanguageVersion());
if (testResult.hasFailures) {
fail('Failure(s)');
}
diff --git a/pkg/analyzer/test/id_tests/reachability_test.dart b/pkg/analyzer/test/id_tests/reachability_test.dart
index 7b4c957..8714082 100644
--- a/pkg/analyzer/test/id_tests/reachability_test.dart
+++ b/pkg/analyzer/test/id_tests/reachability_test.dart
@@ -31,11 +31,8 @@
/// Resolve the given [code] and track nullability in the unit.
Future<void> trackCode(String code) async {
- TestResult<Set<_ReachabilityAssertion>> testResult = await checkTests(
- code,
- const _ReachabilityDataComputer(),
- FeatureSet.forTesting(
- sdkVersion: '2.2.2', additionalFeatures: [Feature.non_nullable]));
+ TestResult<Set<_ReachabilityAssertion>> testResult = await checkTests(code,
+ const _ReachabilityDataComputer(), FeatureSet.latestLanguageVersion());
if (testResult.hasFailures) {
fail('Failure(s)');
}
diff --git a/pkg/analyzer/test/src/dart/analysis/base.dart b/pkg/analyzer/test/src/dart/analysis/base.dart
index 1bb79b1..536922f 100644
--- a/pkg/analyzer/test/src/dart/analysis/base.dart
+++ b/pkg/analyzer/test/src/dart/analysis/base.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/src/context/packages.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/status.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
@@ -40,8 +39,6 @@
late final String testFile;
late final String testCode;
- List<String> enabledExperiments = [];
-
void addTestFile(String content, {bool priority = false}) {
testCode = content;
newFile(testFile, content: content);
@@ -98,10 +95,7 @@
AnalysisOptionsImpl createAnalysisOptions() => AnalysisOptionsImpl()
..useFastaParser = true
- ..contextFeatures = FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: ExperimentStatus.testingSdkLanguageVersion,
- flags: enabledExperiments,
- );
+ ..contextFeatures = FeatureSet.latestLanguageVersion();
int findOffset(String search) {
int offset = testCode.indexOf(search);
diff --git a/pkg/analyzer/test/src/dart/analysis/experiments_test.dart b/pkg/analyzer/test/src/dart/analysis/experiments_test.dart
index 573bc1b..f808c64 100644
--- a/pkg/analyzer/test/src/dart/analysis/experiments_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/experiments_test.dart
@@ -18,10 +18,10 @@
class ExperimentsTest {
var knownFeatures = <String, ExperimentalFeature>{};
- void assertLatestSdkLanguageVersion(ExperimentStatus status) {
+ void assertCurrentSdkLanguageVersion(ExperimentStatus status) {
expect(
getSdkLanguageVersion(status),
- ExperimentStatus.latestSdkLanguageVersion,
+ ExperimentStatus.currentVersion,
);
}
@@ -126,10 +126,10 @@
releaseVersion: null,
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['no-a', 'a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [true]);
}
@@ -145,10 +145,10 @@
releaseVersion: null,
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['a', 'no-a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false]);
}
@@ -163,10 +163,10 @@
releaseVersion: null,
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['no-a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false]);
}
@@ -181,10 +181,10 @@
releaseVersion: Version.parse('1.0.0'),
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['no-a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false]);
}
@@ -208,10 +208,10 @@
releaseVersion: Version.parse('1.0.0'),
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: [],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false, true]);
}
@@ -226,10 +226,10 @@
releaseVersion: null,
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [true]);
}
@@ -244,10 +244,10 @@
releaseVersion: Version.parse('1.0.0'),
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [true]);
}
@@ -263,10 +263,10 @@
releaseVersion: Version.parse('1.0.0'),
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['no-a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [true]);
}
@@ -282,10 +282,10 @@
releaseVersion: null,
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false]);
}
@@ -301,10 +301,10 @@
releaseVersion: null,
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['no-a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false]);
}
@@ -320,20 +320,20 @@
releaseVersion: Version.parse('1.0.0'),
);
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [true]);
}
test_fromStrings2_flags_unrecognized() {
// Unrecognized flags are ignored.
var status = fromStrings2(
- sdkLanguageVersion: ExperimentStatus.latestSdkLanguageVersion,
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
flags: ['a'],
);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), <Object>[]);
}
@@ -485,7 +485,7 @@
releaseVersion: null,
);
var status = fromStrings(['no-a', 'a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [true]);
}
@@ -501,7 +501,7 @@
releaseVersion: null,
);
var status = fromStrings(['a', 'no-a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false]);
}
@@ -525,7 +525,7 @@
releaseVersion: Version.parse('1.0.0'),
);
var status = fromStrings([]);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false, true]);
}
@@ -540,7 +540,7 @@
releaseVersion: null,
);
var status = fromStrings(['no-a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false]);
}
@@ -555,7 +555,7 @@
releaseVersion: Version.parse('1.0.0'),
);
var status = fromStrings(['no-a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false]);
}
@@ -570,7 +570,7 @@
releaseVersion: null,
);
var status = fromStrings(['a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [true]);
}
@@ -585,7 +585,7 @@
releaseVersion: Version.parse('1.0.0'),
);
var status = fromStrings(['a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [true]);
}
@@ -601,7 +601,7 @@
releaseVersion: Version.parse('1.0.0'),
);
var status = fromStrings(['no-a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [true]);
}
@@ -617,7 +617,7 @@
releaseVersion: null,
);
var status = fromStrings(['a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false]);
}
@@ -633,7 +633,7 @@
releaseVersion: null,
);
var status = fromStrings(['no-a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [false]);
}
@@ -649,14 +649,14 @@
releaseVersion: Version.parse('1.0.0'),
);
var status = fromStrings(['a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), [true]);
}
test_fromStrings_unrecognized_flag() {
// Unrecognized flags are ignored.
var status = fromStrings(['a']);
- assertLatestSdkLanguageVersion(status);
+ assertCurrentSdkLanguageVersion(status);
expect(getFlags(status), <Object>[]);
}
diff --git a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
index 5d2201c..7bd38c2 100644
--- a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
@@ -2,9 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/src/dart/analysis/unlinked_api_signature.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -13,7 +11,6 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(UnitApiSignatureTest);
- defineReflectiveTests(UnitApiSignatureWithNullSafetyTest);
});
}
@@ -344,6 +341,30 @@
''');
}
+ test_class_field_late_add() {
+ assertNotSameSignature(r'''
+class C {
+ int a;
+}
+''', r'''
+class C {
+ late int a;
+}
+''');
+ }
+
+ test_class_field_late_remove() {
+ assertNotSameSignature(r'''
+class C {
+ late int a;
+}
+''', r'''
+class C {
+ int a;
+}
+''');
+ }
+
test_class_field_static_add() {
assertNotSameSignature(r'''
class C {
@@ -1224,6 +1245,22 @@
''');
}
+ test_topLevelVariable_late_add() {
+ assertNotSameSignature(r'''
+int a;
+''', r'''
+late int a;
+''');
+ }
+
+ test_topLevelVariable_late_remove() {
+ assertNotSameSignature(r'''
+late int a;
+''', r'''
+int a;
+''');
+ }
+
test_topLevelVariable_withoutType() {
assertNotSameSignature(r'''
var a = 1;
@@ -1288,51 +1325,3 @@
''');
}
}
-
-@reflectiveTest
-class UnitApiSignatureWithNullSafetyTest extends UnitApiSignatureTest {
- @override
- AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
- ..contextFeatures = FeatureSet.forTesting(
- sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
-
- test_class_field_late_add() {
- assertNotSameSignature(r'''
-class C {
- int a;
-}
-''', r'''
-class C {
- late int a;
-}
-''');
- }
-
- test_class_field_late_remove() {
- assertNotSameSignature(r'''
-class C {
- late int a;
-}
-''', r'''
-class C {
- int a;
-}
-''');
- }
-
- test_topLevelVariable_late_add() {
- assertNotSameSignature(r'''
-int a;
-''', r'''
-late int a;
-''');
- }
-
- test_topLevelVariable_late_remove() {
- assertNotSameSignature(r'''
-late int a;
-''', r'''
-int a;
-''');
- }
-}
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 1db519f..ba67935 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -920,6 +920,35 @@
expect(result.toDoubleValue(), 3.0);
}
+ test_visitIsExpression_is_functionType_badTypes() async {
+ await resolveTestCode('''
+void foo(int a) {}
+const c = foo is void Function(String);
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(result.type, typeProvider.boolType);
+ expect(result.toBoolValue(), false);
+ }
+
+ test_visitIsExpression_is_functionType_correctTypes() async {
+ await resolveTestCode('''
+void foo(int a) {}
+const c = foo is void Function(int);
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(result.type, typeProvider.boolType);
+ expect(result.toBoolValue(), true);
+ }
+
+ test_visitIsExpression_is_functionType_nonFunction() async {
+ await resolveTestCode('''
+const c = false is void Function();
+''');
+ DartObjectImpl result = _evaluateConstant('c');
+ expect(result.type, typeProvider.boolType);
+ expect(result.toBoolValue(), false);
+ }
+
test_visitIsExpression_is_instanceOfSameClass() async {
await resolveTestCode('''
const a = const A();
diff --git a/pkg/analyzer/test/src/dart/constant/has_type_parameter_reference_test.dart b/pkg/analyzer/test/src/dart/constant/has_type_parameter_reference_test.dart
index bc0be60..8d2e5cd 100644
--- a/pkg/analyzer/test/src/dart/constant/has_type_parameter_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/has_type_parameter_reference_test.dart
@@ -16,7 +16,7 @@
}
@reflectiveTest
-class HasTypeParameterReferenceTest extends AbstractTypeSystemNullSafetyTest {
+class HasTypeParameterReferenceTest extends AbstractTypeSystemTest {
test_dynamic() {
_checkFalse(dynamicNone);
}
diff --git a/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart b/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart
index 2dd1c49..cf35b13 100644
--- a/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart
+++ b/pkg/analyzer/test/src/dart/element/class_hierarchy_test.dart
@@ -21,7 +21,7 @@
}
@reflectiveTest
-class ClassHierarchyLegacyTest extends AbstractTypeSystemTest
+class ClassHierarchyLegacyTest extends AbstractTypeSystemWithoutNullSafetyTest
with _AbstractClassHierarchyMixin {
@override
void setUp() {
@@ -46,7 +46,7 @@
}
@reflectiveTest
-class ClassHierarchyNullSafetyTest extends AbstractTypeSystemNullSafetyTest
+class ClassHierarchyNullSafetyTest extends AbstractTypeSystemTest
with _AbstractClassHierarchyMixin {
@override
void setUp() {
diff --git a/pkg/analyzer/test/src/dart/element/factor_type_test.dart b/pkg/analyzer/test/src/dart/element/factor_type_test.dart
index 240c5bf..fee6ba8 100644
--- a/pkg/analyzer/test/src/dart/element/factor_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/factor_type_test.dart
@@ -27,12 +27,6 @@
late final TypeSystemImpl typeSystem;
- FeatureSet get testFeatureSet {
- return FeatureSet.forTesting(
- additionalFeatures: [Feature.non_nullable],
- );
- }
-
@override
DartType get voidType => typeProvider.voidType;
@@ -49,7 +43,7 @@
void setUp() {
var analysisContext = TestAnalysisContext(
- featureSet: testFeatureSet,
+ featureSet: FeatureSet.latestLanguageVersion(),
);
typeProvider = analysisContext.typeProviderNonNullableByDefault;
typeSystem = analysisContext.typeSystemNonNullableByDefault;
diff --git a/pkg/analyzer/test/src/dart/element/flatten_type_test.dart b/pkg/analyzer/test/src/dart/element/flatten_type_test.dart
index de300b9..fa4fbd57 100644
--- a/pkg/analyzer/test/src/dart/element/flatten_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/flatten_type_test.dart
@@ -16,7 +16,7 @@
}
@reflectiveTest
-class FlattenTypeTest extends AbstractTypeSystemNullSafetyTest {
+class FlattenTypeTest extends AbstractTypeSystemTest {
test_dynamic() {
_check(dynamicNone, 'dynamic');
}
diff --git a/pkg/analyzer/test/src/dart/element/future_or_base_test.dart b/pkg/analyzer/test/src/dart/element/future_or_base_test.dart
index c70b702..a777618 100644
--- a/pkg/analyzer/test/src/dart/element/future_or_base_test.dart
+++ b/pkg/analyzer/test/src/dart/element/future_or_base_test.dart
@@ -15,7 +15,7 @@
}
@reflectiveTest
-class FutureOrBaseTest extends AbstractTypeSystemNullSafetyTest {
+class FutureOrBaseTest extends AbstractTypeSystemTest {
test_dynamic() {
_check(dynamicNone, 'dynamic');
}
diff --git a/pkg/analyzer/test/src/dart/element/future_value_type_test.dart b/pkg/analyzer/test/src/dart/element/future_value_type_test.dart
index 6c789e7..fc9fe60 100644
--- a/pkg/analyzer/test/src/dart/element/future_value_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/future_value_type_test.dart
@@ -15,7 +15,7 @@
}
@reflectiveTest
-class FutureValueTypeTest extends AbstractTypeSystemNullSafetyTest {
+class FutureValueTypeTest extends AbstractTypeSystemTest {
/// futureValueType(`dynamic`) = `dynamic`.
test_dynamic() {
_check(dynamicNone, 'dynamic');
diff --git a/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart b/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
index 7933c6f..853eb50 100644
--- a/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
+++ b/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
@@ -24,7 +24,7 @@
}
@reflectiveTest
-class GenericFunctionInferenceTest extends AbstractTypeSystemNullSafetyTest {
+class GenericFunctionInferenceTest extends AbstractTypeSystemTest {
void test_boundedByAnotherTypeParameter() {
// <TFrom, TTo extends Iterable<TFrom>>(TFrom) -> TTo
var tFrom = typeParameter('TFrom');
diff --git a/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart b/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart
index 8c1a570..9c1f2df 100644
--- a/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart
+++ b/pkg/analyzer/test/src/dart/element/least_greatest_closure_test.dart
@@ -17,7 +17,8 @@
}
@reflectiveTest
-class GreatestClosureLegacyTest extends AbstractTypeSystemTest {
+class GreatestClosureLegacyTest
+ extends AbstractTypeSystemWithoutNullSafetyTest {
late final TypeParameterElement T;
late final TypeParameterType T_none;
late final TypeParameterType T_question;
@@ -141,7 +142,7 @@
}
@reflectiveTest
-class GreatestClosureNullSafetyTest extends AbstractTypeSystemNullSafetyTest {
+class GreatestClosureNullSafetyTest extends AbstractTypeSystemTest {
late final TypeParameterElement T;
late final TypeParameterType T_none;
late final TypeParameterType T_question;
diff --git a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
index c5e85ce..83fc399 100644
--- a/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
+++ b/pkg/analyzer/test/src/dart/element/least_upper_bound_helper_test.dart
@@ -21,7 +21,7 @@
}
@reflectiveTest
-class PathToObjectTest extends AbstractTypeSystemTest {
+class PathToObjectTest extends AbstractTypeSystemWithoutNullSafetyTest {
@override
final TestTypeProvider typeProvider = TestTypeProvider();
@@ -351,7 +351,7 @@
}
@reflectiveTest
-class SuperinterfaceSetTest extends AbstractTypeSystemTest {
+class SuperinterfaceSetTest extends AbstractTypeSystemWithoutNullSafetyTest {
@override
final TestTypeProvider typeProvider = TestTypeProvider();
diff --git a/pkg/analyzer/test/src/dart/element/normalize_type_test.dart b/pkg/analyzer/test/src/dart/element/normalize_type_test.dart
index f99b5a0..bb73cc4c 100644
--- a/pkg/analyzer/test/src/dart/element/normalize_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/normalize_type_test.dart
@@ -2,19 +2,15 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/dart/element/type_visitor.dart';
import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../../../generated/elements_types_mixin.dart';
-import '../../../generated/test_analysis_context.dart';
+import '../../../generated/type_system_test.dart';
main() {
defineReflectiveSuite(() {
@@ -23,26 +19,7 @@
}
@reflectiveTest
-class NormalizeTypeTest with ElementsTypesMixin {
- @override
- late final TypeProvider typeProvider;
-
- late final TypeSystemImpl typeSystem;
-
- FeatureSet get testFeatureSet {
- return FeatureSet.forTesting(
- additionalFeatures: [Feature.non_nullable],
- );
- }
-
- void setUp() {
- var analysisContext = TestAnalysisContext(
- featureSet: testFeatureSet,
- );
- typeProvider = analysisContext.typeProviderNonNullableByDefault;
- typeSystem = analysisContext.typeSystemNonNullableByDefault;
- }
-
+class NormalizeTypeTest extends AbstractTypeSystemTest {
test_functionType_parameter() {
_check(
functionTypeNone(
diff --git a/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
index ff5c8f9..4471b73 100644
--- a/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
+++ b/pkg/analyzer/test/src/dart/element/nullability_eliminator_test.dart
@@ -18,7 +18,7 @@
}
@reflectiveTest
-class NullabilityEliminatorTest extends AbstractTypeSystemNullSafetyTest {
+class NullabilityEliminatorTest extends AbstractTypeSystemTest {
test_dynamicType() {
_verifySame(typeProvider.dynamicType);
}
diff --git a/pkg/analyzer/test/src/dart/element/nullable_test.dart b/pkg/analyzer/test/src/dart/element/nullable_test.dart
index 1bfb595..92f4950 100644
--- a/pkg/analyzer/test/src/dart/element/nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/element/nullable_test.dart
@@ -23,7 +23,7 @@
}
@reflectiveTest
-class IsNonNullableTest extends AbstractTypeSystemNullSafetyTest {
+class IsNonNullableTest extends AbstractTypeSystemTest {
void isNonNullable(DartType type) {
expect(typeSystem.isNonNullable(type), isTrue);
}
@@ -188,7 +188,7 @@
}
@reflectiveTest
-class IsNullableTest extends AbstractTypeSystemNullSafetyTest {
+class IsNullableTest extends AbstractTypeSystemTest {
void isNotNullable(DartType type) {
expect(typeSystem.isNullable(type), isFalse);
}
@@ -353,7 +353,7 @@
}
@reflectiveTest
-class IsPotentiallyNonNullableTest extends AbstractTypeSystemNullSafetyTest {
+class IsPotentiallyNonNullableTest extends AbstractTypeSystemTest {
void isNotPotentiallyNonNullable(DartType type) {
expect(typeSystem.isPotentiallyNonNullable(type), isFalse);
}
@@ -400,7 +400,7 @@
}
@reflectiveTest
-class IsPotentiallyNullableTest extends AbstractTypeSystemNullSafetyTest {
+class IsPotentiallyNullableTest extends AbstractTypeSystemTest {
void isNotPotentiallyNullable(DartType type) {
expect(typeSystem.isPotentiallyNullable(type), isFalse);
}
@@ -447,7 +447,7 @@
}
@reflectiveTest
-class IsStrictlyNonNullableTest extends AbstractTypeSystemNullSafetyTest {
+class IsStrictlyNonNullableTest extends AbstractTypeSystemTest {
void isNotStrictlyNonNullable(DartType type) {
expect(typeSystem.isStrictlyNonNullable(type), isFalse);
}
@@ -594,7 +594,7 @@
}
@reflectiveTest
-class PromoteToNonNullTest extends AbstractTypeSystemNullSafetyTest {
+class PromoteToNonNullTest extends AbstractTypeSystemTest {
test_dynamic() {
_check(dynamicType, dynamicType);
}
diff --git a/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart b/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
index 54a3fd6..ffdc9cc 100644
--- a/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
+++ b/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
@@ -18,7 +18,8 @@
}
@reflectiveTest
-class ReplaceTopBottomLegacyTest extends AbstractTypeSystemTest {
+class ReplaceTopBottomLegacyTest
+ extends AbstractTypeSystemWithoutNullSafetyTest {
test_contravariant_bottom() {
// Not contravariant.
_check(nullStar, 'Null*');
@@ -77,7 +78,7 @@
}
@reflectiveTest
-class ReplaceTopBottomNullSafetyTest extends AbstractTypeSystemNullSafetyTest {
+class ReplaceTopBottomNullSafetyTest extends AbstractTypeSystemTest {
test_contravariant_bottom() {
// Not contravariant.
_check(neverNone, 'Never');
diff --git a/pkg/analyzer/test/src/dart/element/runtime_type_equality_test.dart b/pkg/analyzer/test/src/dart/element/runtime_type_equality_test.dart
index f7aee23..be647f5 100644
--- a/pkg/analyzer/test/src/dart/element/runtime_type_equality_test.dart
+++ b/pkg/analyzer/test/src/dart/element/runtime_type_equality_test.dart
@@ -2,16 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../../../generated/elements_types_mixin.dart';
-import '../../../generated/test_analysis_context.dart';
+import '../../../generated/type_system_test.dart';
main() {
defineReflectiveSuite(() {
@@ -20,26 +16,7 @@
}
@reflectiveTest
-class RuntimeTypeEqualityTypeTest with ElementsTypesMixin {
- @override
- late final TypeProvider typeProvider;
-
- late final TypeSystemImpl typeSystem;
-
- FeatureSet get testFeatureSet {
- return FeatureSet.forTesting(
- additionalFeatures: [Feature.non_nullable],
- );
- }
-
- void setUp() {
- var analysisContext = TestAnalysisContext(
- featureSet: testFeatureSet,
- );
- typeProvider = analysisContext.typeProviderNonNullableByDefault;
- typeSystem = analysisContext.typeSystemNonNullableByDefault;
- }
-
+class RuntimeTypeEqualityTypeTest extends AbstractTypeSystemTest {
test_dynamic() {
_equal(dynamicNone, dynamicNone);
_notEqual(dynamicNone, voidNone);
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index 4063e9f..89411e9 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -23,13 +22,6 @@
@reflectiveTest
class NonNullableSubtypingCompoundTest extends _SubtypingCompoundTestBase {
- @override
- FeatureSet get testFeatureSet {
- return FeatureSet.forTesting(
- additionalFeatures: [Feature.non_nullable],
- );
- }
-
test_dynamic() {
var equivalents = <DartType>[
voidNone,
@@ -5990,7 +5982,7 @@
}
}
-class _SubtypingTestBase extends AbstractTypeSystemNullSafetyTest {}
+class _SubtypingTestBase extends AbstractTypeSystemTest {}
class _TypeParameterCollector extends TypeVisitor<void> {
final Set<String> typeParameters = {};
diff --git a/pkg/analyzer/test/src/dart/element/top_merge_test.dart b/pkg/analyzer/test/src/dart/element/top_merge_test.dart
index 44ec079..f726cc9 100644
--- a/pkg/analyzer/test/src/dart/element/top_merge_test.dart
+++ b/pkg/analyzer/test/src/dart/element/top_merge_test.dart
@@ -2,15 +2,11 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../../../generated/elements_types_mixin.dart';
-import '../../../generated/test_analysis_context.dart';
+import '../../../generated/type_system_test.dart';
main() {
defineReflectiveSuite(() {
@@ -19,7 +15,7 @@
}
@reflectiveTest
-class TopMergeTest extends _Base {
+class TopMergeTest extends AbstractTypeSystemTest {
test_differentStructure() {
_checkThrows(
intNone,
@@ -341,22 +337,3 @@
}, throwsA(anything));
}
}
-
-abstract class _Base with ElementsTypesMixin {
- @override
- late final TypeProvider typeProvider;
-
- late final TypeSystemImpl typeSystem;
-
- FeatureSet get testFeatureSet {
- return FeatureSet.forTesting();
- }
-
- void setUp() {
- var analysisContext = TestAnalysisContext(
- featureSet: testFeatureSet,
- );
- typeProvider = analysisContext.typeProviderLegacy;
- typeSystem = analysisContext.typeSystemLegacy;
- }
-}
diff --git a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
index a096499..0469fb8 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -480,7 +480,7 @@
}
}
-class _Base extends AbstractTypeSystemNullSafetyTest {
+class _Base extends AbstractTypeSystemTest {
void assertType(DartType type, String expected) {
var typeStr = _typeStr(type);
expect(typeStr, expected);
diff --git a/pkg/analyzer/test/src/dart/element/type_bounded_test.dart b/pkg/analyzer/test/src/dart/element/type_bounded_test.dart
index e851ca6..bf625dc 100644
--- a/pkg/analyzer/test/src/dart/element/type_bounded_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_bounded_test.dart
@@ -16,7 +16,7 @@
}
@reflectiveTest
-class DynamicBoundedTest extends AbstractTypeSystemNullSafetyTest {
+class DynamicBoundedTest extends AbstractTypeSystemTest {
test_dynamic() {
_assertDynamicBounded(dynamicNone);
}
@@ -97,7 +97,7 @@
}
@reflectiveTest
-class FunctionBoundedTest extends AbstractTypeSystemNullSafetyTest {
+class FunctionBoundedTest extends AbstractTypeSystemTest {
test_dynamic() {
_assertNotFunctionBounded(dynamicNone);
}
diff --git a/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart b/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
index bed7bd4..8695591 100644
--- a/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
@@ -18,7 +18,7 @@
}
@reflectiveTest
-class TypeConstraintGathererTest extends AbstractTypeSystemNullSafetyTest {
+class TypeConstraintGathererTest extends AbstractTypeSystemTest {
late final TypeParameterElement T;
late final TypeParameterType T_none;
late final TypeParameterType T_question;
diff --git a/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart b/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart
index 69ceb64..bf8d4c0 100644
--- a/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_parameter_element_test.dart
@@ -16,7 +16,7 @@
}
@reflectiveTest
-class TypeParameterElementTest extends AbstractTypeSystemNullSafetyTest {
+class TypeParameterElementTest extends AbstractTypeSystemTest {
test_equal_elementElement_sameLocation() {
var T1 = typeParameter('T');
var T2 = typeParameter('T');
@@ -45,7 +45,7 @@
}
@reflectiveTest
-class TypeParameterTypeTest extends AbstractTypeSystemNullSafetyTest {
+class TypeParameterTypeTest extends AbstractTypeSystemTest {
test_equal_equalElements() {
var T1 = typeParameter('T');
var T2 = typeParameter('T');
diff --git a/pkg/analyzer/test/src/dart/element/type_references_any_test.dart b/pkg/analyzer/test/src/dart/element/type_references_any_test.dart
index 6a45016..69ba48f 100644
--- a/pkg/analyzer/test/src/dart/element/type_references_any_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_references_any_test.dart
@@ -17,7 +17,7 @@
}
@reflectiveTest
-class TypeReferencesAnyTest extends AbstractTypeSystemNullSafetyTest {
+class TypeReferencesAnyTest extends AbstractTypeSystemTest {
late TypeParameterElement T;
late TypeParameterType T_none;
diff --git a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
index c68511d..5f956f5 100644
--- a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
+++ b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -32,13 +31,6 @@
static final Map<String, StackTrace> _isMoreBottomChecked = {};
static final Map<String, StackTrace> _isMoreTopChecked = {};
- @override
- FeatureSet get testFeatureSet {
- return FeatureSet.forTesting(
- additionalFeatures: [Feature.non_nullable],
- );
- }
-
void isBottom(DartType type) {
expect(typeSystem.isBottom(type), isTrue, reason: _typeString(type));
}
@@ -3347,7 +3339,7 @@
}
@reflectiveTest
-class _BoundsTestBase extends AbstractTypeSystemNullSafetyTest {
+class _BoundsTestBase extends AbstractTypeSystemTest {
void _assertBottom(DartType type) {
if (!typeSystem.isBottom(type)) {
fail('isBottom must be true: ' + _typeString(type));
diff --git a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
index 690050e..c2fe3b1 100644
--- a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
+++ b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
@@ -2,10 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/resolver/exit_detector.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/test_utilities/find_node.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -145,11 +143,6 @@
/// See [ExitDetectorResolvedStatementTest] for tests that require the AST to be resolved.
@reflectiveTest
class ExitDetectorParsedStatementTest extends ParseBase {
- @override
- AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
- ..contextFeatures = FeatureSet.forTesting(
- sdkVersion: '2.13', additionalFeatures: [Feature.constructor_tearoffs]);
-
test_asExpression() async {
_assertFalse('a as Object;');
}
diff --git a/pkg/analyzer/test/src/diagnostics/const_with_type_parameters_test.dart b/pkg/analyzer/test/src/diagnostics/const_with_type_parameters_test.dart
index ebd3043..6df3560 100644
--- a/pkg/analyzer/test/src/diagnostics/const_with_type_parameters_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_with_type_parameters_test.dart
@@ -17,6 +17,21 @@
@reflectiveTest
class ConstWithTypeParametersConstructorTearoffTest
extends PubPackageResolutionTest {
+ test_asExpression_functionType() async {
+ await assertErrorsInCode('''
+void f<T>(T a) {}
+void g() {
+ const [f as void Function<T>(T, [int])];
+}
+''', [
+ // This error is reported because the cast fails if the type on the right
+ // has type parameters.
+ // TODO(srawlins): Deduplicate these two errors.
+ error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 38, 31),
+ error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS, 60, 1),
+ ]);
+ }
+
test_direct() async {
await assertErrorsInCode('''
class A<T> {
@@ -45,6 +60,18 @@
]);
}
+ test_isExpression_functionType() async {
+ await assertErrorsInCode('''
+class A<T> {
+ void m() {
+ const [false is void Function(T)];
+ }
+}
+''', [
+ error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS, 60, 1),
+ ]);
+ }
+
test_nonConst() async {
await assertNoErrorsInCode('''
class A<T> {
diff --git a/pkg/analyzer/test/src/diagnostics/unused_result_test.dart b/pkg/analyzer/test/src/diagnostics/unused_result_test.dart
index 5d1c5a6..250479b 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_result_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_result_test.dart
@@ -765,6 +765,19 @@
''');
}
+ test_topLevelVariable_result_unusedInDoc() async {
+ // https://github.com/dart-lang/sdk/issues/47181
+ await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+
+@useResult
+int get f => 1;
+
+/// I love [f].
+int g = 1;
+''');
+ }
+
test_topLevelVariable_returned() async {
await assertNoErrorsInCode(r'''
import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart
index 9b95376..887e3d9 100644
--- a/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/extra_code_test.dart
@@ -4,6 +4,7 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -308,9 +309,9 @@
''', [ParserErrorCode.MULTIPLE_VARIANCE_MODIFIERS], '''
class A<in X> {}
''',
- featureSet: FeatureSet.forTesting(
- sdkVersion: '2.5.0',
- additionalFeatures: [Feature.variance],
+ featureSet: FeatureSet.fromEnableFlags2(
+ sdkLanguageVersion: ExperimentStatus.currentVersion,
+ flags: [EnableString.variance],
));
}
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart b/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
index c743709..1cd18d7 100644
--- a/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/paired_tokens_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -250,9 +249,7 @@
f(x) => l?[x
''', [ScannerErrorCode.EXPECTED_TOKEN, ParserErrorCode.EXPECTED_TOKEN], '''
f(x) => l?[x];
-''',
- featureSet: FeatureSet.forTesting(
- sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]));
+''');
}
void test_listLiteral_inner_last() {
diff --git a/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart b/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
index 9fd3a24..f6afa71 100644
--- a/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
@@ -2,8 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/summary2/ast_text_printer.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -13,7 +11,6 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AstTextPrinterTest);
- defineReflectiveTests(AstTextPrinterWithNullSafetyTest);
});
}
@@ -79,6 +76,12 @@
''');
}
+ test_genericFunctionType_question() async {
+ assertParseCodeAndPrintAst(this, '''
+void Function()? a;
+''');
+ }
+
test_ifElement_then() async {
assertParseCodeAndPrintAst(this, r'''
var _ = [1, if (true) 2, 3];
@@ -121,20 +124,6 @@
var _ = [1, ...?[2, 3], 4];
''');
}
-}
-
-@reflectiveTest
-class AstTextPrinterWithNullSafetyTest extends ParseBase {
- @override
- AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
- ..contextFeatures = FeatureSet.forTesting(
- sdkVersion: '2.10.0', additionalFeatures: [Feature.non_nullable]);
-
- test_genericFunctionType_question() async {
- assertParseCodeAndPrintAst(this, '''
-void Function()? a;
-''');
- }
test_typeName_question() async {
assertParseCodeAndPrintAst(this, '''
diff --git a/pkg/analyzer/test/util/id_testing_helper.dart b/pkg/analyzer/test/util/id_testing_helper.dart
index f192694..b1317f0c 100644
--- a/pkg/analyzer/test/util/id_testing_helper.dart
+++ b/pkg/analyzer/test/util/id_testing_helper.dart
@@ -29,15 +29,12 @@
/// Test configuration used for testing the analyzer with constant evaluation.
final TestConfig analyzerConstantUpdate2018Config = TestConfig(
analyzerMarker, 'analyzer with constant-update-2018',
- featureSet: FeatureSet.forTesting(
- sdkVersion: '2.2.2',
- additionalFeatures: [Feature.constant_update_2018]));
+ featureSet: FeatureSet.latestLanguageVersion());
/// Test configuration used for testing the analyzer with NNBD.
final TestConfig analyzerNnbdConfig = TestConfig(
analyzerMarker, 'analyzer with NNBD',
- featureSet: FeatureSet.forTesting(
- sdkVersion: '2.2.2', additionalFeatures: [Feature.non_nullable]));
+ featureSet: FeatureSet.latestLanguageVersion());
/// A fake absolute directory used as the root of a memory-file system in ID
/// tests.
diff --git a/pkg/compiler/lib/src/universe/world_impact.dart b/pkg/compiler/lib/src/universe/world_impact.dart
index 1413ae0..87457bc 100644
--- a/pkg/compiler/lib/src/universe/world_impact.dart
+++ b/pkg/compiler/lib/src/universe/world_impact.dart
@@ -247,13 +247,13 @@
@override
void registerDynamicUse(DynamicUse dynamicUse) {
- _dynamicUses ??= Setlet.from(worldImpact.dynamicUses);
+ _dynamicUses ??= Setlet.of(worldImpact.dynamicUses);
_dynamicUses.add(dynamicUse);
}
@override
void registerTypeUse(TypeUse typeUse) {
- _typeUses ??= Setlet.from(worldImpact.typeUses);
+ _typeUses ??= Setlet.of(worldImpact.typeUses);
_typeUses.add(typeUse);
}
@@ -264,7 +264,7 @@
@override
void registerStaticUse(StaticUse staticUse) {
- _staticUses ??= Setlet.from(worldImpact.staticUses);
+ _staticUses ??= Setlet.of(worldImpact.staticUses);
_staticUses.add(staticUse);
}
@@ -280,7 +280,7 @@
@override
void registerConstantUse(ConstantUse constantUse) {
- _constantUses ??= Setlet.from(worldImpact.constantUses);
+ _constantUses ??= Setlet.of(worldImpact.constantUses);
_constantUses.add(constantUse);
}
diff --git a/pkg/compiler/lib/src/util/maplet.dart b/pkg/compiler/lib/src/util/maplet.dart
index 05d7c4c..1afe289 100644
--- a/pkg/compiler/lib/src/util/maplet.dart
+++ b/pkg/compiler/lib/src/util/maplet.dart
@@ -30,7 +30,7 @@
Maplet();
- Maplet.from(Maplet<K, V> other) {
+ Maplet.of(Maplet<K, V> other) {
other.forEach((K key, V value) {
this[key] = value;
});
diff --git a/pkg/compiler/lib/src/util/setlet.dart b/pkg/compiler/lib/src/util/setlet.dart
index c7aef0d..f44b330 100644
--- a/pkg/compiler/lib/src/util/setlet.dart
+++ b/pkg/compiler/lib/src/util/setlet.dart
@@ -26,7 +26,7 @@
Setlet();
- Setlet.from(Iterable<E> elements) {
+ Setlet.of(Iterable<E> elements) {
addAll(elements);
}
@@ -209,8 +209,10 @@
@override
void removeWhere(bool test(E element)) {
if (_extra == null) {
- if (test(_contents)) {
- _contents = _MARKER;
+ if (_MARKER != _contents) {
+ if (test(_contents)) {
+ _contents = _MARKER;
+ }
}
} else if (_MARKER == _extra) {
_contents.removeWhere(test);
@@ -273,11 +275,11 @@
@override
Setlet<E> intersection(Set<Object?> other) =>
- Setlet<E>.from(this.where((e) => other.contains(e)));
+ Setlet.of(this.where((e) => other.contains(e)));
@override
Setlet<E> difference(Set<Object?> other) =>
- Setlet<E>.from(this.where((e) => !other.contains(e)));
+ Setlet.of(this.where((e) => !other.contains(e)));
@override
Setlet<E> toSet() {
diff --git a/pkg/compiler/test/model/maplet_test.dart b/pkg/compiler/test/model/maplet_test.dart
index 1a6e66e..fe9a25f 100644
--- a/pkg/compiler/test/model/maplet_test.dart
+++ b/pkg/compiler/test/model/maplet_test.dart
@@ -2,19 +2,19 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart = 2.7
+// @dart = 2.12
import "package:expect/expect.dart";
import "package:compiler/src/util/maplet.dart";
-main() {
+void main() {
for (int i = 1; i <= 32; i++) {
test(i);
}
}
-test(int size) {
- var maplet = new Maplet();
+void test(int size) {
+ final maplet = Maplet<int?, String>();
for (int i = 0; i < size; i++) {
Expect.isTrue(maplet.isEmpty == (i == 0));
maplet[i] = '$i';
diff --git a/pkg/compiler/test/model/setlet_test.dart b/pkg/compiler/test/model/setlet_test.dart
index a58f6ce..2b212ba 100644
--- a/pkg/compiler/test/model/setlet_test.dart
+++ b/pkg/compiler/test/model/setlet_test.dart
@@ -2,13 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-// @dart = 2.7
+// @dart = 2.12
import "package:expect/expect.dart";
import 'dart:collection';
import 'package:compiler/src/util/setlet.dart';
-main() {
+void main() {
for (int i = 1; i <= 32; i++) {
test(i);
}
@@ -16,8 +16,8 @@
testAllLikeSet();
}
-test(int size) {
- var setlet = new Setlet();
+void test(int size) {
+ final setlet = Setlet<int?>();
for (int i = 0; i < size; i++) {
Expect.isTrue(setlet.isEmpty == (i == 0));
setlet.add(i);
@@ -73,10 +73,10 @@
}
}
-testAllLikeSet() {
+void testAllLikeSet() {
// For a variety of inputs and operations, test that Setlet behaves just like
// Set.
- var samples = [
+ final List<List<int>> samples = [
[],
[1],
[1, 2],
@@ -115,33 +115,36 @@
}
}
-testSetXElement(name, fn, a, b) {
- var set1 = new LinkedHashSet.from(a);
- var setlet1 = new Setlet.from(a);
+void testSetXElement<E, R>(
+ String name, R Function(Set<E>, E) fn, Iterable<E> a, E b) {
+ final set1 = LinkedHashSet.of(a);
+ final setlet1 = Setlet.of(a);
- var setResult = fn(set1, b);
- var setletResult = fn(setlet1, b);
+ final setResult = fn(set1, b);
+ final setletResult = fn(setlet1, b);
- var operationName = '$name $a $b';
+ final operationName = '$name $a $b';
checkResult(operationName, setResult, setletResult);
checkModifications(operationName, set1, setlet1);
}
-testSetXSet(name, fn, a, b) {
- var set1 = new LinkedHashSet.from(a);
- var set2 = new LinkedHashSet.from(b);
- var setlet1 = new Setlet.from(a);
- var setlet2 = new Setlet.from(b);
+void testSetXSet<E, R>(
+ String name, R Function(Set<E>, Set<E>) fn, Iterable<E> a, Iterable<E> b) {
+ final set1 = LinkedHashSet.of(a);
+ final set2 = LinkedHashSet.of(b);
+ final setlet1 = Setlet.of(a);
+ final setlet2 = Setlet.of(b);
- var setResult = fn(set1, set2);
- var setletResult = fn(setlet1, setlet2);
+ final setResult = fn(set1, set2);
+ final setletResult = fn(setlet1, setlet2);
- var operationName = '$name $a $b';
+ final operationName = '$name $a $b';
checkResult(operationName, setResult, setletResult);
checkModifications(operationName, set1, setlet1);
}
-checkResult(operationName, setResult, setletResult) {
+void checkResult(
+ String operationName, dynamic setResult, dynamic setletResult) {
if (setResult == null || setResult is bool || setResult is num) {
Expect.equals(setResult, setletResult, '$operationName');
} else if (setResult is Iterable) {
@@ -152,12 +155,15 @@
setResult.length, setletResult.length, '$operationName: same length');
Expect.listEquals(setResult.toList(), setletResult.toList(),
'$operationName: same toList() result');
+ Expect.listEquals([...setResult], [...setletResult],
+ '$operationName: same spread result');
} else {
Expect.isFalse(true, '$operationName: unexpected result type');
}
}
-checkModifications(operationName, setReceiver, setletReceiver) {
+void checkModifications<E>(
+ String operationName, Set<E> setReceiver, Set<E> setletReceiver) {
Expect.equals(setReceiver.length, setletReceiver.length,
'$operationName: same post-operation receiver length');
Expect.listEquals(setReceiver.toList(), setletReceiver.toList(),
diff --git a/pkg/front_end/test/incremental_suite.dart b/pkg/front_end/test/incremental_suite.dart
index 2f68e15f..6430602 100644
--- a/pkg/front_end/test/incremental_suite.dart
+++ b/pkg/front_end/test/incremental_suite.dart
@@ -26,7 +26,7 @@
show ExperimentalFlag, experimentEnabledVersion;
import "package:front_end/src/api_prototype/memory_file_system.dart"
- show MemoryFileSystem;
+ show MemoryFileSystem, MemoryFileSystemEntity;
import 'package:front_end/src/base/nnbd_mode.dart' show NnbdMode;
@@ -308,7 +308,7 @@
final Uri base = Uri.parse("org-dartlang-test:///");
final Uri sdkSummaryUri = base.resolve(sdkSummary);
- MemoryFileSystem fs = new MemoryFileSystem(base);
+ TestMemoryFileSystem fs = new TestMemoryFileSystem(base);
fs.entityForUri(sdkSummaryUri).writeAsBytesSync(sdkSummaryData);
// Setup all sources
@@ -508,7 +508,7 @@
}
if (brandNewWorld) {
- fs = new MemoryFileSystem(base);
+ fs = new TestMemoryFileSystem(base);
}
fs!.entityForUri(sdkSummaryUri).writeAsBytesSync(sdkSummaryData);
bool expectInitializeFromDill = false;
@@ -1991,3 +1991,19 @@
}
}
}
+
+class TestMemoryFileSystem extends MemoryFileSystem {
+ TestMemoryFileSystem(Uri currentDirectory) : super(currentDirectory);
+
+ @override
+ MemoryFileSystemEntity entityForUri(Uri uri) {
+ // Try to "sanitize" the uri as a real file system does, namely
+ // "a/b.dart" and "a//b.dart" returns the same file.
+ if (uri.pathSegments.contains("")) {
+ Uri newUri = uri.replace(
+ pathSegments: uri.pathSegments.where((element) => element != ""));
+ return super.entityForUri(newUri);
+ }
+ return super.entityForUri(uri);
+ }
+}
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 398070d..82edba1 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -825,6 +825,7 @@
runtimes
rv
sandboxed
+sanitize
saves
scans
scheduler
@@ -926,6 +927,7 @@
timer
timings
tinv
+tk
told
touch
tpt
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart
new file mode 100644
index 0000000..a45bc22
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+ final int Function(int) x;
+ const A(bool b)
+ : x = (b
+ ? id
+ : other)<int>; // OK, `(...)<T1..Tk>` is potentially constant.
+}
+
+X id<X>(X x) => x;
+X other<X>(X x) => throw '$x';
+
+void main() {
+ const c1 =
+ id<int>; // Already supported prior to the addition on this feature.
+ const c2 =
+ id; // Make `c2` a constant expression whose value is a function object.
+ const c3 = c2<int>; // OK, perform generic function instantiation on `c2`.
+ const c4 = A(
+ true); // OK, `(b ? id : other)<int>` is constant after substitution `b` -> `true`.
+ print('$c1, $c2, $c3, $c4');
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.strong.expect
new file mode 100644
index 0000000..a23b6b4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.strong.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/ {
+ final field (core::int) → core::int x;
+ const constructor •(core::bool b) → self::A
+ : self::A::x = (b ?{<X extends core::Object? = dynamic>(X%) → X%} #C1 : #C2)<core::int>, super core::Object::•()
+ ;
+}
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method other<X extends core::Object? = dynamic>(self::other::X% x) → self::other::X%
+ return throw "${x}";
+static method main() → void {
+ core::print("${#C3}, ${#C1}, ${#C3}, ${#C4}");
+}
+
+constants {
+ #C1 = static-tearoff self::id
+ #C2 = static-tearoff self::other
+ #C3 = instantiation self::id <core::int>
+ #C4 = self::A {x:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47154a.dart:
+- A. (from org-dartlang-testcase:///issue47154a.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.strong.transformed.expect
new file mode 100644
index 0000000..a23b6b4
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.strong.transformed.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/ {
+ final field (core::int) → core::int x;
+ const constructor •(core::bool b) → self::A
+ : self::A::x = (b ?{<X extends core::Object? = dynamic>(X%) → X%} #C1 : #C2)<core::int>, super core::Object::•()
+ ;
+}
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method other<X extends core::Object? = dynamic>(self::other::X% x) → self::other::X%
+ return throw "${x}";
+static method main() → void {
+ core::print("${#C3}, ${#C1}, ${#C3}, ${#C4}");
+}
+
+constants {
+ #C1 = static-tearoff self::id
+ #C2 = static-tearoff self::other
+ #C3 = instantiation self::id <core::int>
+ #C4 = self::A {x:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47154a.dart:
+- A. (from org-dartlang-testcase:///issue47154a.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.textual_outline.expect
new file mode 100644
index 0000000..17cdb52
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+class A {
+ final int Function(int) x;
+ const A(bool b) : x = (b ? id : other)<int>;
+}
+
+X id<X>(X x) => x;
+X other<X>(X x) => throw '$x';
+void main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6598e5a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+X id<X>(X x) => x;
+X other<X>(X x) => throw '$x';
+
+class A {
+ const A(bool b) : x = (b ? id : other)<int>;
+ final int Function(int) x;
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.weak.expect
new file mode 100644
index 0000000..55aaf0f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.weak.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/ {
+ final field (core::int) → core::int x;
+ const constructor •(core::bool b) → self::A
+ : self::A::x = (b ?{<X extends core::Object? = dynamic>(X%) → X%} #C1 : #C2)<core::int>, super core::Object::•()
+ ;
+}
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method other<X extends core::Object? = dynamic>(self::other::X% x) → self::other::X%
+ return throw "${x}";
+static method main() → void {
+ core::print("${#C3}, ${#C1}, ${#C3}, ${#C4}");
+}
+
+constants {
+ #C1 = static-tearoff self::id
+ #C2 = static-tearoff self::other
+ #C3 = instantiation self::id <core::int*>
+ #C4 = self::A {x:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47154a.dart:
+- A. (from org-dartlang-testcase:///issue47154a.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.weak.outline.expect
new file mode 100644
index 0000000..efc3521
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.weak.outline.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/ {
+ final field (core::int) → core::int x;
+ const constructor •(core::bool b) → self::A
+ : self::A::x = (b ?{<X extends core::Object? = dynamic>(X%) → X%} self::id : self::other)<core::int>, super core::Object::•()
+ ;
+}
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ ;
+static method other<X extends core::Object? = dynamic>(self::other::X% x) → self::other::X%
+ ;
+static method main() → void
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticTearOff @ org-dartlang-testcase:///issue47154a.dart:9:15 -> StaticTearOffConstant(id)
+Evaluated: StaticTearOff @ org-dartlang-testcase:///issue47154a.dart:10:15 -> StaticTearOffConstant(other)
+Extra constant evaluation: evaluated: 5, effectively constant: 2
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.weak.transformed.expect
new file mode 100644
index 0000000..55aaf0f
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154a.dart.weak.transformed.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/ {
+ final field (core::int) → core::int x;
+ const constructor •(core::bool b) → self::A
+ : self::A::x = (b ?{<X extends core::Object? = dynamic>(X%) → X%} #C1 : #C2)<core::int>, super core::Object::•()
+ ;
+}
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method other<X extends core::Object? = dynamic>(self::other::X% x) → self::other::X%
+ return throw "${x}";
+static method main() → void {
+ core::print("${#C3}, ${#C1}, ${#C3}, ${#C4}");
+}
+
+constants {
+ #C1 = static-tearoff self::id
+ #C2 = static-tearoff self::other
+ #C3 = instantiation self::id <core::int*>
+ #C4 = self::A {x:#C3}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47154a.dart:
+- A. (from org-dartlang-testcase:///issue47154a.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart
new file mode 100644
index 0000000..bc54add
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+ final int Function(int) x;
+ const A(bool b)
+ : x = (b ? id : other); // OK, `(...)<T1..Tk>` is potentially constant.
+}
+
+X id<X>(X x) => x;
+X other<X>(X x) => throw '$x';
+
+void main() {
+ const int Function(int) c1 =
+ id; // Already supported prior to the addition on this feature.
+ const c2 =
+ id; // Make `c2` a constant expression whose value is a function object.
+ const int Function(int) c3 =
+ c2; // OK, perform generic function instantiation on `c2`.
+ const c4 = A(
+ true); // OK, `(b ? id : other)<int>` is constant after substitution `b` -> `true`.
+ print('$c1, $c2, $c3, $c4');
+}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.strong.expect
new file mode 100644
index 0000000..41ae260
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.strong.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/ {
+ final field (core::int) → core::int x;
+ const constructor •(core::bool b) → self::A
+ : self::A::x = b ?{(core::int) → core::int} #C2 : #C4, super core::Object::•()
+ ;
+}
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method other<X extends core::Object? = dynamic>(self::other::X% x) → self::other::X%
+ return throw "${x}";
+static method main() → void {
+ core::print("${#C2}, ${#C1}, ${#C2}, ${#C5}");
+}
+
+constants {
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int>
+ #C3 = static-tearoff self::other
+ #C4 = instantiation self::other <core::int>
+ #C5 = self::A {x:#C2}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47154b.dart:
+- A. (from org-dartlang-testcase:///issue47154b.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.strong.transformed.expect
new file mode 100644
index 0000000..41ae260
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.strong.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/ {
+ final field (core::int) → core::int x;
+ const constructor •(core::bool b) → self::A
+ : self::A::x = b ?{(core::int) → core::int} #C2 : #C4, super core::Object::•()
+ ;
+}
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method other<X extends core::Object? = dynamic>(self::other::X% x) → self::other::X%
+ return throw "${x}";
+static method main() → void {
+ core::print("${#C2}, ${#C1}, ${#C2}, ${#C5}");
+}
+
+constants {
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int>
+ #C3 = static-tearoff self::other
+ #C4 = instantiation self::other <core::int>
+ #C5 = self::A {x:#C2}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47154b.dart:
+- A. (from org-dartlang-testcase:///issue47154b.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.textual_outline.expect
new file mode 100644
index 0000000..5d52a74
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+class A {
+ final int Function(int) x;
+ const A(bool b) : x = (b ? id : other);
+}
+
+X id<X>(X x) => x;
+X other<X>(X x) => throw '$x';
+void main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e5a005e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+X id<X>(X x) => x;
+X other<X>(X x) => throw '$x';
+
+class A {
+ const A(bool b) : x = (b ? id : other);
+ final int Function(int) x;
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.weak.expect
new file mode 100644
index 0000000..535ad97
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.weak.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/ {
+ final field (core::int) → core::int x;
+ const constructor •(core::bool b) → self::A
+ : self::A::x = b ?{(core::int) → core::int} #C2 : #C4, super core::Object::•()
+ ;
+}
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method other<X extends core::Object? = dynamic>(self::other::X% x) → self::other::X%
+ return throw "${x}";
+static method main() → void {
+ core::print("${#C2}, ${#C1}, ${#C2}, ${#C5}");
+}
+
+constants {
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int*>
+ #C3 = static-tearoff self::other
+ #C4 = instantiation self::other <core::int*>
+ #C5 = self::A {x:#C2}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47154b.dart:
+- A. (from org-dartlang-testcase:///issue47154b.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.weak.outline.expect
new file mode 100644
index 0000000..ca341b8
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.weak.outline.expect
@@ -0,0 +1,22 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/ {
+ final field (core::int) → core::int x;
+ const constructor •(core::bool b) → self::A
+ : self::A::x = b ?{(core::int) → core::int} self::id<core::int> : self::other<core::int>, super core::Object::•()
+ ;
+}
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ ;
+static method other<X extends core::Object? = dynamic>(self::other::X% x) → self::other::X%
+ ;
+static method main() → void
+ ;
+
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///issue47154b.dart:8:18 -> InstantiationConstant(id<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///issue47154b.dart:8:23 -> InstantiationConstant(other<int*>)
+Extra constant evaluation: evaluated: 4, effectively constant: 2
diff --git a/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.weak.transformed.expect
new file mode 100644
index 0000000..535ad97
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/issue47154b.dart.weak.transformed.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/ {
+ final field (core::int) → core::int x;
+ const constructor •(core::bool b) → self::A
+ : self::A::x = b ?{(core::int) → core::int} #C2 : #C4, super core::Object::•()
+ ;
+}
+static method id<X extends core::Object? = dynamic>(self::id::X% x) → self::id::X%
+ return x;
+static method other<X extends core::Object? = dynamic>(self::other::X% x) → self::other::X%
+ return throw "${x}";
+static method main() → void {
+ core::print("${#C2}, ${#C1}, ${#C2}, ${#C5}");
+}
+
+constants {
+ #C1 = static-tearoff self::id
+ #C2 = instantiation self::id <core::int*>
+ #C3 = static-tearoff self::other
+ #C4 = instantiation self::other <core::int*>
+ #C5 = self::A {x:#C2}
+}
+
+
+Constructor coverage from constants:
+org-dartlang-testcase:///issue47154b.dart:
+- A. (from org-dartlang-testcase:///issue47154b.dart:7:9)
+- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
diff --git a/pkg/front_end/testcases/incremental.status b/pkg/front_end/testcases/incremental.status
index 1c24c9e..f0401a1 100644
--- a/pkg/front_end/testcases/incremental.status
+++ b/pkg/front_end/testcases/incremental.status
@@ -6,3 +6,5 @@
# http://dartbug.com/41812#issuecomment-684825703
#strongmode_mixins_2: Crash
+
+changing_modules_16: Crash
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental/changing_modules_16.yaml b/pkg/front_end/testcases/incremental/changing_modules_16.yaml
new file mode 100644
index 0000000..69ad3b9
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/changing_modules_16.yaml
@@ -0,0 +1,49 @@
+# Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Reproduction of https://github.com/dart-lang/sdk/issues/47176
+# Compile an application with modules where one module has imported another
+# module with too many slashes. Now try to import it correctly.
+# This is essentially equivalent to not loading a needed component.
+
+type: newworld
+target: DDC
+modules:
+ moduleA:
+ moduleA/x/lib.dart: |
+ void foo() { }
+ moduleA/.packages: |
+ moduleA:.
+ moduleB:
+ moduleB/x/lib.dart: |
+ // Mind the double-slash! (on Windows this could probably also be a change
+ // in case (e.g 'lib' vs 'Lib')).
+ import 'package:moduleA/x//lib.dart';
+ void bar() { }
+ moduleB/.packages: |
+ moduleA:../moduleA
+ moduleB:.
+worlds:
+ - entry: main.dart
+ fromComponent: true
+ sources:
+ main.dart: |
+ import 'package:moduleB/x/lib.dart';
+ main() {
+ bar();
+ }
+ .packages: |
+ moduleA:moduleA
+ moduleB:moduleB
+ modules:
+ - moduleA
+ - moduleB
+ expectedLibraryCount: 3
+ neededDillLibraries:
+ - package:module/x/lib.dart
+ expectedContent:
+ org-dartlang-test:///main.dart:
+ - Procedure main
+ package:module/lib.dart:
+ - Procedure foo
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index a4f43e2..5f81f25 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -185,11 +185,6 @@
var inheritanceManager = InheritanceManager3();
// TODO(paulberry): is it a bad idea to throw away errors?
var errorListener = AnalysisErrorListener.NULL_LISTENER;
- // TODO(paulberry): once the feature is no longer experimental, change the
- // way we enable it in the resolver.
- // ignore: invalid_use_of_visible_for_testing_member
- var featureSet = FeatureSet.forTesting(
- sdkVersion: '2.6.0', additionalFeatures: [Feature.non_nullable]);
_resolver = ResolverVisitorForMigration(
inheritanceManager,
definingLibrary,
@@ -197,7 +192,10 @@
typeProvider,
errorListener,
_typeSystem,
- featureSet,
+ FeatureSet.fromEnableFlags2(
+ sdkLanguageVersion: Feature.non_nullable.releaseVersion!,
+ flags: [],
+ ),
migrationResolutionHooks);
}
diff --git a/pkg/vm/lib/transformations/ffi_native.dart b/pkg/vm/lib/transformations/ffi_native.dart
index ff405f8..3d44d46 100644
--- a/pkg/vm/lib/transformations/ffi_native.dart
+++ b/pkg/vm/lib/transformations/ffi_native.dart
@@ -102,22 +102,26 @@
final DartType dartType =
node.function.computeThisFunctionType(Nullability.nonNullable);
// Double Function(Double)
- final nativeType = annotationConst.typeArguments[0];
+ final nativeType = annotationConst.typeArguments[0] as FunctionType;
// InterfaceType(NativeFunction<Double Function(Double)>*)
final DartType nativeInterfaceType =
InterfaceType(nativeFunctionClass, Nullability.legacy, [nativeType]);
+ // Derive number of arguments from the native function signature.
+ final args_n = nativeType.positionalParameters.length;
+
// TODO(dartbug.com/31579): Add `..fileOffset`s once we can handle these in
// patch files.
- // _ffi_resolver('dart:math', 'Math_sqrt')
+ // _ffi_resolver('dart:math', 'Math_sqrt', 1)
final resolverInvocation = FunctionInvocation(
FunctionAccessKind.FunctionType,
StaticGet(resolverField),
Arguments([
ConstantExpression(
StringConstant(currentLibrary!.importUri.toString())),
- ConstantExpression(functionName)
+ ConstantExpression(functionName),
+ ConstantExpression(IntConstant(args_n)),
]),
functionType: resolverField.type as FunctionType);
@@ -151,7 +155,7 @@
parent.addField(funcPtrField);
} else {
throw 'Unexpected parent of @FfiNative function. '
- 'Expected Class or Library, but found ${parent}.';
+ 'Expected Class or Library, but found ${parent}.';
}
// _@FfiNative__square_root(x)
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 13e7440..f37aa3a 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -1397,9 +1397,8 @@
return _makeUnreachableCall([]);
} else {
if (!shaker.isMemberBodyReachable(node.target)) {
- // Annotations could contain references to constant fields.
- assert((node.target is Field) && (node.target as Field).isConst);
- shaker.addUsedMember(node.target);
+ throw '${node.runtimeType} "$node" uses unreachable member '
+ '${node.target} at ${node.location}';
}
return node;
}
@@ -1435,9 +1434,8 @@
return _makeUnreachableCall(_flattenArguments(node.arguments));
} else {
if (!shaker.isMemberBodyReachable(node.target)) {
- // Annotations could contain references to const constructors.
- assert(node.isConst);
- shaker.addUsedMember(node.target);
+ throw '${node.runtimeType} "$node" uses unreachable member '
+ '${node.target} at ${node.location}';
}
return node;
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart
index 602299f..1311d36 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart
@@ -9,4 +9,4 @@
if (list.isNotEmpty) {
new Class().method(null as dynamic);
}
-}
\ No newline at end of file
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
index 0e15b41..0e12dc6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
@@ -17,12 +17,12 @@
import "dart:core" as core;
abstract class Enum extends core::Object implements core::Enum {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3267] abstract get /*isLegacy*/ index() → core::int;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3265] abstract get /*isLegacy*/ index() → core::int;
}
class Class extends core::Object {
synthetic constructor •() → self::Class
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3268,getterSelectorId:3269] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3266,getterSelectorId:3267] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
return [@vm.inferred-type.metadata=!] e.{self::Enum::index}{core::int};
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.lib.dart b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.lib.dart
index 951e2e9..e5600e4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.lib.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.lib.dart
@@ -6,4 +6,4 @@
class Class {
int method(Enum e) => e.index;
-}
\ No newline at end of file
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart
index 1abc669..e995a89 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart
@@ -37,4 +37,4 @@
if (list.isNotEmpty) {
new ConstClass().method(null as dynamic);
}
-}
\ No newline at end of file
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
index 1f84d00..12268e7 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
@@ -48,12 +48,12 @@
import "dart:core" as core;
abstract class ConstEnum extends core::Object implements core::Enum {
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3273] abstract get /*isLegacy*/ index() → core::int;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3271] abstract get /*isLegacy*/ index() → core::int;
}
class ConstClass extends core::Object {
synthetic constructor •() → self::ConstClass
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3274,getterSelectorId:3275] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3272,getterSelectorId:3273] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
return [@vm.inferred-type.metadata=!] e.{self::ConstEnum::index}{core::int};
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.lib.dart b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.lib.dart
index af82d68..bc873dc 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.lib.dart
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.lib.dart
@@ -6,4 +6,4 @@
class ConstClass {
int method(ConstEnum e) => e.index;
-}
\ No newline at end of file
+}
diff --git a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
index adcdc07..affbe3a 100644
--- a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
@@ -1094,11 +1094,11 @@
return x;
}
-static void* FfiNativeResolver(const char* name) {
- if (strcmp(name, "ReturnIntPtr") == 0) {
+static void* FfiNativeResolver(const char* name, uintptr_t args_n) {
+ if (strcmp(name, "ReturnIntPtr") == 0 && args_n == 1) {
return reinterpret_cast<void*>(ReturnIntPtr);
}
- if (strcmp(name, "IsThreadInGenerated") == 0) {
+ if (strcmp(name, "IsThreadInGenerated") == 0 && args_n == 0) {
return reinterpret_cast<void*>(IsThreadInGenerated);
}
// This should be unreachable in tests.
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 861a87f..422e2be 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -3046,7 +3046,7 @@
*
* See Dart_SetFfiNativeResolver.
*/
-typedef void* (*Dart_FfiNativeResolver)(const char* name);
+typedef void* (*Dart_FfiNativeResolver)(const char* name, uintptr_t args_n);
/*
* ===========
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index cc4a6ff..239f758 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -276,7 +276,9 @@
}
// FFI native C function pointer resolver.
-static intptr_t FfiResolve(Dart_Handle lib_url, Dart_Handle name) {
+static intptr_t FfiResolve(Dart_Handle lib_url,
+ Dart_Handle name,
+ uintptr_t args_n) {
DARTSCOPE(Thread::Current());
const String& lib_url_str = Api::UnwrapStringHandle(T->zone(), lib_url);
@@ -296,7 +298,7 @@
Exceptions::ThrowArgumentError(error);
}
- auto* f = resolver(function_name.ToCString());
+ auto* f = resolver(function_name.ToCString(), args_n);
if (f == nullptr) {
const String& error = String::Handle(String::NewFormatted(
"Couldn't resolve function: '%s'.", function_name.ToCString()));
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 3ca14d8..f478245 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -67,10 +67,12 @@
dart/regress_40462_test: SkipSlow
dart/regress_40753_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
dart/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
+dart/use_strip_flag_test: Pass, Slow # This test can take a longer time to complete.
dart_2/appjit_cha_deopt_test: SkipSlow
dart_2/regress_40462_test: SkipSlow
dart_2/regress_40753_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
dart_2/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
+dart_2/use_strip_flag_test: Pass, Slow # This test can take a longer time to complete.
[ $compiler == app_jitk ]
dart/snapshot_version_test: RuntimeError
diff --git a/runtime/vm/code_patcher_arm64_test.cc b/runtime/vm/code_patcher_arm64_test.cc
index 54fc1b9..0bd184c 100644
--- a/runtime/vm/code_patcher_arm64_test.cc
+++ b/runtime/vm/code_patcher_arm64_test.cc
@@ -33,7 +33,8 @@
signature, function_name, UntaggedFunction::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
- const String& target_name = String::Handle(String::New("targetFunction"));
+ const String& target_name =
+ String::Handle(Symbols::New(thread, "targetFunction"));
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgs = 1;
const Array& args_descriptor = Array::Handle(ArgumentsDescriptor::NewBoxed(
diff --git a/runtime/vm/code_patcher_arm_test.cc b/runtime/vm/code_patcher_arm_test.cc
index c9026d5..c963d44 100644
--- a/runtime/vm/code_patcher_arm_test.cc
+++ b/runtime/vm/code_patcher_arm_test.cc
@@ -33,7 +33,8 @@
signature, function_name, UntaggedFunction::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
- const String& target_name = String::Handle(String::New("targetFunction"));
+ const String& target_name =
+ String::Handle(Symbols::New(thread, "targetFunction"));
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgs = 1;
const Array& args_descriptor = Array::Handle(ArgumentsDescriptor::NewBoxed(
diff --git a/runtime/vm/code_patcher_ia32_test.cc b/runtime/vm/code_patcher_ia32_test.cc
index 36c6ec5..ef55b48 100644
--- a/runtime/vm/code_patcher_ia32_test.cc
+++ b/runtime/vm/code_patcher_ia32_test.cc
@@ -33,7 +33,8 @@
signature, function_name, UntaggedFunction::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
- const String& target_name = String::Handle(String::New("targetFunction"));
+ const String& target_name =
+ String::Handle(Symbols::New(thread, "targetFunction"));
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgs = 1;
const Array& args_descriptor = Array::Handle(ArgumentsDescriptor::NewBoxed(
diff --git a/runtime/vm/code_patcher_x64_test.cc b/runtime/vm/code_patcher_x64_test.cc
index e5666e3..29cf624 100644
--- a/runtime/vm/code_patcher_x64_test.cc
+++ b/runtime/vm/code_patcher_x64_test.cc
@@ -33,7 +33,8 @@
signature, function_name, UntaggedFunction::kRegularFunction, true, false,
false, false, false, owner_class, TokenPosition::kNoSource));
- const String& target_name = String::Handle(String::New("targetFunction"));
+ const String& target_name =
+ String::Handle(Symbols::New(thread, "targetFunction"));
const intptr_t kTypeArgsLen = 0;
const intptr_t kNumArgs = 1;
const Array& args_descriptor = Array::Handle(ArgumentsDescriptor::NewBoxed(
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 163403a..1f65f74 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -1671,8 +1671,11 @@
RELEASE_ASSERT(CanLoadFromObjectPool(object));
// Make sure that class CallPattern is able to decode this load from the
// object pool.
- const auto index = is_unique ? object_pool_builder().AddObject(object)
- : object_pool_builder().FindObject(object);
+ const auto index = is_unique
+ ? object_pool_builder().AddObject(
+ object, ObjectPoolBuilderEntry::kPatchable)
+ : object_pool_builder().FindObject(
+ object, ObjectPoolBuilderEntry::kNotPatchable);
LoadWordFromPoolIndex(rd, index, pp, cond);
}
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index d15a27a..cd72ba5 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -555,8 +555,11 @@
}
}
if (CanLoadFromObjectPool(object)) {
- const intptr_t index = is_unique ? object_pool_builder().AddObject(object)
- : object_pool_builder().FindObject(object);
+ const intptr_t index =
+ is_unique ? object_pool_builder().AddObject(
+ object, ObjectPoolBuilderEntry::kPatchable)
+ : object_pool_builder().FindObject(
+ object, ObjectPoolBuilderEntry::kNotPatchable);
LoadWordFromPoolIndex(dst, index);
return;
}
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 7042a44..d2dc30c 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1287,8 +1287,11 @@
}
}
if (CanLoadFromObjectPool(object)) {
- const intptr_t index = is_unique ? object_pool_builder().AddObject(object)
- : object_pool_builder().FindObject(object);
+ const intptr_t index =
+ is_unique ? object_pool_builder().AddObject(
+ object, ObjectPoolBuilderEntry::kPatchable)
+ : object_pool_builder().FindObject(
+ object, ObjectPoolBuilderEntry::kNotPatchable);
LoadWordFromPoolIndex(dst, index);
return;
}
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index c4fcdd7..65efc13 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -99,7 +99,7 @@
if (obj.IsNull()) {
return 2011;
}
- if (obj.IsString() || obj.IsNumber()) {
+ if (obj.IsInstance()) {
return Instance::Cast(obj).CanonicalizeHash();
}
if (obj.IsCode()) {
@@ -112,6 +112,9 @@
if (obj.IsField()) {
return dart::String::HashRawSymbol(Field::Cast(obj).name());
}
+ if (obj.IsICData()) {
+ return ICData::Cast(obj).Hash();
+ }
// Unlikely.
return obj.GetClassId();
}
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 38b1022..fda1251 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -92,86 +92,62 @@
class DartInitializationState {
public:
- enum class InitializationState {
- kUnInitialized = 0,
- kInitializing = 1,
- kInitialized = 2,
- kCleaningup = 3,
- };
+ uint8_t kUnInitialized = 0;
+ uint8_t kInitializing = 1;
+ uint8_t kInitialized = 2;
+ uint8_t kCleaningup = 3;
- DartInitializationState()
- : state_(InitializationState::kUnInitialized),
- in_use_(false),
- lock_(nullptr) {
- lock_ = new Monitor();
- }
+ DartInitializationState() : state_(0), in_use_count_(0) {}
~DartInitializationState() {}
bool SetInitializing() {
- MonitorLocker ml(lock_);
- if (state_ != InitializationState::kUnInitialized || in_use_) {
- return false;
- }
- state_ = InitializationState::kInitializing;
- return true;
+ ASSERT(in_use_count_.load() == 0);
+ return state_.compare_exchange_strong(kUnInitialized, kInitializing);
}
void ResetInitializing() {
- MonitorLocker ml(lock_);
- ASSERT((state_ == InitializationState::kInitializing) && !in_use_);
- state_ = InitializationState::kUnInitialized;
+ ASSERT(in_use_count_.load() == 0);
+ bool result = state_.compare_exchange_strong(kInitializing, kUnInitialized);
+ ASSERT(result);
}
void SetInitialized() {
- MonitorLocker ml(lock_);
- ASSERT((state_ == InitializationState::kInitializing) && !in_use_);
- state_ = InitializationState::kInitialized;
+ ASSERT(in_use_count_.load() == 0);
+ bool result = state_.compare_exchange_strong(kInitializing, kInitialized);
+ ASSERT(result);
}
- bool IsInitialized() const {
- MonitorLocker ml(lock_);
- return (state_ == InitializationState::kInitialized);
- }
+ bool IsInitialized() const { return state_.load() == kInitialized; }
bool SetCleaningup() {
- MonitorLocker ml(lock_);
- if (state_ != InitializationState::kInitialized) {
- return false;
- }
- state_ = InitializationState::kCleaningup;
- return true;
+ return state_.compare_exchange_strong(kInitialized, kCleaningup);
}
void SetUnInitialized() {
- MonitorLocker ml(lock_);
- ASSERT(state_ == InitializationState::kCleaningup);
- while (in_use_) {
- ml.Wait();
+ while (in_use_count_.load() > 0) {
+ OS::Sleep(1); // Sleep for 1 millis waiting for it to not be in use.
}
- state_ = InitializationState::kUnInitialized;
+ bool result = state_.compare_exchange_strong(kCleaningup, kUnInitialized);
+ ASSERT(result);
}
bool SetInUse() {
- MonitorLocker ml(lock_);
- if (state_ != InitializationState::kInitialized) {
+ if (state_.load() != kInitialized) {
return false;
}
- in_use_ = true;
+ in_use_count_ += 1;
return true;
}
void ResetInUse() {
- MonitorLocker ml(lock_);
- ASSERT((state_ == InitializationState::kInitialized) ||
- (state_ == InitializationState::kCleaningup));
- in_use_ = false;
- ml.NotifyAll();
+ uint8_t value = state_.load();
+ ASSERT((value == kInitialized) || (value == kCleaningup));
+ in_use_count_ -= 1;
}
private:
- InitializationState state_;
- bool in_use_;
- Monitor* lock_;
+ std::atomic<uint8_t> state_;
+ std::atomic<uint64_t> in_use_count_;
};
static DartInitializationState init_state_;
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 2849c6b..4d9d1df 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -9585,8 +9585,9 @@
return x;
}
-static void* FfiNativeResolver(const char* name) {
+static void* FfiNativeResolver(const char* name, uintptr_t args_n) {
ASSERT(strcmp(name, "EchoInt") == 0);
+ ASSERT(args_n == 1);
return reinterpret_cast<void*>(EchoInt);
}
@@ -9628,7 +9629,7 @@
"Invalid argument(s): Library has no handler: 'file:///test-lib'.");
}
-static void* NopResolver(const char* name) {
+static void* NopResolver(const char* name, uintptr_t args_n) {
return nullptr;
}
diff --git a/runtime/vm/hash_map.h b/runtime/vm/hash_map.h
index 7c0cb4b..e1f1be9 100644
--- a/runtime/vm/hash_map.h
+++ b/runtime/vm/hash_map.h
@@ -17,25 +17,18 @@
public:
explicit BaseDirectChainedHashMap(Allocator* allocator,
intptr_t initial_size = kInitialSize)
- : array_size_(0),
- lists_size_(0),
- count_(0),
- array_(NULL),
- lists_(NULL),
- free_list_head_(kNil),
- allocator_(allocator) {
- ASSERT(Utils::IsPowerOfTwo(initial_size));
- ResizeLists(initial_size);
+ : allocator_(allocator) {
Resize(initial_size);
}
BaseDirectChainedHashMap(const BaseDirectChainedHashMap& other);
- intptr_t Length() const { return count_; }
+ intptr_t Length() const { return next_pair_index_ - deleted_count_; }
- virtual ~BaseDirectChainedHashMap() {
- allocator_->template Free<HashMapListElement>(array_, array_size_);
- allocator_->template Free<HashMapListElement>(lists_, lists_size_);
+ ~BaseDirectChainedHashMap() {
+ allocator_->template Free<uint32_t>(hash_table_, hash_table_size_);
+ allocator_->template Free<typename KeyValueTrait::Pair>(pairs_,
+ pairs_size_);
}
// Assumes that no existing pair in the map has a key equal to [kv.key].
@@ -56,41 +49,35 @@
typename KeyValueTrait::Pair* Lookup(typename KeyValueTrait::Key key) const;
bool HasKey(typename KeyValueTrait::Key key) const {
- return Lookup(key) != NULL;
+ return Lookup(key) != nullptr;
}
- intptr_t Size() const { return count_; }
- bool IsEmpty() const { return count_ == 0; }
+ intptr_t Size() const { return next_pair_index_ - deleted_count_; }
+ bool IsEmpty() const { return Size() == 0; }
- virtual void Clear() {
- if (!IsEmpty()) {
- count_ = 0;
- InitArray(array_, array_size_);
- InitArray(lists_, lists_size_);
- lists_[0].next = kNil;
- for (intptr_t i = 1; i < lists_size_; ++i) {
- lists_[i].next = i - 1;
- }
- free_list_head_ = lists_size_ - 1;
+ void Clear() {
+ for (uint32_t i = 0; i < hash_table_size_; i++) {
+ hash_table_[i] = kEmpty;
}
+ for (uint32_t i = 0; i < next_pair_index_; i++) {
+ pairs_[i] = typename KeyValueTrait::Pair();
+ }
+ next_pair_index_ = 0;
+ deleted_count_ = 0;
}
class Iterator {
public:
typename KeyValueTrait::Pair* Next();
- void Reset() {
- array_index_ = 0;
- list_index_ = kNil;
- }
+ void Reset() { pair_index_ = 0; }
private:
explicit Iterator(const BaseDirectChainedHashMap& map)
- : map_(map), array_index_(0), list_index_(kNil) {}
+ : map_(map), pair_index_(0) {}
const BaseDirectChainedHashMap& map_;
- intptr_t array_index_;
- intptr_t list_index_;
+ uint32_t pair_index_;
template <typename T, typename Bs, typename A>
friend class BaseDirectChainedHashMap;
@@ -99,35 +86,21 @@
Iterator GetIterator() const { return Iterator(*this); }
protected:
- // A linked list of T values. Stored in arrays.
- struct HashMapListElement {
- HashMapListElement() : kv(), next(kNil) {}
- typename KeyValueTrait::Pair kv;
- intptr_t next; // Index in the array of the next list element.
- };
- static const intptr_t kNil = -1; // The end of a linked list
-
- static void InitArray(HashMapListElement* array, intptr_t size) {
- for (intptr_t i = 0; i < size; ++i) {
- array[i] = HashMapListElement();
- }
- }
-
- // Must be a power of 2.
- static const intptr_t kInitialSize = 16;
+ static constexpr intptr_t kInitialSize = 16;
void Resize(intptr_t new_size);
- void ResizeLists(intptr_t new_size);
- uword Bound(uword value) const { return value & (array_size_ - 1); }
- intptr_t array_size_;
- intptr_t lists_size_;
- intptr_t count_; // The number of values stored in the HashMap.
- HashMapListElement* array_; // Primary store - contains the first value
- // with a given hash. Colliding elements are stored in linked lists.
- HashMapListElement* lists_; // The linked lists containing hash collisions.
- intptr_t free_list_head_; // Unused elements in lists_ are on the free list.
- Allocator* allocator_;
+ Allocator* const allocator_;
+ uint32_t* hash_table_ = nullptr;
+ typename KeyValueTrait::Pair* pairs_ = nullptr;
+ uint32_t hash_table_size_ = 0;
+ uint32_t pairs_size_ = 0;
+ uint32_t next_pair_index_ = 0;
+ uint32_t deleted_count_ = 0;
+
+ static constexpr uint32_t kEmpty = kMaxUint32;
+ static constexpr uint32_t kDeleted = kMaxUint32 - 1;
+ static constexpr uint32_t kMaxPairs = kMaxUint32 - 2;
private:
void operator=(const BaseDirectChainedHashMap& other) = delete;
@@ -137,42 +110,45 @@
BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::BaseDirectChainedHashMap(
const BaseDirectChainedHashMap& other)
: B(),
- array_size_(other.array_size_),
- lists_size_(other.lists_size_),
- count_(other.count_),
- array_(other.allocator_->template Alloc<HashMapListElement>(
- other.array_size_)),
- lists_(other.allocator_->template Alloc<HashMapListElement>(
- other.lists_size_)),
- free_list_head_(other.free_list_head_),
- allocator_(other.allocator_) {
- memmove(array_, other.array_, array_size_ * sizeof(HashMapListElement));
- memmove(lists_, other.lists_, lists_size_ * sizeof(HashMapListElement));
+ allocator_(other.allocator_),
+ hash_table_(
+ other.allocator_->template Alloc<uint32_t>(other.hash_table_size_)),
+ pairs_(other.allocator_->template Alloc<typename KeyValueTrait::Pair>(
+ other.pairs_size_)),
+ hash_table_size_(other.hash_table_size_),
+ pairs_size_(other.pairs_size_),
+ next_pair_index_(other.next_pair_index_),
+ deleted_count_(other.deleted_count_) {
+ memmove(hash_table_, other.hash_table_, hash_table_size_ * sizeof(uint32_t));
+ memmove(pairs_, other.pairs_,
+ pairs_size_ * sizeof(typename KeyValueTrait::Pair));
}
template <typename KeyValueTrait, typename B, typename Allocator>
typename KeyValueTrait::Pair*
BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Lookup(
typename KeyValueTrait::Key key) const {
- const typename KeyValueTrait::Value kNoValue =
- KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
-
uword hash = KeyValueTrait::Hash(key);
- uword pos = Bound(hash);
- if (KeyValueTrait::ValueOf(array_[pos].kv) != kNoValue) {
- if (KeyValueTrait::IsKeyEqual(array_[pos].kv, key)) {
- return &array_[pos].kv;
+ uint32_t mask = hash_table_size_ - 1;
+ uint32_t hash_index = hash & mask;
+ uint32_t start = hash_index;
+ for (;;) {
+ uint32_t pair_index = hash_table_[hash_index];
+ if (pair_index == kEmpty) {
+ return nullptr;
}
-
- intptr_t next = array_[pos].next;
- while (next != kNil) {
- if (KeyValueTrait::IsKeyEqual(lists_[next].kv, key)) {
- return &lists_[next].kv;
+ if (pair_index != kDeleted) {
+ ASSERT(pair_index < pairs_size_);
+ if (KeyValueTrait::IsKeyEqual(pairs_[pair_index], key)) {
+ return &pairs_[pair_index];
}
- next = lists_[next].next;
}
+ hash_index = (hash_index + 1) & mask;
+ // Hashtable must contain at least one empty marker.
+ ASSERT(hash_index != start);
}
- return NULL;
+ UNREACHABLE();
+ return nullptr;
}
template <typename KeyValueTrait, typename B, typename Allocator>
@@ -182,7 +158,7 @@
const typename KeyValueTrait::Value kNoValue =
KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
typename KeyValueTrait::Pair* pair = Lookup(key);
- return (pair == NULL) ? kNoValue : KeyValueTrait::ValueOf(*pair);
+ return (pair == nullptr) ? kNoValue : KeyValueTrait::ValueOf(*pair);
}
template <typename KeyValueTrait, typename B, typename Allocator>
@@ -190,135 +166,89 @@
BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Iterator::Next() {
const typename KeyValueTrait::Value kNoValue =
KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
-
- // Return the current lists_ entry (if any), advancing list_index_.
- if (list_index_ != kNil) {
- intptr_t current = list_index_;
- list_index_ = map_.lists_[current].next;
- return &map_.lists_[current].kv;
+ while (pair_index_ < map_.next_pair_index_) {
+ if (KeyValueTrait::ValueOf(map_.pairs_[pair_index_]) != kNoValue) {
+ intptr_t old_index = pair_index_;
+ pair_index_++;
+ return &map_.pairs_[old_index];
+ }
+ pair_index_++;
}
-
- // When we're done with the list, we'll continue with the next array
- // slot.
- while ((array_index_ < map_.array_size_) &&
- KeyValueTrait::ValueOf(map_.array_[array_index_].kv) == kNoValue) {
- ++array_index_;
- }
- if (array_index_ < map_.array_size_) {
- const intptr_t old_array_index = array_index_;
- ++array_index_;
- list_index_ = map_.array_[old_array_index].next;
- return &map_.array_[old_array_index].kv;
- }
-
return nullptr;
}
template <typename KeyValueTrait, typename B, typename Allocator>
void BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Resize(
intptr_t new_size) {
+ ASSERT(new_size >= Size());
+
+ uint32_t old_hash_table_size = hash_table_size_;
+ // 75% load factor + at least one kEmpty slot
+ hash_table_size_ = Utils::RoundUpToPowerOfTwo(new_size * 4 / 3 + 1);
+ hash_table_ = allocator_->template Realloc<uint32_t>(
+ hash_table_, old_hash_table_size, hash_table_size_);
+ for (uint32_t i = 0; i < hash_table_size_; i++) {
+ hash_table_[i] = kEmpty;
+ }
+
+ typename KeyValueTrait::Pair* old_pairs = pairs_;
+ uint32_t old_pairs_size = pairs_size_;
+ uint32_t old_next_pair_index = next_pair_index_;
+ uint32_t old_deleted_count = deleted_count_;
+ next_pair_index_ = 0;
+ deleted_count_ = 0;
+ pairs_size_ = new_size;
+ pairs_ =
+ allocator_->template Alloc<typename KeyValueTrait::Pair>(pairs_size_);
+ for (uint32_t i = 0; i < pairs_size_; i++) {
+ pairs_[i] = typename KeyValueTrait::Pair();
+ }
+
const typename KeyValueTrait::Value kNoValue =
KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
-
- ASSERT(new_size > count_);
- // Hashing the values into the new array has no more collisions than in the
- // old hash map, so we can use the existing lists_ array, if we are careful.
-
- // Make sure we have at least one free element.
- if (free_list_head_ == kNil) {
- ResizeLists(lists_size_ << 1);
- }
-
- HashMapListElement* new_array =
- allocator_->template Alloc<HashMapListElement>(new_size);
- InitArray(new_array, new_size);
-
- HashMapListElement* old_array = array_;
- intptr_t old_size = array_size_;
-
- intptr_t old_count = count_;
- count_ = 0;
- array_size_ = new_size;
- array_ = new_array;
-
- if (old_array != NULL) {
- // Iterate over all the elements in lists, rehashing them.
- for (intptr_t i = 0; i < old_size; ++i) {
- if (KeyValueTrait::ValueOf(old_array[i].kv) != kNoValue) {
- intptr_t current = old_array[i].next;
- while (current != kNil) {
- Insert(lists_[current].kv);
- intptr_t next = lists_[current].next;
- lists_[current].next = free_list_head_;
- free_list_head_ = current;
- current = next;
- }
- // Rehash the directly stored value.
- Insert(old_array[i].kv);
- }
+ uint32_t used = 0;
+ uint32_t deleted = 0;
+ for (uint32_t i = 0; i < old_next_pair_index; i++) {
+ if (KeyValueTrait::ValueOf(old_pairs[i]) == kNoValue) {
+ deleted++;
+ } else {
+ Insert(old_pairs[i]);
+ used++;
}
}
- USE(old_count);
- ASSERT(count_ == old_count);
- allocator_->template Free<HashMapListElement>(old_array, old_size);
-}
-
-template <typename KeyValueTrait, typename B, typename Allocator>
-void BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::ResizeLists(
- intptr_t new_size) {
- ASSERT(new_size > lists_size_);
-
- HashMapListElement* new_lists =
- allocator_->template Alloc<HashMapListElement>(new_size);
- InitArray(new_lists, new_size);
-
- HashMapListElement* old_lists = lists_;
- intptr_t old_size = lists_size_;
-
- lists_size_ = new_size;
- lists_ = new_lists;
-
- if (old_lists != NULL) {
- for (intptr_t i = 0; i < old_size; i++) {
- lists_[i] = old_lists[i];
- }
- }
- for (intptr_t i = old_size; i < lists_size_; ++i) {
- lists_[i].next = free_list_head_;
- free_list_head_ = i;
- }
- allocator_->template Free<HashMapListElement>(old_lists, old_size);
+ ASSERT_EQUAL(deleted, old_deleted_count);
+ ASSERT_EQUAL(used, old_next_pair_index - old_deleted_count);
+ ASSERT_EQUAL(used, next_pair_index_);
+ allocator_->template Free<typename KeyValueTrait::Pair>(old_pairs,
+ old_pairs_size);
}
template <typename KeyValueTrait, typename B, typename Allocator>
void BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Insert(
typename KeyValueTrait::Pair kv) {
- const typename KeyValueTrait::Value kNoValue =
- KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
-
- ASSERT(KeyValueTrait::ValueOf(kv) != kNoValue);
- // TODO(dartbug.com/38018): Add assert that Lookup returns nullptr for key.
-
- // Resizing when half of the hashtable is filled up.
- if (count_ >= array_size_ >> 1) Resize(array_size_ << 1);
- ASSERT(count_ < array_size_);
- count_++;
- uword pos = Bound(KeyValueTrait::Hash(KeyValueTrait::KeyOf(kv)));
- if (KeyValueTrait::ValueOf(array_[pos].kv) == kNoValue) {
- array_[pos].kv = kv;
- array_[pos].next = kNil;
- } else {
- if (free_list_head_ == kNil) {
- ResizeLists(lists_size_ << 1);
+ // TODO(dartbug.com/38018):
+ // ASSERT(Lookup(KeyValueTrait::KeyOf(kv)) == nullptr);
+ ASSERT(next_pair_index_ < pairs_size_);
+ uword hash = KeyValueTrait::Hash(KeyValueTrait::KeyOf(kv));
+ uint32_t mask = hash_table_size_ - 1;
+ uint32_t hash_index = hash & mask;
+ uint32_t start = hash_index;
+ for (;;) {
+ uint32_t pair_index = hash_table_[hash_index];
+ if ((pair_index == kEmpty) || (pair_index == kDeleted)) {
+ hash_table_[hash_index] = next_pair_index_;
+ pairs_[next_pair_index_] = kv;
+ next_pair_index_++;
+ break;
}
- intptr_t new_element_pos = free_list_head_;
- ASSERT(new_element_pos != kNil);
- free_list_head_ = lists_[free_list_head_].next;
- lists_[new_element_pos].kv = kv;
- lists_[new_element_pos].next = array_[pos].next;
- ASSERT(array_[pos].next == kNil ||
- KeyValueTrait::ValueOf(lists_[array_[pos].next].kv) != kNoValue);
- array_[pos].next = new_element_pos;
+ ASSERT(pair_index < pairs_size_);
+ hash_index = (hash_index + 1) & mask;
+ // Hashtable must contain at least one empty marker.
+ ASSERT(hash_index != start);
+ }
+
+ if (next_pair_index_ == pairs_size_) {
+ Resize(Size() << 1);
}
}
@@ -339,66 +269,30 @@
template <typename KeyValueTrait, typename B, typename Allocator>
bool BaseDirectChainedHashMap<KeyValueTrait, B, Allocator>::Remove(
typename KeyValueTrait::Key key) {
- const typename KeyValueTrait::Value kNoValue =
- KeyValueTrait::ValueOf(typename KeyValueTrait::Pair());
-
- uword pos = Bound(KeyValueTrait::Hash(key));
-
- // Check to see if the first element in the bucket is the one we want to
- // remove.
- if (KeyValueTrait::ValueOf(array_[pos].kv) == kNoValue) return false;
- if (KeyValueTrait::IsKeyEqual(array_[pos].kv, key)) {
- if (array_[pos].next == kNil) {
- array_[pos] = HashMapListElement();
- } else {
- intptr_t next = array_[pos].next;
- array_[pos] = lists_[next];
- lists_[next] = HashMapListElement();
- lists_[next].next = free_list_head_;
- free_list_head_ = next;
- }
- count_--;
- return true;
- }
-
- intptr_t current = array_[pos].next;
-
- // If there's only the single element in the bucket and it does not match the
- // key to be removed, just return.
- if (current == kNil) {
- return false;
- }
-
- // Check the case where the second element in the bucket is the one to be
- // removed.
- if (KeyValueTrait::IsKeyEqual(lists_[current].kv, key)) {
- array_[pos].next = lists_[current].next;
- lists_[current] = HashMapListElement();
- lists_[current].next = free_list_head_;
- free_list_head_ = current;
- count_--;
- return true;
- }
-
- // Finally, iterate through the rest of the bucket to see if we can find the
- // entry that matches our key.
- intptr_t previous = -1;
- while (!KeyValueTrait::IsKeyEqual(lists_[current].kv, key)) {
- previous = current;
- current = lists_[current].next;
-
- if (current == kNil) {
- // Could not find entry with provided key to remove.
+ uword hash = KeyValueTrait::Hash(key);
+ uint32_t mask = hash_table_size_ - 1;
+ uint32_t hash_index = hash & mask;
+ uint32_t start = hash_index;
+ for (;;) {
+ uint32_t pair_index = hash_table_[hash_index];
+ if (pair_index == kEmpty) {
return false;
}
+ if (pair_index != kDeleted) {
+ ASSERT(pair_index < pairs_size_);
+ if (KeyValueTrait::IsKeyEqual(pairs_[pair_index], key)) {
+ hash_table_[hash_index] = kDeleted;
+ pairs_[pair_index] = typename KeyValueTrait::Pair();
+ deleted_count_++;
+ return true;
+ }
+ }
+ hash_index = (hash_index + 1) & mask;
+ // Hashtable must contain at least one empty marker.
+ ASSERT(hash_index != start);
}
-
- lists_[previous].next = lists_[current].next;
- lists_[current] = HashMapListElement();
- lists_[current].next = free_list_head_;
- free_list_head_ = current;
- count_--;
- return true;
+ UNREACHABLE();
+ return false;
}
template <typename KeyValueTrait>
@@ -433,7 +327,7 @@
MallocDirectChainedHashMap(
intptr_t initial_size = MallocDirectChainedHashMap::kInitialSize)
: BaseDirectChainedHashMap<KeyValueTrait, MallocAllocated, Malloc>(
- NULL,
+ nullptr,
initial_size) {}
// The only use of the copy constructor seems to be in hash_map_test.cc.
@@ -502,7 +396,7 @@
struct Pair {
Key key;
Value value;
- Pair() : key(NULL), value() {}
+ Pair() : key(nullptr), value() {}
Pair(const Key key, const Value& value) : key(key), value(value) {}
Pair(const Pair& other) : key(other.key), value(other.value) {}
Pair& operator=(const Pair&) = default;
@@ -645,7 +539,7 @@
inline V Lookup(const Key& key) const {
Pair* pair =
DirectChainedHashMap<IntKeyRawPointerValueTrait<V> >::Lookup(key);
- if (pair == NULL) {
+ if (pair == nullptr) {
return V();
} else {
return pair->value;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 1355962..7a9fc6e 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -15526,6 +15526,7 @@
void CallSiteData::set_target_name(const String& value) const {
ASSERT(!value.IsNull());
+ ASSERT(value.IsCanonical());
untag()->set_target_name(value.ptr());
}
@@ -15566,15 +15567,17 @@
#endif
}
+uword ICData::Hash() const {
+ return String::HashRawSymbol(target_name()) ^ deopt_id();
+}
+
const char* ICData::ToCString() const {
Zone* zone = Thread::Current()->zone();
const String& name = String::Handle(zone, target_name());
- const intptr_t num_args = NumArgsTested();
- const intptr_t num_checks = NumberOfChecks();
- const intptr_t type_args_len = TypeArgsLen();
- return zone->PrintToString(
- "ICData(%s num-args: %" Pd " num-checks: %" Pd " type-args-len: %" Pd ")",
- name.ToCString(), num_args, num_checks, type_args_len);
+ return zone->PrintToString("ICData(%s num-args: %" Pd " num-checks: %" Pd
+ " type-args-len: %" Pd ", deopt-id: %" Pd ")",
+ name.ToCString(), NumArgsTested(),
+ NumberOfChecks(), TypeArgsLen(), deopt_id());
}
FunctionPtr ICData::Owner() const {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 50d4136..b68fe85 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2436,6 +2436,8 @@
untag()->state_bits_.UpdateBool<ReceiverCannotBeSmiBit>(value);
}
+ uword Hash() const;
+
private:
static ICDataPtr New();
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 7b98530..be755ef 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3209,7 +3209,7 @@
}
ISOLATE_UNIT_TEST_CASE(MegamorphicCache) {
- const auto& name = String::Handle(String::New("name"));
+ const auto& name = String::Handle(Symbols::New(thread, "name"));
const auto& args_descriptor =
Array::Handle(ArgumentsDescriptor::NewBoxed(1, 1, Object::null_array()));
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 2eba0fb..14171a6 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -464,7 +464,7 @@
const Array& ic_datas = Array::Handle(Array::New(kNumICData));
ICData& ic_data = ICData::Handle();
Function& owner = *CreateFunction("DummyFunction");
- String& name = String::Handle(String::New("foo"));
+ String& name = String::Handle(Symbols::New(thread, "foo"));
const Array& args_desc =
Array::Handle(ArgumentsDescriptor::NewBoxed(0, 0, Object::empty_array()));
for (intptr_t i = 0; i < kNumICData; i++) {
diff --git a/sdk/lib/core/duration.dart b/sdk/lib/core/duration.dart
index 57075cb..b85de35 100644
--- a/sdk/lib/core/duration.dart
+++ b/sdk/lib/core/duration.dart
@@ -124,6 +124,10 @@
/// Likewise, values can be negative, in which case they
/// underflow and subtract from the next larger unit.
///
+ /// If the total number of microseconds cannot be represented
+ /// as an integer value, the number of microseconds might be truncated
+ /// and it might lose precision.
+ ///
/// All arguments are 0 by default.
const Duration(
{int days = 0,
@@ -132,12 +136,12 @@
int seconds = 0,
int milliseconds = 0,
int microseconds = 0})
- : this._microseconds(microsecondsPerDay * days +
- microsecondsPerHour * hours +
- microsecondsPerMinute * minutes +
- microsecondsPerSecond * seconds +
+ : this._microseconds(microseconds +
microsecondsPerMillisecond * milliseconds +
- microseconds);
+ microsecondsPerSecond * seconds +
+ microsecondsPerMinute * minutes +
+ microsecondsPerHour * hours +
+ microsecondsPerDay * days);
// Fast path internal direct constructor to avoids the optional arguments and
// [_microseconds] recomputation.
@@ -257,30 +261,35 @@
/// d.toString(); // "1:10:00.000500"
/// ```
String toString() {
- String sixDigits(int n) {
- if (n >= 100000) return "$n";
- if (n >= 10000) return "0$n";
- if (n >= 1000) return "00$n";
- if (n >= 100) return "000$n";
- if (n >= 10) return "0000$n";
- return "00000$n";
- }
+ var buffer = List<String>.filled(9, "");
+ var microseconds = inMicroseconds;
- String twoDigits(int n) {
- if (n >= 10) return "$n";
- return "0$n";
- }
+ var hours = microseconds ~/ microsecondsPerHour;
+ microseconds = microseconds.remainder(microsecondsPerHour);
- if (inMicroseconds < 0) {
- return "-${-this}";
- }
- String twoDigitMinutes =
- twoDigits(inMinutes.remainder(minutesPerHour) as int);
- String twoDigitSeconds =
- twoDigits(inSeconds.remainder(secondsPerMinute) as int);
- String sixDigitUs =
- sixDigits(inMicroseconds.remainder(microsecondsPerSecond) as int);
- return "$inHours:$twoDigitMinutes:$twoDigitSeconds.$sixDigitUs";
+ if (microseconds < 0) microseconds = -microseconds;
+ var hoursString = hours.toString();
+ buffer
+ ..[0] = hoursString
+ ..[1] = ":";
+
+ var minutes = microseconds ~/ microsecondsPerMinute;
+ microseconds = microseconds.remainder(microsecondsPerMinute);
+
+ if (minutes < 10) buffer[2] = "0";
+ buffer
+ ..[3] = minutes.toString()
+ ..[4] = ":";
+
+ var seconds = microseconds ~/ microsecondsPerSecond;
+ microseconds = microseconds.remainder(microsecondsPerSecond);
+
+ if (seconds < 10) buffer[5] = "0";
+ buffer
+ ..[6] = seconds.toString()
+ ..[7] = "."
+ ..[8] = microseconds.toString().padLeft(6, "0");
+ return buffer.join("");
}
/// Whether this [Duration] is negative.
@@ -293,13 +302,13 @@
/// [Duration].
///
/// The returned [Duration] has the same length as this one, but is always
- /// positive.
+ /// positive where possible.
Duration abs() => Duration._microseconds(_duration.abs());
/// Creates a new [Duration] with the opposite direction of this [Duration].
///
/// The returned [Duration] has the same length as this one, but will have the
- /// opposite sign (as reported by [isNegative]) as this one.
+ /// opposite sign (as reported by [isNegative]) as this one where possible.
// Using subtraction helps dart2js avoid negative zeros.
Duration operator -() => Duration._microseconds(0 - _duration);
}
diff --git a/sdk/lib/core/iterable.dart b/sdk/lib/core/iterable.dart
index 2079afb..0b42ab7 100644
--- a/sdk/lib/core/iterable.dart
+++ b/sdk/lib/core/iterable.dart
@@ -412,12 +412,12 @@
return count;
}
- /// Returns `true` if there are no elements in this collection.
+ /// Whether this collection has no elements.
///
/// May be computed by checking if `iterator.moveNext()` returns `false`.
bool get isEmpty => !iterator.moveNext();
- /// Returns true if there is at least one element in this collection.
+ /// Whether this collection has at least one element.
///
/// May be computed by checking if `iterator.moveNext()` returns `true`.
bool get isNotEmpty => !isEmpty;
diff --git a/sdk/lib/core/pattern.dart b/sdk/lib/core/pattern.dart
index 94c8980..0926b5c 100644
--- a/sdk/lib/core/pattern.dart
+++ b/sdk/lib/core/pattern.dart
@@ -19,7 +19,7 @@
/// of the pattern in the string, initially starting from [start],
/// and then from the end of the previous match (but always
/// at least one position later than the *start* of the previous
- /// match, in case the patter matches an empty substring).
+ /// match, in case the pattern matches an empty substring).
Iterable<Match> allMatches(String string, [int start = 0]);
/// Matches this pattern against the start of `string`.
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index 2e3b2bd..3e2dd21 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -824,11 +824,11 @@
// Bootstrapping native for getting the FFI native C function pointer to look
// up the FFI resolver.
@pragma("vm:external-name", "Ffi_GetFfiNativeResolver")
-external Pointer<NativeFunction<IntPtr Function(Handle, Handle)>>
+external Pointer<NativeFunction<IntPtr Function(Handle, Handle, IntPtr)>>
_get_ffi_native_resolver<T extends NativeFunction>();
// Resolver for FFI Native C function pointers.
@pragma('vm:entry-point')
-final _ffi_resolver =
- _get_ffi_native_resolver<NativeFunction<IntPtr Function(Handle, Handle)>>()
- .asFunction<int Function(Object, Object)>();
+final _ffi_resolver = _get_ffi_native_resolver<
+ NativeFunction<IntPtr Function(Handle, Handle, IntPtr)>>()
+ .asFunction<int Function(Object, Object, int)>();
diff --git a/tests/corelib/duration_test.dart b/tests/corelib/duration_test.dart
index 842f4b0..1f8c543 100644
--- a/tests/corelib/duration_test.dart
+++ b/tests/corelib/duration_test.dart
@@ -281,6 +281,14 @@
d = const Duration(microseconds: 1000000);
Expect.equals("0:00:01.000000", d.toString());
+ // Regression test: Infinite loop prior to fix.
+ d = const Duration(microseconds: -0x8000000000000000);
+ Expect.equals("-2562047788:00:54.775808", d.toString());
+
+ d = const Duration(
+ hours: -2562047788, minutes: 0, seconds: -54, microseconds: -775808);
+ Expect.equals(-0x8000000000000000, d.inMicroseconds);
+
d1 = const Duration(hours: 1);
d2 = const Duration(hours: -1);
Expect.isFalse(d1.isNegative);
diff --git a/tests/corelib_2/duration_test.dart b/tests/corelib_2/duration_test.dart
index 09a5141..1e5c5a3 100644
--- a/tests/corelib_2/duration_test.dart
+++ b/tests/corelib_2/duration_test.dart
@@ -283,6 +283,14 @@
d = const Duration(microseconds: 1000000);
Expect.equals("0:00:01.000000", d.toString());
+ // Regression test: Infinite loop prior to fix.
+ d = const Duration(microseconds: -0x8000000000000000);
+ Expect.equals("-2562047788:00:54.775808", d.toString());
+
+ d = const Duration(
+ hours: -2562047788, minutes: 0, seconds: -54, microseconds: -775808);
+ Expect.equals(-0x8000000000000000, d.inMicroseconds);
+
d1 = const Duration(hours: 1);
d2 = const Duration(hours: -1);
Expect.isFalse(d1.isNegative);
diff --git a/tests/lib/html/js_interop_1_test.dart b/tests/lib/html/js_interop_1_test.dart
index 5f57dfb..cb9b6e8 100644
--- a/tests/lib/html/js_interop_1_test.dart
+++ b/tests/lib/html/js_interop_1_test.dart
@@ -27,6 +27,6 @@
});
injectSource("window.postMessage('hello', '*');");
- await completer;
+ await completer.future;
});
}
diff --git a/tests/lib_2/html/js_interop_1_test.dart b/tests/lib_2/html/js_interop_1_test.dart
index 95b280e..6057d80 100644
--- a/tests/lib_2/html/js_interop_1_test.dart
+++ b/tests/lib_2/html/js_interop_1_test.dart
@@ -29,6 +29,6 @@
});
injectSource("window.postMessage('hello', '*');");
- await completer;
+ await completer.future;
});
}
diff --git a/tools/VERSION b/tools/VERSION
index dded213..7a5c162 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 98
+PRERELEASE 99
PRERELEASE_PATCH 0
\ No newline at end of file