Version 2.15.0-212.0.dev
Merge commit '14428eda6940e0edab7f3810542ddcc049a569e2' into 'dev'
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
index fd178e1..939c8fc 100644
--- a/build/config/compiler/compiler.gni
+++ b/build/config/compiler/compiler.gni
@@ -10,4 +10,5 @@
build_with_chromium = false
use_libfuzzer = false
is_apple = is_ios || is_mac
+ use_thin_lto = false
}
diff --git a/pkg/analysis_server/lib/src/status/element_writer.dart b/pkg/analysis_server/lib/src/status/element_writer.dart
index dffcd49..bc09cd5 100644
--- a/pkg/analysis_server/lib/src/status/element_writer.dart
+++ b/pkg/analysis_server/lib/src/status/element_writer.dart
@@ -107,7 +107,6 @@
if (element is LibraryElement) {
properties['definingCompilationUnit'] = element.definingCompilationUnit;
properties['entryPoint'] = element.entryPoint;
- properties['hasExtUri'] = element.hasExtUri;
properties['isBrowserApplication'] = element.isBrowserApplication;
properties['isDartAsync'] = element.isDartAsync;
properties['isDartCore'] = element.isDartCore;
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 4663fa5..1a8d912 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,6 +1,7 @@
## 2.6.0-dev
* Deprecated `AnalysisResult.state`, check for specific valid or invalid subtypes.
* Deprecated `ResultState`.
+* Deprecated `LibraryElement.hasExtUri`, FFI should be used instead.
## 2.5.0
* Updated `MockSdk` to include more declarations.
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 7dc7476..362575d 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -479,6 +479,8 @@
R? visitImplementsClause(ImplementsClause node);
+ R? visitImplicitCallReference(ImplicitCallReference node);
+
R? visitImportDirective(ImportDirective node);
R? visitIndexExpression(IndexExpression node);
@@ -2599,6 +2601,33 @@
NodeList<NamedType> get interfaces2;
}
+/// An expression representing an implicit 'call' method reference.
+///
+/// Objects of this type are not produced directly by the parser (because the
+/// parser cannot tell whether an expression refers to a callable type); they
+/// are produced at resolution time.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ImplicitCallReference implements MethodReferenceExpression {
+ /// Return the expression from which a `call` method is being referenced.
+ Expression get expression;
+
+ /// Return the element associated with the implicit 'call' reference based on
+ /// the static types.
+ @override
+ MethodElement get staticElement;
+
+ /// The type arguments being applied to the tear-off, or `null` if there are
+ /// no type arguments.
+ TypeArgumentList? get typeArguments;
+
+ /// The actual type arguments being applied to the tear-off, either explicitly
+ /// specified in [typeArguments], or inferred.
+ ///
+ /// Returns an empty list if the 'call' method does not have type parameters.
+ List<DartType> get typeArgumentTypes;
+}
+
/// An import directive.
///
/// importDirective ::=
diff --git a/pkg/analyzer/lib/dart/ast/ast_factory.dart b/pkg/analyzer/lib/dart/ast/ast_factory.dart
index 64d8fb4..baa41a5 100644
--- a/pkg/analyzer/lib/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/dart/ast/ast_factory.dart
@@ -5,6 +5,8 @@
import 'package:_fe_analyzer_shared/src/scanner/token.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
/// A collection of factory methods which may be used to create concrete
@@ -580,6 +582,17 @@
ImplementsClause implementsClause(
Token implementsKeyword, List<NamedType> interfaces);
+ /// Returns a newly created implicit call reference.
+ ///
+ /// The [typeArguments] can be `null` if there are no type arguments being
+ /// applied to the reference.
+ ImplicitCallReference implicitCallReference({
+ required Expression expression,
+ required MethodElement staticElement,
+ required TypeArgumentList? typeArguments,
+ required List<DartType> typeArgumentTypes,
+ });
+
/// Returns a newly created import directive. Either or both of the
/// [comment] and [metadata] can be `null` if the function does not have the
/// corresponding attribute. The [deferredKeyword] can be `null` if the import
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
index 451f318..5d3dda9 100644
--- a/pkg/analyzer/lib/dart/ast/visitor.dart
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -383,6 +383,9 @@
R? visitImplementsClause(ImplementsClause node) => visitNode(node);
@override
+ R? visitImplicitCallReference(ImplicitCallReference node) => visitNode(node);
+
+ @override
R? visitImportDirective(ImportDirective node) =>
visitNamespaceDirective(node);
@@ -1035,6 +1038,12 @@
}
@override
+ R? visitImplicitCallReference(ImplicitCallReference node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
R? visitImportDirective(ImportDirective node) {
node.visitChildren(this);
return null;
@@ -1624,6 +1633,9 @@
R? visitImplementsClause(ImplementsClause node) => null;
@override
+ R? visitImplicitCallReference(ImplicitCallReference node) => null;
+
+ @override
R? visitImportDirective(ImportDirective node) => null;
@override
@@ -2032,6 +2044,9 @@
R? visitImplementsClause(ImplementsClause node) => _throw(node);
@override
+ R? visitImplicitCallReference(ImplicitCallReference node) => _throw(node);
+
+ @override
R? visitImportDirective(ImportDirective node) => _throw(node);
@override
@@ -2769,6 +2784,14 @@
}
@override
+ T? visitImplicitCallReference(ImplicitCallReference node) {
+ stopwatch.start();
+ T? result = _baseVisitor.visitImplicitCallReference(node);
+ stopwatch.stop();
+ return result;
+ }
+
+ @override
T? visitImportDirective(ImportDirective node) {
stopwatch.start();
T? result = _baseVisitor.visitImportDirective(node);
@@ -3498,6 +3521,9 @@
R? visitImplementsClause(ImplementsClause node) => visitNode(node);
@override
+ R? visitImplicitCallReference(ImplicitCallReference node) => visitNode(node);
+
+ @override
R? visitImportDirective(ImportDirective node) => visitNode(node);
@override
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index f34732b..43cc3b1 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1331,6 +1331,7 @@
/// Return `true` if the defining compilation unit of this library contains at
/// least one import directive whose URI uses the "dart-ext" scheme.
+ @Deprecated('Support for dart-ext is replaced with FFI')
bool get hasExtUri;
/// Return `true` if this library defines a top-level function named
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 311591d..1871a08 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -457,6 +457,7 @@
CompileTimeErrorCode.URI_DOES_NOT_EXIST,
CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED,
CompileTimeErrorCode.URI_WITH_INTERPOLATION,
+ CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
CompileTimeErrorCode.USE_OF_VOID_RESULT,
CompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
CompileTimeErrorCode.WRONG_EXPLICIT_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
@@ -640,7 +641,6 @@
HintCode.UNUSED_RESULT,
HintCode.UNUSED_RESULT_WITH_MESSAGE,
HintCode.UNUSED_SHOWN_NAME,
- HintCode.USE_OF_NATIVE_EXTENSION,
LanguageCode.IMPLICIT_DYNAMIC_FIELD,
LanguageCode.IMPLICIT_DYNAMIC_FUNCTION,
LanguageCode.IMPLICIT_DYNAMIC_INVOKE,
diff --git a/pkg/analyzer/lib/src/dart/analysis/byte_store.dart b/pkg/analyzer/lib/src/dart/analysis/byte_store.dart
index 740ddc2..7fa38f7 100644
--- a/pkg/analyzer/lib/src/dart/analysis/byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/byte_store.dart
@@ -2,6 +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 'dart:typed_data';
+
import 'package:analyzer/src/dart/analysis/cache.dart';
/// Store of bytes associated with string keys.
@@ -17,23 +19,23 @@
abstract class ByteStore {
/// Return the bytes associated with the given [key].
/// Return `null` if the association does not exist.
- List<int>? get(String key);
+ Uint8List? get(String key);
/// Associate the given [bytes] with the [key].
- void put(String key, List<int> bytes);
+ void put(String key, Uint8List bytes);
}
/// [ByteStore] which stores data only in memory.
class MemoryByteStore implements ByteStore {
- final Map<String, List<int>> _map = {};
+ final Map<String, Uint8List> _map = {};
@override
- List<int>? get(String key) {
+ Uint8List? get(String key) {
return _map[key];
}
@override
- void put(String key, List<int> bytes) {
+ void put(String key, Uint8List bytes) {
_map[key] = bytes;
}
}
@@ -41,18 +43,18 @@
/// A wrapper around [ByteStore] which adds an in-memory LRU cache to it.
class MemoryCachingByteStore implements ByteStore {
final ByteStore _store;
- final Cache<String, List<int>> _cache;
+ final Cache<String, Uint8List> _cache;
MemoryCachingByteStore(this._store, int maxSizeBytes)
- : _cache = Cache<String, List<int>>(maxSizeBytes, (v) => v.length);
+ : _cache = Cache<String, Uint8List>(maxSizeBytes, (v) => v.length);
@override
- List<int>? get(String key) {
+ Uint8List? get(String key) {
return _cache.get(key, () => _store.get(key));
}
@override
- void put(String key, List<int> bytes) {
+ void put(String key, Uint8List bytes) {
_store.put(key, bytes);
_cache.put(key, bytes);
}
@@ -61,8 +63,8 @@
/// [ByteStore] which does not store any data.
class NullByteStore implements ByteStore {
@override
- List<int>? get(String key) => null;
+ Uint8List? get(String key) => null;
@override
- void put(String key, List<int> bytes) {}
+ void put(String key, Uint8List bytes) {}
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 0d71dc5..aba8fef 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -80,7 +80,7 @@
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
- static const int DATA_VERSION = 185;
+ static const int DATA_VERSION = 186;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
@@ -1318,7 +1318,7 @@
late CompilationUnit resolvedUnit;
for (FileState unitFile in results.keys) {
UnitAnalysisResult unitResult = results[unitFile]!;
- List<int> unitBytes =
+ var unitBytes =
_serializeResolvedUnit(unitResult.unit, unitResult.errors);
String unitSignature = _getResolvedUnitSignature(library, unitFile);
String unitKey = _getResolvedUnitKey(unitSignature);
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart b/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
index d4d3e04..58f154e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
@@ -41,10 +41,10 @@
}
@override
- List<int>? get(String key) => _fileByteStore.get(key);
+ Uint8List? get(String key) => _fileByteStore.get(key);
@override
- void put(String key, List<int> bytes) {
+ void put(String key, Uint8List bytes) {
_fileByteStore.put(key, bytes);
// Update the current size.
_bytesWrittenSinceCleanup += bytes.length;
@@ -146,7 +146,7 @@
final String _cachePath;
final String _tempSuffix;
- final Map<String, List<int>> _writeInProgress = {};
+ final Map<String, Uint8List> _writeInProgress = {};
final FuturePool _pool = FuturePool(20);
/// If the same cache path is used from more than one isolate of the same
@@ -156,7 +156,7 @@
'-temp-$pid${tempNameSuffix.isEmpty ? '' : '-$tempNameSuffix'}';
@override
- List<int>? get(String key) {
+ Uint8List? get(String key) {
if (!_canShard(key)) return null;
var bytes = _writeInProgress[key];
@@ -176,7 +176,7 @@
}
@override
- void put(String key, List<int> bytes) {
+ void put(String key, Uint8List bytes) {
if (!_canShard(key)) return;
_writeInProgress[key] = bytes;
@@ -225,7 +225,7 @@
/// If the [rawBytes] have the valid version and checksum, extract and
/// return the data from it. Otherwise return `null`.
- List<int>? getData(List<int> rawBytes) {
+ Uint8List? getData(Uint8List rawBytes) {
// There must be at least the version and the checksum in the raw bytes.
if (rawBytes.length < 4) {
return null;
@@ -238,7 +238,7 @@
}
// Check the checksum of the data.
- List<int> data = rawBytes.sublist(0, len);
+ var data = rawBytes.sublist(0, len);
int checksum = fletcher16(data);
if (rawBytes[len + 2] != checksum & 0xFF ||
rawBytes[len + 3] != (checksum >> 8) & 0xFF) {
@@ -251,7 +251,7 @@
/// Return bytes that include the given [data] plus the current version and
/// the checksum of the [data].
- List<int> wrapData(List<int> data) {
+ Uint8List wrapData(Uint8List data) {
int len = data.length;
var bytes = Uint8List(len + 4);
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index d44f37d..239d1cb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -341,7 +341,7 @@
}
Uint8List getInformativeBytes({CompilationUnit? unit}) {
- var bytes = _fsState._byteStore.get(_informativeKey!) as Uint8List?;
+ var bytes = _fsState._byteStore.get(_informativeKey!);
if (bytes == null) {
unit ??= parse();
bytes = writeUnitInformative(unit);
@@ -404,11 +404,8 @@
_informativeKey = '$signatureHex.ast';
}
- // Prepare bytes of the unlinked bundle - existing or new.
- var bytes = _getUnlinkedBytes();
-
- // Read the unlinked bundle.
- _driverUnlinkedUnit = AnalysisDriverUnlinkedUnit.fromBytes(bytes);
+ // Prepare the unlinked unit.
+ _driverUnlinkedUnit = _getUnlinkedUnit();
_unlinked2 = _driverUnlinkedUnit!.unit;
_lineInfo = LineInfo(_unlinked2!.lineStarts);
@@ -493,11 +490,11 @@
return _fsState.getFileForUri(absoluteUri);
}
- /// Return the bytes of the unlinked summary - existing or new.
- Uint8List _getUnlinkedBytes() {
+ /// Return the unlinked unit, from bytes or new.
+ AnalysisDriverUnlinkedUnit _getUnlinkedUnit() {
var bytes = _fsState._byteStore.get(_unlinkedKey!);
if (bytes != null && bytes.isNotEmpty) {
- return bytes as Uint8List;
+ return AnalysisDriverUnlinkedUnit.fromBytes(bytes);
}
var unit = parse();
@@ -506,17 +503,18 @@
var definedNames = computeDefinedNames(unit);
var referencedNames = computeReferencedNames(unit);
var subtypedNames = computeSubtypedNames(unit);
- var bytes = AnalysisDriverUnlinkedUnit(
+ var driverUnlinkedUnit = AnalysisDriverUnlinkedUnit(
definedTopLevelNames: definedNames.topLevelNames,
definedClassMemberNames: definedNames.classMemberNames,
referencedNames: referencedNames,
subtypedNames: subtypedNames,
unit: unlinkedUnit,
- ).toBytes();
+ );
+ var bytes = driverUnlinkedUnit.toBytes();
_fsState._byteStore.put(_unlinkedKey!, bytes);
counterUnlinkedBytes += bytes.length;
counterUnlinkedLinkedBytes += bytes.length;
- return bytes;
+ return driverUnlinkedUnit;
});
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 04235d9..6278c6f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -532,10 +532,14 @@
var importedLibrary = importElement.importedLibrary;
if (importedLibrary is LibraryElementImpl) {
if (importedLibrary.hasPartOfDirective) {
+ // It is safe to assume that `directive.uri.stringValue` is
+ // non-`null`, because the only time it is `null` is if the URI
+ // contains a string interpolation, in which case the import
+ // would never have resolved in the first place.
libraryErrorReporter.reportErrorForNode(
CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY,
directive.uri,
- [directive.uri]);
+ [directive.uri.stringValue!]);
}
}
}
@@ -547,10 +551,14 @@
var exportedLibrary = exportElement.exportedLibrary;
if (exportedLibrary is LibraryElementImpl) {
if (exportedLibrary.hasPartOfDirective) {
+ // It is safe to assume that `directive.uri.stringValue` is
+ // non-`null`, because the only time it is `null` is if the URI
+ // contains a string interpolation, in which case the export
+ // would never have resolved in the first place.
libraryErrorReporter.reportErrorForNode(
CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
directive.uri,
- [directive.uri]);
+ [directive.uri.stringValue!]);
}
}
}
@@ -696,8 +704,6 @@
return null;
}
return _sourceFactory.resolveUri(file.source, uriContent);
- } else if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
- return null;
} else if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
_getErrorReporter(file).reportErrorForNode(
CompileTimeErrorCode.URI_WITH_INTERPOLATION, uriLiteral);
@@ -783,13 +789,21 @@
return;
}
}
- StringLiteral uriLiteral = directive.uri;
+
+ if (uriContent != null && uriContent.startsWith('dart-ext:')) {
+ _getErrorReporter(file).reportErrorForNode(
+ CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
+ directive.uri,
+ );
+ return;
+ }
+
CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
if (isGeneratedSource(source)) {
errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
}
_getErrorReporter(file)
- .reportErrorForNode(errorCode, uriLiteral, [uriContent]);
+ .reportErrorForNode(errorCode, directive.uri, [uriContent]);
}
/// Check each directive in the given [unit] to see if the referenced source
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index dbc60bd..7973df8 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -122,7 +122,7 @@
}
var resolutionKey = cycle.transitiveSignature + '.linked_bundle';
- var resolutionBytes = byteStore.get(resolutionKey) as Uint8List?;
+ var resolutionBytes = byteStore.get(resolutionKey);
if (resolutionBytes == null) {
librariesLinkedTimer.start();
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 38a93cf..d9d000b 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -5803,6 +5803,69 @@
}
}
+class ImplicitCallReferenceImpl extends ExpressionImpl
+ implements ImplicitCallReference {
+ ExpressionImpl _expression;
+
+ TypeArgumentListImpl? _typeArguments;
+
+ @override
+ List<DartType> typeArgumentTypes;
+
+ @override
+ MethodElement staticElement;
+
+ ImplicitCallReferenceImpl(
+ this._expression, {
+ required this.staticElement,
+ required TypeArgumentListImpl? typeArguments,
+ required this.typeArgumentTypes,
+ }) : _typeArguments = typeArguments {
+ _becomeParentOf(_expression);
+ _becomeParentOf(_typeArguments);
+ }
+
+ @override
+ Token get beginToken => expression.beginToken;
+
+ @override
+ Iterable<SyntacticEntity> get childEntities => ChildEntities()
+ ..add(expression)
+ ..add(typeArguments);
+
+ @override
+ Token get endToken => typeArguments?.endToken ?? expression.endToken;
+
+ @override
+ ExpressionImpl get expression => _expression;
+
+ set expression(ExpressionImpl value) {
+ _expression = _becomeParentOf(value);
+ }
+
+ @override
+ Precedence get precedence =>
+ typeArguments == null ? expression.precedence : Precedence.postfix;
+
+ @override
+ TypeArgumentListImpl? get typeArguments => _typeArguments;
+
+ set typeArguments(TypeArgumentListImpl? value) {
+ _typeArguments = _becomeParentOf(value);
+ }
+
+ @override
+ E? accept<E>(AstVisitor<E> visitor) {
+ return visitor.visitImplicitCallReference(this);
+ }
+
+ @override
+ void visitChildren(AstVisitor visitor) {
+ expression.accept(visitor);
+ typeArguments?.accept(visitor);
+ }
+}
+
/// An import directive.
///
/// importDirective ::=
@@ -10466,10 +10529,6 @@
/// | [PartDirective]
abstract class UriBasedDirectiveImpl extends DirectiveImpl
implements UriBasedDirective {
- /// The prefix of a URI using the `dart-ext` scheme to reference a native code
- /// library.
- static const String _DART_EXT_SCHEME = "dart-ext:";
-
/// The URI referenced by this directive.
StringLiteralImpl _uri;
@@ -10518,9 +10577,6 @@
if (uriContent.isEmpty) {
return null;
}
- if (isImport && uriContent.startsWith(_DART_EXT_SCHEME)) {
- return UriValidationCode.URI_WITH_DART_EXT_SCHEME;
- }
Uri uri;
try {
uri = Uri.parse(Uri.encodeFull(uriContent));
@@ -10541,9 +10597,6 @@
static const UriValidationCode URI_WITH_INTERPOLATION =
UriValidationCode('URI_WITH_INTERPOLATION');
- static const UriValidationCode URI_WITH_DART_EXT_SCHEME =
- UriValidationCode('URI_WITH_DART_EXT_SCHEME');
-
/// The name of the validation code.
final String name;
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index 0fcad99..f9e04f4 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -6,6 +6,8 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/ast_factory.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -786,6 +788,18 @@
ImplementsClauseImpl(implementsKeyword, interfaces);
@override
+ ImplicitCallReferenceImpl implicitCallReference({
+ required Expression expression,
+ required MethodElement staticElement,
+ required TypeArgumentList? typeArguments,
+ required List<DartType> typeArgumentTypes,
+ }) =>
+ ImplicitCallReferenceImpl(expression as ExpressionImpl,
+ staticElement: staticElement,
+ typeArguments: typeArguments as TypeArgumentListImpl?,
+ typeArgumentTypes: typeArgumentTypes);
+
+ @override
ImportDirectiveImpl importDirective(
Comment? comment,
List<Annotation>? metadata,
diff --git a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
index b912645..c32bd06 100644
--- a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
@@ -604,6 +604,12 @@
}
@override
+ void visitImplicitCallReference(ImplicitCallReference node) {
+ _visitNode(node.expression);
+ _visitNode(node.typeArguments);
+ }
+
+ @override
void visitImportDirective(ImportDirective node) {
_visitNodeList(node.metadata, separator: ' ', suffix: ' ');
sink.write('import ');
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 11c386e..6e2918a 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -723,6 +723,13 @@
}
@override
+ bool visitImplicitCallReference(ImplicitCallReference node) {
+ ImplicitCallReference other = _other as ImplicitCallReference;
+ return isEqualNodes(node.expression, other.expression) &&
+ isEqualNodes(node.typeArguments, other.typeArguments);
+ }
+
+ @override
bool visitImportDirective(ImportDirective node) {
ImportDirective other = _other as ImportDirective;
return isEqualNodes(
@@ -2345,6 +2352,18 @@
}
@override
+ bool visitImplicitCallReference(covariant ImplicitCallReferenceImpl node) {
+ if (identical(node.expression, _oldNode)) {
+ node.expression = _newNode as ExpressionImpl;
+ return true;
+ } else if (identical(node.typeArguments, _oldNode)) {
+ node.typeArguments = _newNode as TypeArgumentListImpl;
+ return true;
+ }
+ return visitNode(node);
+ }
+
+ @override
bool visitImportDirective(covariant ImportDirectiveImpl node) {
if (identical(node.prefix, _oldNode)) {
node.prefix = _newNode as SimpleIdentifier;
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 4a5e452..34df7af 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -171,6 +171,7 @@
_evaluationEngine.evaluateConstructorCall(
_currentLibrary,
node,
+ constructor.returnType.typeArguments,
node.argumentList.arguments,
constructor,
constantVisitor,
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 3c30694..54d5c5d 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -4,6 +4,7 @@
import 'dart:collection';
+import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
@@ -141,6 +142,7 @@
var result = evaluateConstructorCall(
library,
constNode,
+ element.returnType.typeArguments,
constNode.arguments!.arguments,
element,
constantVisitor,
@@ -272,15 +274,26 @@
DartObjectImpl? evaluateConstructorCall(
LibraryElementImpl library,
AstNode node,
+ List<DartType>? typeArguments,
List<Expression> arguments,
ConstructorElement constructor,
ConstantVisitor constantVisitor,
ErrorReporter errorReporter, {
ConstructorInvocation? invocation,
}) {
- return _InstanceCreationEvaluator.evaluate(this, _declaredVariables,
- errorReporter, library, node, constructor, arguments, constantVisitor,
- isNullSafe: _isNonNullableByDefault, invocation: invocation);
+ return _InstanceCreationEvaluator.evaluate(
+ this,
+ _declaredVariables,
+ errorReporter,
+ library,
+ node,
+ constructor,
+ typeArguments,
+ arguments,
+ constantVisitor,
+ isNullSafe: _isNonNullableByDefault,
+ invocation: invocation,
+ );
}
/// Generate an error indicating that the given [constant] is not a valid
@@ -430,7 +443,12 @@
/// The library that contains the constant expression being evaluated.
final LibraryElementImpl _library;
+ /// A mapping of variable names to runtime values.
final Map<String, DartObjectImpl>? _lexicalEnvironment;
+
+ /// A mapping of type parameter names to runtime values (types).
+ final Map<String, DartType>? _lexicalTypeEnvironment;
+
final Substitution? _substitution;
/// Error reporter that we use to report errors accumulated while computing
@@ -453,8 +471,10 @@
this._library,
this._errorReporter, {
Map<String, DartObjectImpl>? lexicalEnvironment,
+ Map<String, DartType>? lexicalTypeEnvironment,
Substitution? substitution,
}) : _lexicalEnvironment = lexicalEnvironment,
+ _lexicalTypeEnvironment = lexicalTypeEnvironment,
_substitution = substitution {
_dartObjectComputer = DartObjectComputer(
typeSystem,
@@ -705,8 +725,15 @@
return null;
}
- return evaluationEngine.evaluateConstructorCall(_library, node,
- node.argumentList.arguments, constructor, this, _errorReporter);
+ return evaluationEngine.evaluateConstructorCall(
+ _library,
+ node,
+ constructor.returnType.typeArguments,
+ node.argumentList.arguments,
+ constructor,
+ this,
+ _errorReporter,
+ );
}
@override
@@ -1253,7 +1280,18 @@
TypeState(_typeProvider.neverType),
);
} else if (variableElement is TypeParameterElement) {
- // Constants may not refer to type parameters.
+ // Constants may refer to type parameters only if the constructor-tearoffs
+ // feature is enabled.
+ if (_library.featureSet.isEnabled(Feature.constructor_tearoffs)) {
+ var typeArgument = _lexicalTypeEnvironment?[identifier.name];
+ if (typeArgument != null) {
+ return DartObjectImpl(
+ typeSystem,
+ _typeProvider.typeType,
+ TypeState(typeArgument),
+ );
+ }
+ }
}
// TODO(https://github.com/dart-lang/sdk/issues/47061): Use a specific
@@ -1926,13 +1964,17 @@
_constructor.library as LibraryElementImpl,
_externalErrorReporter,
lexicalEnvironment: _parameterMap,
+ lexicalTypeEnvironment: _typeParameterMap,
substitution: Substitution.fromInterfaceType(definingType),
);
- final AstNode _node;
+ /// The node used for most error reporting.
+ final AstNode _errorNode;
final ConstructorElement _constructor;
+ final List<DartType>? _typeArguments;
+
final ConstructorInvocation _invocation;
final Map<String, NamedExpression> _namedNodes;
@@ -1941,17 +1983,25 @@
final List<DartObjectImpl> _argumentValues;
+ final Map<String, DartType> _typeParameterMap = HashMap();
+
final Map<String, DartObjectImpl> _parameterMap = HashMap();
final Map<String, DartObjectImpl> _fieldMap = HashMap();
- _InstanceCreationEvaluator.generative(
+ /// Constructor for [_InstanceCreationEvaluator].
+ ///
+ /// This constructor is private, as the entry point for using a
+ /// [_InstanceCreationEvaluator] is the static method,
+ /// [_InstanceCreationEvaluator.evaluate].
+ _InstanceCreationEvaluator._(
this._evaluationEngine,
this._declaredVariables,
this._errorReporter,
this._library,
- this._node,
- this._constructor, {
+ this._errorNode,
+ this._constructor,
+ this._typeArguments, {
required Map<String, NamedExpression> namedNodes,
required Map<String, DartObjectImpl> namedValues,
required List<DartObjectImpl> argumentValues,
@@ -1979,7 +2029,7 @@
if (_constructor.name == "fromEnvironment") {
if (!_checkFromEnvironmentArguments(arguments, definingType)) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
return null;
}
String? variableName =
@@ -2004,7 +2054,7 @@
argumentCount == 1) {
if (!_checkSymbolArguments(arguments, isNullSafe: isNullSafe)) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
return null;
}
return DartObjectImpl(
@@ -2028,6 +2078,7 @@
// Start with final fields that are initialized at their declaration site.
_checkFields();
+ _checkTypeParameters();
_checkParameters(arguments);
var evaluationResult = _checkInitializers();
if (evaluationResult.evaluationIsComplete) {
@@ -2038,7 +2089,7 @@
superArguments: evaluationResult.superArguments);
if (_externalErrorListener.errorReported) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
}
return DartObjectImpl(
typeSystem,
@@ -2049,8 +2100,7 @@
void _checkFields() {
var fields = _constructor.enclosingElement.fields;
- for (var i = 0; i < fields.length; i++) {
- var field = fields[i];
+ for (var field in fields) {
if ((field.isFinal || field.isConst) &&
!field.isStatic &&
field is ConstFieldElementImpl) {
@@ -2067,7 +2117,7 @@
if (!typeSystem.runtimeTypeMatch(fieldValue, fieldType)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
- _node,
+ _errorNode,
[fieldValue.type, field.name, fieldType]);
}
_fieldMap[field.name] = fieldValue;
@@ -2130,7 +2180,7 @@
var fieldName = initializer.fieldName.name;
if (_fieldMap.containsKey(fieldName)) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
}
_fieldMap[fieldName] = evaluationResult;
var getter = definingType.getGetter(fieldName);
@@ -2139,13 +2189,13 @@
if (!typeSystem.runtimeTypeMatch(evaluationResult, field.type)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
- _node,
+ _errorNode,
[evaluationResult.type, fieldName, field.type]);
}
}
} else {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
}
} else if (initializer is SuperConstructorInvocation) {
var name = initializer.constructorName;
@@ -2162,7 +2212,8 @@
constructor = ConstructorMember.from(constructor, definingType);
var result = _evaluationEngine.evaluateConstructorCall(
_library,
- _node,
+ _errorNode,
+ _typeArguments,
initializer.argumentList.arguments,
constructor,
_initializerVisitor,
@@ -2170,7 +2221,7 @@
invocation: _invocation);
if (_externalErrorListener.errorReported) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
}
return _InitializersEvaluationResult(result,
evaluationIsComplete: true);
@@ -2182,7 +2233,7 @@
!evaluationResult.isBool ||
evaluationResult.toBoolValue() == false) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
return _InitializersEvaluationResult(null,
evaluationIsComplete: true);
}
@@ -2213,7 +2264,7 @@
// No argument node that we can direct error messages to, because we
// are handling an optional parameter that wasn't specified. So just
// direct error messages to the constructor call.
- errorTarget ??= _node;
+ errorTarget ??= _errorNode;
if (argumentValue == null && baseParameter is ParameterElementImpl) {
// The parameter is an optional positional parameter for which no value
// was provided, so use the default value.
@@ -2252,7 +2303,7 @@
var fieldName = field.name;
if (_fieldMap.containsKey(fieldName)) {
_errorReporter.reportErrorForNode(
- CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _node);
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, _errorNode);
}
_fieldMap[fieldName] = argumentValue;
}
@@ -2288,8 +2339,9 @@
if (superConstructor.isConst) {
var evaluationResult = _evaluationEngine.evaluateConstructorCall(
_library,
- _node,
- superArguments ?? astFactory.nodeList(_node),
+ _errorNode,
+ superclass.typeArguments,
+ superArguments ?? astFactory.nodeList(_errorNode),
superConstructor,
_initializerVisitor,
_externalErrorReporter,
@@ -2328,6 +2380,20 @@
return _isValidPublicSymbol(name);
}
+ void _checkTypeParameters() {
+ var typeParameters = _constructor.enclosingElement.typeParameters;
+ var typeArguments = _typeArguments;
+ if (typeParameters.isNotEmpty &&
+ typeArguments != null &&
+ typeParameters.length == typeArguments.length) {
+ for (int i = 0; i < typeParameters.length; i++) {
+ var typeParameter = typeParameters[i];
+ var typeArgument = typeArguments[i];
+ _typeParameterMap[typeParameter.name] = typeArgument;
+ }
+ }
+ }
+
/// Evaluates [node] as an instance creation expression using [constructor].
static DartObjectImpl? evaluate(
ConstantEvaluationEngine evaluationEngine,
@@ -2336,6 +2402,7 @@
LibraryElementImpl library,
AstNode node,
ConstructorElement constructor,
+ List<DartType>? typeArguments,
List<Expression> arguments,
ConstantVisitor constantVisitor, {
required bool isNullSafe,
@@ -2386,13 +2453,14 @@
constructor = _followConstantRedirectionChain(constructor);
- var evaluator = _InstanceCreationEvaluator.generative(
+ var evaluator = _InstanceCreationEvaluator._(
evaluationEngine,
declaredVariables,
errorReporter,
library,
node,
constructor,
+ typeArguments,
namedNodes: namedNodes,
namedValues: namedValues,
argumentValues: argumentValues,
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index f1b79a3..541f9db 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3786,15 +3786,9 @@
return _exports;
}
+ @Deprecated('Support for dart-ext is replaced with FFI')
@override
- bool get hasExtUri {
- return hasModifier(Modifier.HAS_EXT_URI);
- }
-
- /// Set whether this library has an import of a "dart-ext" URI.
- set hasExtUri(bool hasExtUri) {
- setModifier(Modifier.HAS_EXT_URI, hasExtUri);
- }
+ bool get hasExtUri => false;
@Deprecated('Not useful for clients')
@override
@@ -4354,47 +4348,42 @@
/// Indicates that the pseudo-modifier 'get' was applied to the element.
static const Modifier GETTER = Modifier('GETTER', 11);
- /// A flag used for libraries indicating that the defining compilation unit
- /// contains at least one import directive whose URI uses the "dart-ext"
- /// scheme.
- static const Modifier HAS_EXT_URI = Modifier('HAS_EXT_URI', 12);
-
/// A flag used for libraries indicating that the variable has an explicit
/// initializer.
- static const Modifier HAS_INITIALIZER = Modifier('HAS_INITIALIZER', 13);
+ static const Modifier HAS_INITIALIZER = Modifier('HAS_INITIALIZER', 12);
/// A flag used for fields and top-level variables that have implicit type,
/// and specify when the type has been inferred.
- static const Modifier HAS_TYPE_INFERRED = Modifier('HAS_TYPE_INFERRED', 14);
+ static const Modifier HAS_TYPE_INFERRED = Modifier('HAS_TYPE_INFERRED', 13);
/// A flag used for libraries indicating that the defining compilation unit
/// has a `part of` directive, meaning that this unit should be a part,
/// but is used as a library.
static const Modifier HAS_PART_OF_DIRECTIVE =
- Modifier('HAS_PART_OF_DIRECTIVE', 15);
+ Modifier('HAS_PART_OF_DIRECTIVE', 14);
/// Indicates that the associated element did not have an explicit type
/// associated with it. If the element is an [ExecutableElement], then the
/// type being referred to is the return type.
- static const Modifier IMPLICIT_TYPE = Modifier('IMPLICIT_TYPE', 16);
+ static const Modifier IMPLICIT_TYPE = Modifier('IMPLICIT_TYPE', 15);
/// Indicates that modifier 'lazy' was applied to the element.
- static const Modifier LATE = Modifier('LATE', 17);
+ static const Modifier LATE = Modifier('LATE', 16);
/// Indicates that a class is a mixin application.
- static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 18);
+ static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 17);
/// Indicates that the pseudo-modifier 'set' was applied to the element.
- static const Modifier SETTER = Modifier('SETTER', 19);
+ static const Modifier SETTER = Modifier('SETTER', 18);
/// Indicates that the modifier 'static' was applied to the element.
- static const Modifier STATIC = Modifier('STATIC', 20);
+ static const Modifier STATIC = Modifier('STATIC', 19);
/// Indicates that the element does not appear in the source code but was
/// implicitly created. For example, if a class does not define any
/// constructors, an implicit zero-argument constructor will be created and it
/// will be marked as being synthetic.
- static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 21);
+ static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 20);
static const List<Modifier> values = [
ABSTRACT,
@@ -4409,7 +4398,6 @@
FINAL,
GENERATOR,
GETTER,
- HAS_EXT_URI,
HAS_INITIALIZER,
HAS_PART_OF_DIRECTIVE,
IMPLICIT_TYPE,
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
index 12bbdcc..3406875 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.g.dart
@@ -3866,35 +3866,6 @@
hasPublishedDocs: true,
);
- /**
- * No parameters.
- */
- // #### Description
- //
- // The analyzer produces this diagnostic when a library is imported using the
- // `dart-ext` scheme.
- //
- // #### Example
- //
- // The following code produces this diagnostic because the native library `x`
- // is being imported using a scheme of `dart-ext`:
- //
- // ```dart
- // [!import 'dart-ext:x';!]
- // int f() native 'string';
- // ```
- //
- // #### Common fixes
- //
- // Rewrite the code to use `dart:ffi` as a way of invoking the contents of the
- // native library.
- static const HintCode USE_OF_NATIVE_EXTENSION = HintCode(
- 'USE_OF_NATIVE_EXTENSION',
- "Dart native extensions are deprecated and aren’t available in Dart 2.15.",
- correctionMessage: "Try using dart:ffi for C interop.",
- hasPublishedDocs: true,
- );
-
/// Initialize a newly created error code to have the given [name].
const HintCode(
String name,
diff --git a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
index fc56800..dc78189 100644
--- a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
@@ -2,12 +2,14 @@
// 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:typed_data';
+
import 'package:analyzer/src/dart/analysis/cache.dart';
import 'package:collection/collection.dart';
class CacheData {
final int id;
- final List<int> bytes;
+ final Uint8List bytes;
CacheData(this.id, this.bytes);
}
@@ -25,11 +27,11 @@
/// [signature].
///
/// Return `null` if the association does not exist.
- CacheData? get(String key, List<int> signature);
+ CacheData? get(String key, Uint8List signature);
/// Associate the given [bytes] with the [key] and [signature]. Return the
/// [CacheData].
- CacheData putGet(String key, List<int> signature, List<int> bytes);
+ CacheData putGet(String key, Uint8List signature, Uint8List bytes);
/// Used to decrement reference count for the given ids, if implemented.
void release(Iterable<int> ids);
@@ -51,7 +53,7 @@
maxCacheSize, (v) => v.data.bytes.length);
@override
- CacheData? get(String key, List<int> signature) {
+ CacheData? get(String key, Uint8List signature) {
var entry = _cache.get(key, () => null);
if (entry != null &&
@@ -62,7 +64,7 @@
}
@override
- CacheData putGet(String key, List<int> signature, List<int> bytes) {
+ CacheData putGet(String key, Uint8List signature, Uint8List bytes) {
idCounter++;
var entry = CiderCacheEntry(signature, CacheData(idCounter, bytes));
_cache.put(key, entry);
@@ -78,7 +80,7 @@
class CiderCacheEntry {
final CacheData data;
- final List<int> signature;
+ final Uint8List signature;
CiderCacheEntry(this.signature, this.data);
}
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index 1fa7152..30be965 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -565,9 +565,13 @@
directive.prefix?.staticElement = importElement.prefix;
var source = importElement.importedLibrary?.source;
if (source != null && !_isLibrarySource(source)) {
+ // It is safe to assume that `directive.uri.stringValue` is
+ // non-`null`, because the only time it is `null` is if the URI
+ // contains a string interpolation, in which case the import
+ // would never have resolved in the first place.
ErrorCode errorCode = CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY;
libraryErrorReporter.reportErrorForNode(
- errorCode, directive.uri, [directive.uri]);
+ errorCode, directive.uri, [directive.uri.stringValue!]);
}
}
}
@@ -577,10 +581,14 @@
directive.element = exportElement;
var source = exportElement.exportedLibrary?.source;
if (source != null && !_isLibrarySource(source)) {
+ // It is safe to assume that `directive.uri.stringValue` is
+ // non-`null`, because the only time it is `null` is if the URI
+ // contains a string interpolation, in which case the export
+ // would never have resolved in the first place.
libraryErrorReporter.reportErrorForNode(
CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY,
directive.uri,
- [directive.uri]);
+ [directive.uri.stringValue!]);
}
}
}
@@ -737,8 +745,6 @@
UriBasedDirectiveImpl.validateUri(isImport, uriLiteral, uriContent);
if (code == null) {
return _sourceFactory.resolveUri(file.source, uriContent);
- } else if (code == UriValidationCode.URI_WITH_DART_EXT_SCHEME) {
- return null;
} else if (code == UriValidationCode.URI_WITH_INTERPOLATION) {
_getErrorReporter(file).reportErrorForNode(
CompileTimeErrorCode.URI_WITH_INTERPOLATION, uriLiteral);
@@ -798,13 +804,23 @@
return;
}
}
+
+ var uriContent = directive.uriContent;
+ if (uriContent != null && uriContent.startsWith('dart-ext:')) {
+ _getErrorReporter(file).reportErrorForNode(
+ CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION,
+ directive.uri,
+ );
+ return;
+ }
+
StringLiteral uriLiteral = directive.uri;
CompileTimeErrorCode errorCode = CompileTimeErrorCode.URI_DOES_NOT_EXIST;
if (isGeneratedSource(source)) {
errorCode = CompileTimeErrorCode.URI_HAS_NOT_BEEN_GENERATED;
}
_getErrorReporter(file)
- .reportErrorForNode(errorCode, uriLiteral, [directive.uriContent]);
+ .reportErrorForNode(errorCode, uriLiteral, [uriContent]);
}
/// Check each directive in the given [unit] to see if the referenced source
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index 4e56df0..c1b1c9f 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -83,7 +83,7 @@
final List<FileState> libraryFiles = [];
FileState? partOfLibrary;
- late List<int> _digest;
+ late Uint8List _digest;
late bool _exists;
late List<int> _apiSignature;
late UnlinkedUnit2 unlinked2;
@@ -226,7 +226,7 @@
performance.getDataInt('count').increment();
performance.run('digest', (_) {
- _digest = utf8.encode(_fsState.getFileDigest(path));
+ _digest = utf8.encode(_fsState.getFileDigest(path)) as Uint8List;
_exists = _digest.isNotEmpty;
});
@@ -235,8 +235,8 @@
// Prepare bytes of the unlinked bundle - existing or new.
// TODO(migration): should not be nullable
- List<int>? unlinkedBytes;
- List<int>? informativeBytes;
+ Uint8List? unlinkedBytes;
+ Uint8List? informativeBytes;
{
var unlinkedData = _fsState._byteStore.get(unlinkedKey, _digest);
var informativeData = _fsState._byteStore.get(informativeKey, _digest);
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index e28b029..f60649d 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -898,7 +898,7 @@
BundleReader(
elementFactory: elementFactory,
unitsInformativeBytes: unitsInformativeBytes,
- resolutionBytes: resolutionBytes as Uint8List,
+ resolutionBytes: resolutionBytes,
),
);
}
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 66844bc..3900f37 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -427,7 +427,6 @@
void visitExportDirective(ExportDirective node) {
_deprecatedVerifier.exportDirective(node);
_checkForInternalExport(node);
- _checkForUseOfNativeExtension(node);
super.visitExportDirective(node);
}
@@ -582,7 +581,6 @@
}
_invalidAccessVerifier.verifyImport(node);
_checkForImportOfLegacyLibraryIntoNullSafe(node);
- _checkForUseOfNativeExtension(node);
super.visitImportDirective(node);
}
@@ -1442,16 +1440,6 @@
return false;
}
- void _checkForUseOfNativeExtension(UriBasedDirective node) {
- var uri = node.uriContent;
- if (uri == null) {
- return;
- }
- if (uri.startsWith('dart-ext:')) {
- _errorReporter.reportErrorForNode(HintCode.USE_OF_NATIVE_EXTENSION, node);
- }
- }
-
void _checkRequiredParameter(FormalParameterList node) {
final requiredParameters =
node.parameters.where((p) => p.declaredElement?.hasRequired == true);
diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart
index dd11f38..22dec30 100644
--- a/pkg/analyzer/lib/src/error/codes.g.dart
+++ b/pkg/analyzer/lib/src/error/codes.g.dart
@@ -15028,6 +15028,35 @@
*/
// #### Description
//
+ // The analyzer produces this diagnostic when a library is imported using the
+ // `dart-ext` scheme.
+ //
+ // #### Example
+ //
+ // The following code produces this diagnostic because the native library `x`
+ // is being imported using a scheme of `dart-ext`:
+ //
+ // ```dart
+ // import [!'dart-ext:x'!];
+ // ```
+ //
+ // #### Common fixes
+ //
+ // Rewrite the code to use `dart:ffi` as a way of invoking the contents of the
+ // native library.
+ static const CompileTimeErrorCode USE_OF_NATIVE_EXTENSION =
+ CompileTimeErrorCode(
+ 'USE_OF_NATIVE_EXTENSION',
+ "Dart native extensions are deprecated and aren’t available in Dart 2.15.",
+ correctionMessage: "Try using dart:ffi for C interop.",
+ hasPublishedDocs: true,
+ );
+
+ /**
+ * No parameters.
+ */
+ // #### Description
+ //
// The analyzer produces this diagnostic when it finds an expression whose
// type is `void`, and the expression is used in a place where a value is
// expected, such as before a member access or on the right-hand side of an
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 647e36b..7f01644 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -208,10 +208,6 @@
/// A flag indicating whether the visitor is currently within code in the SDK.
bool _isInSystemLibrary = false;
- /// A flag indicating whether the current library contains at least one import
- /// directive with a URI that uses the "dart-ext" scheme.
- bool _hasExtUri = false;
-
/// The class containing the AST nodes being visited, or `null` if we are not
/// in the scope of a class.
ClassElementImpl? _enclosingClass;
@@ -265,7 +261,6 @@
_duplicateDefinitionVerifier =
DuplicateDefinitionVerifier(_currentLibrary, errorReporter) {
_isInSystemLibrary = _currentLibrary.source.isInSystemLibrary;
- _hasExtUri = _currentLibrary.hasExtUri;
_isInCatchClause = false;
_isInStaticVariableDeclaration = false;
_isInConstructorInitializer = false;
@@ -2274,10 +2269,14 @@
return;
}
+ // It is safe to assume that `directive.uri.stringValue` is non-`null`,
+ // because the only time it is `null` is if the URI contains a string
+ // interpolation, in which case the export would never have resolved in the
+ // first place.
errorReporter.reportErrorForNode(
CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY,
directive,
- [directive.uri]);
+ [directive.uri.stringValue!]);
}
/// See [CompileTimeErrorCode.EXPORT_LEGACY_SYMBOL].
@@ -3247,7 +3246,7 @@
///
/// See [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE].
void _checkForNativeFunctionBodyInNonSdkCode(NativeFunctionBody body) {
- if (!_isInSystemLibrary && !_hasExtUri) {
+ if (!_isInSystemLibrary) {
errorReporter.reportErrorForNode(
ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE, body);
}
diff --git a/pkg/analyzer/lib/src/generated/source.dart b/pkg/analyzer/lib/src/generated/source.dart
index 2203d3d..f134a33 100644
--- a/pkg/analyzer/lib/src/generated/source.dart
+++ b/pkg/analyzer/lib/src/generated/source.dart
@@ -48,10 +48,6 @@
/// The name of the `dart` scheme.
static String DART_SCHEME = "dart";
- /// The prefix of a URI using the dart-ext scheme to reference a native code
- /// library.
- static const String _DART_EXT_SCHEME = "dart-ext:";
-
/// The Dart SDK against which URI's are to be resolved.
final DartSdk _sdk;
@@ -78,13 +74,6 @@
return dartSource?.uri;
}
- /// Return `true` if the given URI is a `dart-ext:` URI.
- ///
- /// @param uriContent the textual representation of the URI being tested
- /// @return `true` if the given URI is a `dart-ext:` URI
- static bool isDartExtUri(String? uriContent) =>
- uriContent != null && uriContent.startsWith(_DART_EXT_SCHEME);
-
/// Return `true` if the given URI is a `dart:` URI.
///
/// @param uri the URI being tested
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index c375b8c..5d1e535 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
import 'package:analyzer/src/summary2/link.dart';
@@ -24,7 +23,6 @@
final _imports = <ImportElement>[];
var _isFirstLibraryDirective = true;
var _hasCoreImport = false;
- var _hasExtUri = false;
var _partDirectiveIndex = 0;
_EnclosingContext _enclosingContext;
@@ -72,7 +70,6 @@
);
}
_libraryElement.imports = _imports;
- _libraryElement.hasExtUri = _hasExtUri;
if (_isFirstLibraryDirective) {
_isFirstLibraryDirective = false;
@@ -619,8 +616,6 @@
if (uriStr == 'dart:core') {
_hasCoreImport = true;
- } else if (DartUriResolver.isDartExtUri(uriStr)) {
- _hasExtUri = true;
}
}
diff --git a/pkg/analyzer/lib/src/summary2/element_flags.dart b/pkg/analyzer/lib/src/summary2/element_flags.dart
index e808000..806aab7 100644
--- a/pkg/analyzer/lib/src/summary2/element_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/element_flags.dart
@@ -136,20 +136,17 @@
}
class LibraryElementFlags {
- static const int _hasExtUri = 1 << 0;
- static const int _hasPartOfDirective = 1 << 1;
- static const int _isSynthetic = 1 << 2;
+ static const int _hasPartOfDirective = 1 << 0;
+ static const int _isSynthetic = 1 << 1;
static void read(SummaryDataReader reader, LibraryElementImpl element) {
var byte = reader.readByte();
- element.hasExtUri = (byte & _hasExtUri) != 0;
element.hasPartOfDirective = (byte & _hasPartOfDirective) != 0;
element.isSynthetic = (byte & _isSynthetic) != 0;
}
static void write(BufferedSink sink, LibraryElementImpl element) {
var result = 0;
- result |= element.hasExtUri ? _hasExtUri : 0;
result |= element.hasPartOfDirective ? _hasPartOfDirective : 0;
result |= element.isSynthetic ? _isSynthetic : 0;
sink.writeByte(result);
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index ebd0349..bee1e35 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -13204,6 +13204,30 @@
var zero = min(0, 0);
```
+ USE_OF_NATIVE_EXTENSION:
+ problemMessage: Dart native extensions are deprecated and aren’t available in Dart 2.15.
+ correctionMessage: "Try using dart:ffi for C interop."
+ hasPublishedDocs: true
+ comment: No parameters.
+ documentation: |-
+ #### Description
+
+ The analyzer produces this diagnostic when a library is imported using the
+ `dart-ext` scheme.
+
+ #### Example
+
+ The following code produces this diagnostic because the native library `x`
+ is being imported using a scheme of `dart-ext`:
+
+ ```dart
+ import [!'dart-ext:x'!];
+ ```
+
+ #### Common fixes
+
+ Rewrite the code to use `dart:ffi` as a way of invoking the contents of the
+ native library.
USE_OF_VOID_RESULT:
problemMessage: "This expression has a type of 'void' so its value can't be used."
correctionMessage: "Try checking to see if you're using the correct API; there might be a function or call that returns void you didn't expect. Also check type parameters and variables which might also be void."
@@ -17272,31 +17296,6 @@
var x = min(0, 1);
```
- USE_OF_NATIVE_EXTENSION:
- problemMessage: Dart native extensions are deprecated and aren’t available in Dart 2.15.
- correctionMessage: "Try using dart:ffi for C interop."
- hasPublishedDocs: true
- comment: No parameters.
- documentation: |-
- #### Description
-
- The analyzer produces this diagnostic when a library is imported using the
- `dart-ext` scheme.
-
- #### Example
-
- The following code produces this diagnostic because the native library `x`
- is being imported using a scheme of `dart-ext`:
-
- ```dart
- [!import 'dart-ext:x';!]
- int f() native 'string';
- ```
-
- #### Common fixes
-
- Rewrite the code to use `dart:ffi` as a way of invoking the contents of the
- native library.
LanguageCode:
IMPLICIT_DYNAMIC_FIELD:
problemMessage: "Missing field type for '{0}'."
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 91e4e01..a1cdefa 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -2358,28 +2358,6 @@
''');
}
- test_nativeConstConstructor() async {
- await assertErrorsInCode(r'''
-import 'dart-ext:x';
-class Foo {
- const Foo() native 'Foo_Foo';
- const factory Foo.foo() native 'Foo_Foo_foo';
-}
-''', [
- error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 20),
- error(ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY, 47, 6),
- ]);
- }
-
- test_nativeFunctionBodyInNonSDKCode_function() async {
- await assertErrorsInCode(r'''
-import 'dart-ext:x';
-int m(a) native 'string';
-''', [
- error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 20),
- ]);
- }
-
test_newWithAbstractClass_factory() async {
await assertNoErrorsInCode(r'''
abstract class A {
diff --git a/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart b/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart
index 47202d9..6cf3fea 100644
--- a/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/byte_store_test.dart
@@ -2,6 +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 'dart:typed_data';
+
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -13,8 +15,8 @@
});
}
-List<int> _b(int length) {
- return List<int>.filled(length, 0);
+Uint8List _b(int length) {
+ return Uint8List(length);
}
@reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/analysis/file_byte_store_test.dart b/pkg/analyzer/test/src/dart/analysis/file_byte_store_test.dart
index c767dce..5b59568 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_byte_store_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_byte_store_test.dart
@@ -2,6 +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 'dart:typed_data';
+
import 'package:analyzer/src/dart/analysis/file_byte_store.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -17,20 +19,20 @@
final validator = FileByteStoreValidator();
test_get_bad_notEnoughBytes() {
- List<int> bytes = <int>[1, 2, 3];
+ var bytes = Uint8List.fromList([1, 2, 3]);
var data = validator.getData(bytes);
expect(data, isNull);
}
test_get_bad_notEnoughBytes_zero() {
- List<int> bytes = <int>[];
+ var bytes = Uint8List.fromList([]);
var data = validator.getData(bytes);
expect(data, isNull);
}
test_get_bad_wrongChecksum() {
- List<int> data = <int>[1, 2, 3];
- List<int> bytes = validator.wrapData(data);
+ var data = Uint8List.fromList([1, 2, 3]);
+ var bytes = validator.wrapData(data);
// Damage the checksum.
expect(bytes[bytes.length - 1], isNot(42));
@@ -41,22 +43,24 @@
}
test_get_bad_wrongVersion() {
- List<int> bytes = <int>[0xBA, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
+ var bytes = Uint8List.fromList(
+ [0xBA, 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
+ );
var data = validator.getData(bytes);
expect(data, isNull);
}
test_get_good() {
- List<int> data = <int>[1, 2, 3];
- List<int> bytes = validator.wrapData(data);
+ var data = Uint8List.fromList([1, 2, 3]);
+ var bytes = validator.wrapData(data);
var data2 = validator.getData(bytes);
expect(data2, hasLength(3));
expect(data2, data);
}
test_get_good_zeroBytesData() {
- List<int> data = <int>[];
- List<int> bytes = validator.wrapData(data);
+ var data = Uint8List.fromList([]);
+ var bytes = validator.wrapData(data);
var data2 = validator.getData(bytes);
expect(data2, hasLength(0));
expect(data2, data);
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 29fcbe1..a4da5db 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -619,7 +619,7 @@
expect(file.unlinked2, isNotNull);
// Make the unlinked unit in the byte store zero-length, damaged.
- byteStore.put(file.test.unlinkedKey, <int>[]);
+ byteStore.put(file.test.unlinkedKey, Uint8List(0));
// Refresh should not fail, zero bytes in the store are ignored.
file.refresh();
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index c2ad9fe..f2dd07e 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -4,6 +4,7 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/element/element.dart';
@@ -317,6 +318,137 @@
);
}
+ test_instanceCreationExpression_redirecting_typeParameter() async {
+ await resolveTestCode('''
+class A<T> {
+ final Object f;
+ const A(): this.named(T);
+ const A.named(Object t): f = t;
+}
+const a = const A<int>();
+''');
+ var result = _evaluateConstant('a');
+ expect(result, isNotNull);
+ }
+
+ test_instanceCreationExpression_typeParameter() async {
+ await resolveTestCode('''
+class A<T> {
+ final Object f;
+ const A(): f = T;
+}
+const a = const A<int>();
+''');
+ var result = _evaluateConstant('a');
+ var aElement = findElement.class_('A');
+ var expectedType = aElement.instantiate(
+ typeArguments: [typeProvider.intType],
+ nullabilitySuffix: NullabilitySuffix.none);
+ expect(result.type, expectedType);
+ }
+
+ test_instanceCreationExpression_typeParameter_implicitTypeArgs() async {
+ await resolveTestCode('''
+class A<T> {
+ final Object f;
+ const A(): f = T;
+}
+const a = const A();
+''');
+ var result = _evaluateConstant('a');
+ var aElement = findElement.class_('A');
+ var expectedType = aElement.instantiate(
+ typeArguments: [typeProvider.dynamicType],
+ nullabilitySuffix: NullabilitySuffix.none);
+ expect(result.type, expectedType);
+ }
+
+ test_instanceCreationExpression_typeParameter_super() async {
+ await resolveTestCode('''
+class A<T> {
+ final Object f;
+ const A(Object t): f = t;
+}
+class B<T> extends A<T> {
+ const B(): super(T);
+}
+const a = const B<int>();
+''');
+ var result = _evaluateConstant('a');
+ var bElement = findElement.class_('B');
+ var expectedType = bElement.instantiate(
+ typeArguments: [typeProvider.intType],
+ nullabilitySuffix: NullabilitySuffix.none);
+ expect(result.type, expectedType);
+ }
+
+ test_instanceCreationExpression_typeParameter_superNonGeneric() async {
+ await resolveTestCode('''
+class A {
+ final Object f;
+ const A(Object t): f = t;
+}
+class B<T> extends A {
+ const B(): super(T);
+}
+const a = const B<int>();
+''');
+ var result = _evaluateConstant('a');
+ expect(result, isNotNull);
+ }
+
+ test_instanceCreationExpression_typeParameter_typeAlias() async {
+ await resolveTestCode('''
+class A<T, U> {
+ final Object f, g;
+ const A(): f = T, g = U;
+}
+typedef B<S> = A<int, S>;
+const a = const B<String>();
+''');
+ var result = _evaluateConstant('a');
+ var aElement = findElement.class_('A');
+ var expectedType = aElement.instantiate(
+ typeArguments: [typeProvider.intType, typeProvider.stringType],
+ nullabilitySuffix: NullabilitySuffix.none);
+ expect(result.type, expectedType);
+ }
+
+ test_instanceCreationExpression_typeParameter_withoutConstructorTearoffs() async {
+ await resolveTestCode('''
+// @dart=2.12
+class A<T> {
+ final Object f;
+ const A(): f = T;
+}
+const a = const A<int>();
+''');
+ var result = _evaluateConstant('a', errorCodes: [
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
+ CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION,
+ ]);
+ var aElement = findElement.class_('A');
+ var expectedType = aElement.instantiate(
+ typeArguments: [typeProvider.intType],
+ nullabilitySuffix: NullabilitySuffix.none);
+ expect(result.type, expectedType);
+ }
+
+ test_typeParameter() async {
+ await resolveTestCode('''
+class A<X> {
+ const A();
+ void m() {
+ const x = X;
+ }
+}
+''');
+ var result = _evaluateConstantLocal('x', errorCodes: [
+ CompileTimeErrorCode.INVALID_CONSTANT,
+ ]);
+ expect(result, isNull);
+ }
+
test_visitAsExpression_potentialConstType() async {
await assertNoErrorsInCode('''
const num three = 3;
diff --git a/pkg/analyzer/test/src/diagnostics/export_internal_library_test.dart b/pkg/analyzer/test/src/diagnostics/export_internal_library_test.dart
index e4a7206..c4eea53 100644
--- a/pkg/analyzer/test/src/diagnostics/export_internal_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/export_internal_library_test.dart
@@ -19,7 +19,8 @@
await assertErrorsInCode('''
export 'dart:_internal';
''', [
- error(CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, 0, 24),
+ error(CompileTimeErrorCode.EXPORT_INTERNAL_LIBRARY, 0, 24,
+ messageContains: "library 'dart:_internal' "),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/export_of_non_library_test.dart b/pkg/analyzer/test/src/diagnostics/export_of_non_library_test.dart
index 4c4ef49..fc0bf97 100644
--- a/pkg/analyzer/test/src/diagnostics/export_of_non_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/export_of_non_library_test.dart
@@ -23,7 +23,8 @@
library L;
export 'lib1.dart';
''', [
- error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 18, 11),
+ error(CompileTimeErrorCode.EXPORT_OF_NON_LIBRARY, 18, 11,
+ messageContains: "library 'lib1.dart' "),
]);
}
diff --git a/pkg/analyzer/test/src/diagnostics/import_of_non_library_test.dart b/pkg/analyzer/test/src/diagnostics/import_of_non_library_test.dart
index 7a0dca2..d5ffe46 100644
--- a/pkg/analyzer/test/src/diagnostics/import_of_non_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/import_of_non_library_test.dart
@@ -25,7 +25,8 @@
import 'lib1.dart' deferred as p;
var a = new p.A();
''', [
- error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 20, 11),
+ error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 20, 11,
+ messageContains: "library 'lib1.dart' "),
]);
}
@@ -39,7 +40,8 @@
import 'part.dart';
A a = A();
''', [
- error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 20, 11),
+ error(CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY, 20, 11,
+ messageContains: "library 'part.dart' "),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/uri_does_not_exist_test.dart b/pkg/analyzer/test/src/diagnostics/uri_does_not_exist_test.dart
index 4ae834a..ceca9ef 100644
--- a/pkg/analyzer/test/src/diagnostics/uri_does_not_exist_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/uri_does_not_exist_test.dart
@@ -88,31 +88,4 @@
error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 18, 14),
]);
}
-
- test_valid_dll() async {
- newFile("$testPackageLibPath/lib.dll");
- await assertErrorsInCode('''
-import 'dart-ext:lib';
-''', [
- error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 22),
- ]);
- }
-
- test_valid_dylib() async {
- newFile("$testPackageLibPath/lib.dylib");
- await assertErrorsInCode('''
-import 'dart-ext:lib';
-''', [
- error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 22),
- ]);
- }
-
- test_valid_so() async {
- newFile("$testPackageLibPath/lib.so");
- await assertErrorsInCode('''
-import 'dart-ext:lib';
-''', [
- error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 22),
- ]);
- }
}
diff --git a/pkg/analyzer/test/src/diagnostics/use_of_native_extension_test.dart b/pkg/analyzer/test/src/diagnostics/use_of_native_extension_test.dart
index e172765..8a89fab 100644
--- a/pkg/analyzer/test/src/diagnostics/use_of_native_extension_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/use_of_native_extension_test.dart
@@ -19,8 +19,7 @@
await assertErrorsInCode(r'''
export 'dart-ext:x';
''', [
- error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 20),
- error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 7, 12),
+ error(CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION, 7, 12),
]);
}
@@ -28,8 +27,7 @@
await assertErrorsInCode(r'''
import 'dart-ext:x';
''', [
- // TODO(srawlins): Why does this file not have a URI_DOES_NOT_EXIST error?
- error(HintCode.USE_OF_NATIVE_EXTENSION, 0, 20),
+ error(CompileTimeErrorCode.USE_OF_NATIVE_EXTENSION, 7, 12),
]);
}
}
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index 9c1892b..fc014beb 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -15374,8 +15374,7 @@
is being imported using a scheme of `dart-ext`:
{% prettify dart tag=pre+code %}
-[!import 'dart-ext:x';!]
-int f() native 'string';
+import [!'dart-ext:x'!];
{% endprettify %}
#### Common fixes
diff --git a/pkg/dds/lib/src/dap/adapters/dart.dart b/pkg/dds/lib/src/dap/adapters/dart.dart
index b585cd5..67be4b5 100644
--- a/pkg/dds/lib/src/dap/adapters/dart.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart.dart
@@ -1666,10 +1666,10 @@
}
}
- void _logTraffic(String data) {
- logger?.call(data);
+ void _logTraffic(String message) {
+ logger?.call(message);
if (sendLogsToClient) {
- sendEvent(RawEventBody(data), eventType: 'dart.log');
+ sendEvent(RawEventBody({"message": message}), eventType: 'dart.log');
}
}
diff --git a/pkg/dds/test/dap/integration/debug_logging_test.dart b/pkg/dds/test/dap/integration/debug_logging_test.dart
index 27578f5..02685fb 100644
--- a/pkg/dds/test/dap/integration/debug_logging_test.dart
+++ b/pkg/dds/test/dap/integration/debug_logging_test.dart
@@ -5,6 +5,7 @@
import 'package:test/test.dart';
import 'test_client.dart';
+import 'test_scripts.dart';
import 'test_support.dart';
main() {
@@ -15,6 +16,33 @@
tearDown(() => dap.tearDown());
group('debug mode', () {
+ test('sends dart.log events when sendLogsToClient=true', () async {
+ final testFile = dap.createTestFile(simpleArgPrintingProgram);
+
+ final logOutputs = dap.client
+ .events('dart.log')
+ .map((event) => event.body as Map<String, Object?>)
+ .map((body) => body['message'] as String);
+
+ await Future.wait([
+ expectLater(
+ logOutputs,
+ // Check for a known VM Service packet.
+ emitsThrough(
+ contains('"method":"streamListen","params":{"streamId":"Debug"}'),
+ ),
+ ),
+ dap.client.start(
+ file: testFile,
+ launch: () => dap.client.launch(
+ testFile.path,
+ sendLogsToClient: true,
+ ),
+ ),
+ ]);
+ await dap.client.terminate();
+ });
+
test('prints messages from dart:developer log()', () async {
final testFile = dap.createTestFile(r'''
import 'dart:developer';
diff --git a/pkg/dds/test/dap/integration/test_client.dart b/pkg/dds/test/dap/integration/test_client.dart
index 78b145d..66f44da 100644
--- a/pkg/dds/test/dap/integration/test_client.dart
+++ b/pkg/dds/test/dap/integration/test_client.dart
@@ -227,6 +227,7 @@
bool? debugExternalPackageLibraries,
bool? evaluateGettersInDebugViews,
bool? evaluateToStringInDebugViews,
+ bool? sendLogsToClient,
}) {
return sendRequest(
DartLaunchRequestArguments(
@@ -243,7 +244,7 @@
// When running out of process, VM Service traffic won't be available
// to the client-side logger, so force logging on which sends VM Service
// traffic in a custom event.
- sendLogsToClient: captureVmServiceTraffic,
+ sendLogsToClient: sendLogsToClient ?? captureVmServiceTraffic,
),
// We can't automatically pick the command when using a custom type
// (DartLaunchRequestArguments).
diff --git a/pkg/dds/tool/dap/README.md b/pkg/dds/tool/dap/README.md
index 6ba9e91..216d648 100644
--- a/pkg/dds/tool/dap/README.md
+++ b/pkg/dds/tool/dap/README.md
@@ -100,7 +100,9 @@
{
"type": "event",
"event": "dart.log",
- "body": "<log message or json string>"
+ "body": {
+ "message": "<log message or json string>"
+ }
}
```
diff --git a/runtime/observatory/lib/src/elements/process_snapshot.dart b/runtime/observatory/lib/src/elements/process_snapshot.dart
index 4aef2cf..6e87923 100644
--- a/runtime/observatory/lib/src/elements/process_snapshot.dart
+++ b/runtime/observatory/lib/src/elements/process_snapshot.dart
@@ -602,6 +602,7 @@
..onChange.listen((_) {
_snapshotA = _loadedSnapshots[s.selectedIndex];
selection = null;
+ diffSelection = null;
_r.dirty();
})
];
@@ -622,6 +623,7 @@
..onChange.listen((_) {
_snapshotB = _loadedSnapshots[s.selectedIndex];
selection = null;
+ diffSelection = null;
_r.dirty();
})
];
diff --git a/runtime/tests/vm/dart/regress_47425_test.dart b/runtime/tests/vm/dart/regress_47425_test.dart
new file mode 100644
index 0000000..f8d6576
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_47425_test.dart
@@ -0,0 +1,37 @@
+// 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.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/47425.
+// Verifies that Type.operator== works on generic types which
+// classes are not finalized.
+
+import 'package:expect/expect.dart';
+
+void testTypesEquality<A, B>(bool expected) {
+ Expect.equals(expected, A == B);
+}
+
+void withNewBox() {
+ Box();
+ testTypesEquality<Box<num>, Box<int>>(false);
+}
+
+void withoutNewBox() {
+ testTypesEquality<Box<num>, Box<int>>(false);
+}
+
+class Box<T> {}
+
+void main() {
+ testTypesEquality<num, int>(false);
+ testTypesEquality<Box<num>, Box<int>>(false);
+ testTypesEquality<Box<num>, Box<num>>(true);
+
+ withoutNewBox();
+ withNewBox();
+ withoutNewBox();
+
+ testTypesEquality<Box<num>, Box<int>>(false);
+ testTypesEquality<Box<num>, Box<num>>(true);
+}
diff --git a/runtime/tests/vm/dart_2/regress_47425_test.dart b/runtime/tests/vm/dart_2/regress_47425_test.dart
new file mode 100644
index 0000000..7cd3cfa
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_47425_test.dart
@@ -0,0 +1,39 @@
+// 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.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/47425.
+// Verifies that Type.operator== works on generic types which
+// classes are not finalized.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+void testTypesEquality<A, B>(bool expected) {
+ Expect.equals(expected, A == B);
+}
+
+void withNewBox() {
+ Box();
+ testTypesEquality<Box<num>, Box<int>>(false);
+}
+
+void withoutNewBox() {
+ testTypesEquality<Box<num>, Box<int>>(false);
+}
+
+class Box<T> {}
+
+void main() {
+ testTypesEquality<num, int>(false);
+ testTypesEquality<Box<num>, Box<int>>(false);
+ testTypesEquality<Box<num>, Box<num>>(true);
+
+ withoutNewBox();
+ withNewBox();
+ withoutNewBox();
+
+ testTypesEquality<Box<num>, Box<int>>(false);
+ testTypesEquality<Box<num>, Box<num>>(true);
+}
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index f29a90a..8a97dd4 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -1210,20 +1210,19 @@
}
// Compares cid1 and cid2 to see if they're syntactically equivalent. If this
-// can be determined by this fast path, it jumps to either equal or not_equal,
-// if equal but belonging to a generic class, it falls through with the scratch
-// register containing host_type_arguments_field_offset_in_words,
-// otherwise it jumps to normal_ir_body. May clobber scratch.
+// can be determined by this fast path, it jumps to either equal_* or not_equal.
+// If classes are equivalent but may be generic, then jumps to
+// equal_may_be_generic. Clobbers scratch.
static void EquivalentClassIds(Assembler* assembler,
Label* normal_ir_body,
- Label* equal,
+ Label* equal_may_be_generic,
+ Label* equal_not_generic,
Label* not_equal,
Register cid1,
Register cid2,
Register scratch,
bool testing_instance_cids) {
- Label different_cids, equal_cids_but_generic, not_integer,
- not_integer_or_string, not_integer_or_string_or_list;
+ Label not_integer, not_integer_or_string, not_integer_or_string_or_list;
// Check if left hand side is a closure. Closures are handled in the runtime.
__ CompareImmediate(cid1, kClosureCid);
@@ -1233,25 +1232,11 @@
// considered equivalent (e.g. multiple string implementation classes map to a
// single String type).
__ cmp(cid1, Operand(cid2));
- __ b(&different_cids, NE);
-
- // Types have the same class and neither is a closure type.
- // Check if there are no type arguments. In this case we can return true.
- // Otherwise fall through into the runtime to handle comparison.
- __ LoadClassById(scratch, cid1);
- __ ldr(
- scratch,
- FieldAddress(
- scratch,
- target::Class::host_type_arguments_field_offset_in_words_offset()));
- __ CompareImmediate(scratch, target::Class::kNoTypeArguments);
- __ b(&equal_cids_but_generic, NE);
- __ b(equal);
+ __ b(equal_may_be_generic, EQ);
// Class ids are different. Check if we are comparing two string types (with
// different representations), two integer types, two list types or two type
// types.
- __ Bind(&different_cids);
__ CompareImmediate(cid1, kNumPredefinedCids);
__ b(not_equal, HI);
@@ -1259,7 +1244,7 @@
JumpIfNotInteger(assembler, cid1, scratch, ¬_integer);
// First type is an integer. Check if the second is an integer too.
- JumpIfInteger(assembler, cid2, scratch, equal);
+ JumpIfInteger(assembler, cid2, scratch, equal_not_generic);
// Integer types are only equivalent to other integer types.
__ b(not_equal);
@@ -1269,7 +1254,7 @@
testing_instance_cids ? ¬_integer_or_string : not_equal);
// First type is String. Check if the second is a string too.
- JumpIfString(assembler, cid2, scratch, equal);
+ JumpIfString(assembler, cid2, scratch, equal_not_generic);
// String types are only equivalent to other String types.
__ b(not_equal);
@@ -1282,8 +1267,7 @@
JumpIfNotList(assembler, cid2, scratch, not_equal);
ASSERT(compiler::target::Array::type_arguments_offset() ==
compiler::target::GrowableObjectArray::type_arguments_offset());
- __ LoadImmediate(scratch, compiler::target::Array::type_arguments_offset());
- __ b(&equal_cids_but_generic);
+ __ b(equal_may_be_generic);
__ Bind(¬_integer_or_string_or_list);
// Check if the first type is a Type. If it is not then types are not
@@ -1292,13 +1276,10 @@
JumpIfNotType(assembler, cid1, scratch, not_equal);
// First type is a Type. Check if the second is a Type too.
- JumpIfType(assembler, cid2, scratch, equal);
+ JumpIfType(assembler, cid2, scratch, equal_not_generic);
// Type types are only equivalent to other Type types.
__ b(not_equal);
}
-
- // The caller must compare the type arguments.
- __ Bind(&equal_cids_but_generic);
}
void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
@@ -1307,10 +1288,24 @@
__ LoadClassIdMayBeSmi(R1, R1);
__ LoadClassIdMayBeSmi(R2, R2);
- Label equal, not_equal;
- EquivalentClassIds(assembler, normal_ir_body, &equal, ¬_equal, R1, R2, R0,
+ Label equal_may_be_generic, equal, not_equal;
+ EquivalentClassIds(assembler, normal_ir_body, &equal_may_be_generic, &equal,
+ ¬_equal, R1, R2, R0,
/* testing_instance_cids = */ true);
+ __ Bind(&equal_may_be_generic);
+ // Classes are equivalent and neither is a closure class.
+ // Check if there are no type arguments. In this case we can return true.
+ // Otherwise fall through into the runtime to handle comparison.
+ __ LoadClassById(R0, R1);
+ __ ldr(
+ R0,
+ FieldAddress(
+ R0,
+ target::Class::host_type_arguments_field_offset_in_words_offset()));
+ __ CompareImmediate(R0, target::Class::kNoTypeArguments);
+ __ b(&equal, EQ);
+
// Compare type arguments, host_type_arguments_field_offset_in_words in R0.
__ ldm(IA, SP, (1 << R1 | 1 << R2));
__ AddImmediate(R1, -kHeapObjectTag);
@@ -1352,7 +1347,7 @@
void AsmIntrinsifier::Type_equality(Assembler* assembler,
Label* normal_ir_body) {
- Label equal, not_equal, equiv_cids, check_legacy;
+ Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
__ ldm(IA, SP, (1 << R1 | 1 << R2));
__ cmp(R1, Operand(R2));
@@ -1370,9 +1365,11 @@
__ ldr(R4, FieldAddress(R2, target::Type::type_class_id_offset()));
__ SmiUntag(R4);
// We are not testing instance cids, but type class cids of Type instances.
- EquivalentClassIds(assembler, normal_ir_body, &equiv_cids, ¬_equal, R3, R4,
- R0, /* testing_instance_cids = */ false);
+ EquivalentClassIds(assembler, normal_ir_body, &equiv_cids_may_be_generic,
+ &equiv_cids, ¬_equal, R3, R4, R0,
+ /* testing_instance_cids = */ false);
+ __ Bind(&equiv_cids_may_be_generic);
// Compare type arguments in Type instances.
__ ldr(R3, FieldAddress(R1, target::Type::arguments_offset()));
__ ldr(R4, FieldAddress(R2, target::Type::arguments_offset()));
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 66a1480..1b2a819 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -1355,20 +1355,19 @@
}
// Compares cid1 and cid2 to see if they're syntactically equivalent. If this
-// can be determined by this fast path, it jumps to either equal or not_equal,
-// if equal but belonging to a generic class, it falls through with the scratch
-// register containing host_type_arguments_field_offset_in_words,
-// otherwise it jumps to normal_ir_body. May clobber scratch.
+// can be determined by this fast path, it jumps to either equal_* or not_equal.
+// If classes are equivalent but may be generic, then jumps to
+// equal_may_be_generic. Clobbers scratch.
static void EquivalentClassIds(Assembler* assembler,
Label* normal_ir_body,
- Label* equal,
+ Label* equal_may_be_generic,
+ Label* equal_not_generic,
Label* not_equal,
Register cid1,
Register cid2,
Register scratch,
bool testing_instance_cids) {
- Label different_cids, equal_cids_but_generic, not_integer,
- not_integer_or_string, not_integer_or_string_or_list;
+ Label not_integer, not_integer_or_string, not_integer_or_string_or_list;
// Check if left hand side is a closure. Closures are handled in the runtime.
__ CompareImmediate(cid1, kClosureCid);
@@ -1378,25 +1377,11 @@
// considered equivalent (e.g. multiple string implementation classes map to a
// single String type).
__ cmp(cid1, Operand(cid2));
- __ b(&different_cids, NE);
-
- // Types have the same class and neither is a closure type.
- // Check if there are no type arguments. In this case we can return true.
- // Otherwise fall through into the runtime to handle comparison.
- __ LoadClassById(scratch, cid1);
- __ ldr(scratch,
- FieldAddress(
- scratch,
- target::Class::host_type_arguments_field_offset_in_words_offset()),
- kFourBytes);
- __ CompareImmediate(scratch, target::Class::kNoTypeArguments);
- __ b(&equal_cids_but_generic, NE);
- __ b(equal);
+ __ b(equal_may_be_generic, EQ);
// Class ids are different. Check if we are comparing two string types (with
// different representations), two integer types, two list types or two type
// types.
- __ Bind(&different_cids);
__ CompareImmediate(cid1, kNumPredefinedCids);
__ b(not_equal, HI);
@@ -1404,7 +1389,7 @@
JumpIfNotInteger(assembler, cid1, scratch, ¬_integer);
// First type is an integer. Check if the second is an integer too.
- JumpIfInteger(assembler, cid2, scratch, equal);
+ JumpIfInteger(assembler, cid2, scratch, equal_not_generic);
// Integer types are only equivalent to other integer types.
__ b(not_equal);
@@ -1414,7 +1399,7 @@
testing_instance_cids ? ¬_integer_or_string : not_equal);
// First type is String. Check if the second is a string too.
- JumpIfString(assembler, cid2, scratch, equal);
+ JumpIfString(assembler, cid2, scratch, equal_not_generic);
// String types are only equivalent to other String types.
__ b(not_equal);
@@ -1427,8 +1412,7 @@
JumpIfNotList(assembler, cid2, scratch, not_equal);
ASSERT(compiler::target::Array::type_arguments_offset() ==
compiler::target::GrowableObjectArray::type_arguments_offset());
- __ LoadImmediate(scratch, compiler::target::Array::type_arguments_offset());
- __ b(&equal_cids_but_generic);
+ __ b(equal_may_be_generic);
__ Bind(¬_integer_or_string_or_list);
// Check if the first type is a Type. If it is not then types are not
@@ -1437,13 +1421,10 @@
JumpIfNotType(assembler, cid1, scratch, not_equal);
// First type is a Type. Check if the second is a Type too.
- JumpIfType(assembler, cid2, scratch, equal);
+ JumpIfType(assembler, cid2, scratch, equal_not_generic);
// Type types are only equivalent to other Type types.
__ b(not_equal);
}
-
- // The caller must compare the type arguments.
- __ Bind(&equal_cids_but_generic);
}
void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
@@ -1452,10 +1433,24 @@
__ LoadClassIdMayBeSmi(R2, R1);
__ LoadClassIdMayBeSmi(R1, R0);
- Label equal, not_equal;
- EquivalentClassIds(assembler, normal_ir_body, &equal, ¬_equal, R1, R2, R0,
+ Label equal_may_be_generic, equal, not_equal;
+ EquivalentClassIds(assembler, normal_ir_body, &equal_may_be_generic, &equal,
+ ¬_equal, R1, R2, R0,
/* testing_instance_cids = */ true);
+ __ Bind(&equal_may_be_generic);
+ // Classes are equivalent and neither is a closure class.
+ // Check if there are no type arguments. In this case we can return true.
+ // Otherwise fall through into the runtime to handle comparison.
+ __ LoadClassById(R0, R1);
+ __ ldr(R0,
+ FieldAddress(
+ R0,
+ target::Class::host_type_arguments_field_offset_in_words_offset()),
+ kFourBytes);
+ __ CompareImmediate(R0, target::Class::kNoTypeArguments);
+ __ b(&equal, EQ);
+
// Compare type arguments, host_type_arguments_field_offset_in_words in R0.
__ ldp(R1, R2, Address(SP, 0 * target::kWordSize, Address::PairOffset));
__ AddImmediate(R1, -kHeapObjectTag);
@@ -1501,7 +1496,7 @@
void AsmIntrinsifier::Type_equality(Assembler* assembler,
Label* normal_ir_body) {
- Label equal, not_equal, equiv_cids, check_legacy;
+ Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
__ ldp(R1, R2, Address(SP, 0 * target::kWordSize, Address::PairOffset));
__ CompareObjectRegisters(R1, R2);
@@ -1521,9 +1516,11 @@
FieldAddress(R2, target::Type::type_class_id_offset()));
__ SmiUntag(R4);
// We are not testing instance cids, but type class cids of Type instances.
- EquivalentClassIds(assembler, normal_ir_body, &equiv_cids, ¬_equal, R3, R4,
- R0, /* testing_instance_cids = */ false);
+ EquivalentClassIds(assembler, normal_ir_body, &equiv_cids_may_be_generic,
+ &equiv_cids, ¬_equal, R3, R4, R0,
+ /* testing_instance_cids = */ false);
+ __ Bind(&equiv_cids_may_be_generic);
// Compare type arguments in Type instances.
__ LoadCompressed(R3, FieldAddress(R1, target::Type::arguments_offset()));
__ LoadCompressed(R4, FieldAddress(R2, target::Type::arguments_offset()));
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index 7cb2f54..91a1794 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -1311,20 +1311,19 @@
}
// Compares cid1 and cid2 to see if they're syntactically equivalent. If this
-// can be determined by this fast path, it jumps to either equal or not_equal,
-// if equal but belonging to a generic class, it falls through with the scratch
-// register containing host_type_arguments_field_offset_in_words,
-// otherwise it jumps to normal_ir_body. May clobber scratch.
+// can be determined by this fast path, it jumps to either equal_* or not_equal.
+// If classes are equivalent but may be generic, then jumps to
+// equal_may_be_generic. Clobbers scratch.
static void EquivalentClassIds(Assembler* assembler,
Label* normal_ir_body,
- Label* equal,
+ Label* equal_may_be_generic,
+ Label* equal_not_generic,
Label* not_equal,
Register cid1,
Register cid2,
Register scratch,
bool testing_instance_cids) {
- Label different_cids, equal_cids_but_generic, not_integer,
- not_integer_or_string, not_integer_or_string_or_list;
+ Label not_integer, not_integer_or_string, not_integer_or_string_or_list;
// Check if left hand side is a closure. Closures are handled in the runtime.
__ cmpl(cid1, Immediate(kClosureCid));
@@ -1334,25 +1333,11 @@
// considered equivalent (e.g. multiple string implementation classes map to a
// single String type).
__ cmpl(cid1, cid2);
- __ j(NOT_EQUAL, &different_cids);
-
- // Types have the same class and neither is a closure type.
- // Check if there are no type arguments. In this case we can return true.
- // Otherwise fall through into the runtime to handle comparison.
- __ LoadClassById(scratch, cid1);
- __ movl(
- scratch,
- FieldAddress(
- scratch,
- target::Class::host_type_arguments_field_offset_in_words_offset()));
- __ cmpl(scratch, Immediate(target::Class::kNoTypeArguments));
- __ j(NOT_EQUAL, &equal_cids_but_generic);
- __ jmp(equal);
+ __ j(EQUAL, equal_may_be_generic);
// Class ids are different. Check if we are comparing two string types (with
// different representations), two integer types, two list types or two type
// types.
- __ Bind(&different_cids);
__ cmpl(cid1, Immediate(kNumPredefinedCids));
__ j(ABOVE_EQUAL, not_equal);
@@ -1362,7 +1347,7 @@
// First type is an integer. Check if the second is an integer too.
__ movl(scratch, cid2);
- JumpIfInteger(assembler, scratch, equal);
+ JumpIfInteger(assembler, scratch, equal_not_generic);
// Integer types are only equivalent to other integer types.
__ jmp(not_equal);
@@ -1374,7 +1359,7 @@
// First type is a String. Check if the second is a String too.
__ movl(scratch, cid2);
- JumpIfString(assembler, scratch, equal);
+ JumpIfString(assembler, scratch, equal_not_generic);
// String types are only equivalent to other String types.
__ jmp(not_equal);
@@ -1389,24 +1374,21 @@
JumpIfNotList(assembler, scratch, not_equal);
ASSERT(compiler::target::Array::type_arguments_offset() ==
compiler::target::GrowableObjectArray::type_arguments_offset());
- __ movl(scratch,
- Immediate(compiler::target::Array::type_arguments_offset()));
- __ jmp(&equal_cids_but_generic, Assembler::kNearJump);
+ __ jmp(equal_may_be_generic);
__ Bind(¬_integer_or_string_or_list);
// Check if the first type is a Type. If it is not then types are not
// equivalent because they have different class ids and they are not String
// or integer or List or Type.
- JumpIfNotType(assembler, cid1, not_equal);
+ __ movl(scratch, cid1);
+ JumpIfNotType(assembler, scratch, not_equal);
// First type is a Type. Check if the second is a Type too.
- JumpIfType(assembler, cid2, equal);
+ __ movl(scratch, cid2);
+ JumpIfType(assembler, scratch, equal_not_generic);
// Type types are only equivalent to other Type types.
__ jmp(not_equal);
}
-
- // The caller must compare the type arguments.
- __ Bind(&equal_cids_but_generic);
}
void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
@@ -1417,9 +1399,23 @@
__ movl(EAX, Address(ESP, +2 * target::kWordSize));
__ LoadClassIdMayBeSmi(EBX, EAX);
- Label equal, not_equal;
- EquivalentClassIds(assembler, normal_ir_body, &equal, ¬_equal, EDI, EBX,
- EAX, /* testing_instance_cids = */ true);
+ Label equal_may_be_generic, equal, not_equal;
+ EquivalentClassIds(assembler, normal_ir_body, &equal_may_be_generic, &equal,
+ ¬_equal, EDI, EBX, EAX,
+ /* testing_instance_cids = */ true);
+
+ __ Bind(&equal_may_be_generic);
+ // Classes are equivalent and neither is a closure class.
+ // Check if there are no type arguments. In this case we can return true.
+ // Otherwise fall through into the runtime to handle comparison.
+ __ LoadClassById(EAX, EDI);
+ __ movl(
+ EAX,
+ FieldAddress(
+ EAX,
+ target::Class::host_type_arguments_field_offset_in_words_offset()));
+ __ cmpl(EAX, Immediate(target::Class::kNoTypeArguments));
+ __ j(EQUAL, &equal);
// Compare type arguments, host_type_arguments_field_offset_in_words in EAX.
__ movl(EDI, Address(ESP, +1 * target::kWordSize));
@@ -1465,7 +1461,7 @@
void AsmIntrinsifier::Type_equality(Assembler* assembler,
Label* normal_ir_body) {
- Label equal, not_equal, equiv_cids, check_legacy;
+ Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
__ movl(EDI, Address(ESP, +1 * target::kWordSize));
__ movl(EBX, Address(ESP, +2 * target::kWordSize));
@@ -1484,9 +1480,11 @@
__ movl(EDX, FieldAddress(EBX, target::Type::type_class_id_offset()));
__ SmiUntag(EDX);
// We are not testing instance cids, but type class cids of Type instances.
- EquivalentClassIds(assembler, normal_ir_body, &equiv_cids, ¬_equal, ECX,
- EDX, EAX, /* testing_instance_cids = */ false);
+ EquivalentClassIds(assembler, normal_ir_body, &equiv_cids_may_be_generic,
+ &equiv_cids, ¬_equal, ECX, EDX, EAX,
+ /* testing_instance_cids = */ false);
+ __ Bind(&equiv_cids_may_be_generic);
// Compare type arguments in Type instances.
__ movl(ECX, FieldAddress(EDI, target::Type::arguments_offset()));
__ movl(EDX, FieldAddress(EBX, target::Type::arguments_offset()));
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 8a57264..0b84166 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -1212,20 +1212,19 @@
}
// Compares cid1 and cid2 to see if they're syntactically equivalent. If this
-// can be determined by this fast path, it jumps to either equal or not_equal,
-// if equal but belonging to a generic class, it falls through with the scratch
-// register containing host_type_arguments_field_offset_in_words,
-// otherwise it jumps to normal_ir_body. May clobber scratch.
+// can be determined by this fast path, it jumps to either equal_* or not_equal.
+// If classes are equivalent but may be generic, then jumps to
+// equal_may_be_generic. Clobbers scratch.
static void EquivalentClassIds(Assembler* assembler,
Label* normal_ir_body,
- Label* equal,
+ Label* equal_may_be_generic,
+ Label* equal_not_generic,
Label* not_equal,
Register cid1,
Register cid2,
Register scratch,
bool testing_instance_cids) {
- Label different_cids, equal_cids_but_generic, not_integer,
- not_integer_or_string, not_integer_or_string_or_list;
+ Label not_integer, not_integer_or_string, not_integer_or_string_or_list;
// Check if left hand side is a closure. Closures are handled in the runtime.
__ cmpq(cid1, Immediate(kClosureCid));
@@ -1235,25 +1234,11 @@
// considered equivalent (e.g. multiple string implementation classes map to a
// single String type).
__ cmpq(cid1, cid2);
- __ j(NOT_EQUAL, &different_cids);
-
- // Types have the same class and neither is a closure type.
- // Check if there are no type arguments. In this case we can return true.
- // Otherwise fall through into the runtime to handle comparison.
- __ LoadClassById(scratch, cid1);
- __ movl(
- scratch,
- FieldAddress(
- scratch,
- target::Class::host_type_arguments_field_offset_in_words_offset()));
- __ cmpl(scratch, Immediate(target::Class::kNoTypeArguments));
- __ j(NOT_EQUAL, &equal_cids_but_generic);
- __ jmp(equal);
+ __ j(EQUAL, equal_may_be_generic);
// Class ids are different. Check if we are comparing two string types (with
// different representations), two integer types, two list types or two type
// types.
- __ Bind(&different_cids);
__ cmpq(cid1, Immediate(kNumPredefinedCids));
__ j(ABOVE_EQUAL, not_equal);
@@ -1263,7 +1248,7 @@
// First type is an integer. Check if the second is an integer too.
__ movq(scratch, cid2);
- JumpIfInteger(assembler, scratch, equal);
+ JumpIfInteger(assembler, scratch, equal_not_generic);
// Integer types are only equivalent to other integer types.
__ jmp(not_equal);
@@ -1275,7 +1260,7 @@
// First type is a String. Check if the second is a String too.
__ movq(scratch, cid2);
- JumpIfString(assembler, scratch, equal);
+ JumpIfString(assembler, scratch, equal_not_generic);
// String types are only equivalent to other String types.
__ jmp(not_equal);
@@ -1290,24 +1275,21 @@
JumpIfNotList(assembler, scratch, not_equal);
ASSERT(compiler::target::Array::type_arguments_offset() ==
compiler::target::GrowableObjectArray::type_arguments_offset());
- __ movq(scratch,
- Immediate(compiler::target::Array::type_arguments_offset()));
- __ jmp(&equal_cids_but_generic, Assembler::kNearJump);
+ __ jmp(equal_may_be_generic);
__ Bind(¬_integer_or_string_or_list);
// Check if the first type is a Type. If it is not then types are not
// equivalent because they have different class ids and they are not String
// or integer or List or Type.
- JumpIfNotType(assembler, cid1, not_equal);
+ __ movq(scratch, cid1);
+ JumpIfNotType(assembler, scratch, not_equal);
// First type is a Type. Check if the second is a Type too.
- JumpIfType(assembler, cid2, equal);
+ __ movq(scratch, cid2);
+ JumpIfType(assembler, scratch, equal_not_generic);
// Type types are only equivalent to other Type types.
__ jmp(not_equal);
}
-
- // The caller must compare the type arguments.
- __ Bind(&equal_cids_but_generic);
}
void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
@@ -1318,9 +1300,23 @@
__ movq(RAX, Address(RSP, +2 * target::kWordSize));
__ LoadClassIdMayBeSmi(RDX, RAX);
- Label equal, not_equal;
- EquivalentClassIds(assembler, normal_ir_body, &equal, ¬_equal, RCX, RDX,
- RAX, /* testing_instance_cids = */ true);
+ Label equal_may_be_generic, equal, not_equal;
+ EquivalentClassIds(assembler, normal_ir_body, &equal_may_be_generic, &equal,
+ ¬_equal, RCX, RDX, RAX,
+ /* testing_instance_cids = */ true);
+
+ __ Bind(&equal_may_be_generic);
+ // Classes are equivalent and neither is a closure class.
+ // Check if there are no type arguments. In this case we can return true.
+ // Otherwise fall through into the runtime to handle comparison.
+ __ LoadClassById(RAX, RCX);
+ __ movl(
+ RAX,
+ FieldAddress(
+ RAX,
+ target::Class::host_type_arguments_field_offset_in_words_offset()));
+ __ cmpl(RAX, Immediate(target::Class::kNoTypeArguments));
+ __ j(EQUAL, &equal);
// Compare type arguments, host_type_arguments_field_offset_in_words in RAX.
__ movq(RCX, Address(RSP, +1 * target::kWordSize));
@@ -1370,7 +1366,7 @@
void AsmIntrinsifier::Type_equality(Assembler* assembler,
Label* normal_ir_body) {
- Label equal, not_equal, equiv_cids, check_legacy;
+ Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
__ movq(RCX, Address(RSP, +1 * target::kWordSize));
__ movq(RDX, Address(RSP, +2 * target::kWordSize));
@@ -1391,9 +1387,11 @@
FieldAddress(RDX, target::Type::type_class_id_offset()));
__ SmiUntag(RSI);
// We are not testing instance cids, but type class cids of Type instances.
- EquivalentClassIds(assembler, normal_ir_body, &equiv_cids, ¬_equal, RDI,
- RSI, RAX, /* testing_instance_cids = */ false);
+ EquivalentClassIds(assembler, normal_ir_body, &equiv_cids_may_be_generic,
+ &equiv_cids, ¬_equal, RDI, RSI, RAX,
+ /* testing_instance_cids = */ false);
+ __ Bind(&equiv_cids_may_be_generic);
// Compare type arguments in Type instances.
__ LoadCompressed(RDI, FieldAddress(RCX, target::Type::arguments_offset()));
__ LoadCompressed(RSI, FieldAddress(RDX, target::Type::arguments_offset()));
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index ac65f6d..6d300fb 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -83,12 +83,11 @@
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sys_icache_invalidate.3.html
#if defined(DART_HOST_OS_IOS)
sys_icache_invalidate(reinterpret_cast<void*>(start), size);
-#elif defined(__linux__) && !defined(ANDROID)
- extern void __clear_cache(char*, char*);
+#elif defined(DART_HOST_OS_LINUX)
char* beg = reinterpret_cast<char*>(start);
char* end = reinterpret_cast<char*>(start + size);
- ::__clear_cache(beg, end);
-#elif defined(ANDROID)
+ __builtin___clear_cache(beg, end);
+#elif defined(DART_HOST_OS_ANDROID)
cacheflush(start, start + size, 0);
#else
#error FlushICache only tested/supported on Linux, Android and iOS
diff --git a/runtime/vm/cpu_arm64.cc b/runtime/vm/cpu_arm64.cc
index d193d23..23e9fee 100644
--- a/runtime/vm/cpu_arm64.cc
+++ b/runtime/vm/cpu_arm64.cc
@@ -45,10 +45,9 @@
#if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
sys_icache_invalidate(reinterpret_cast<void*>(start), size);
#elif defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX)
- extern void __clear_cache(char*, char*);
char* beg = reinterpret_cast<char*>(start);
char* end = reinterpret_cast<char*>(start + size);
- ::__clear_cache(beg, end);
+ __builtin___clear_cache(beg, end);
#elif defined(DART_HOST_OS_FUCHSIA)
zx_status_t result = zx_cache_flush(reinterpret_cast<const void*>(start),
size, ZX_CACHE_FLUSH_INSN);
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index fc47a29..bffde99 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -556,11 +556,12 @@
/// Terminates the current isolate synchronously.
///
- /// This operations is potentially dangerous and should be used judiciously.
- /// The isolate stops operating *immediately*. It throws if optional [message]
- /// does not adhere to the limitation on what can be send from one isolate to
- /// another. It also throws if a [finalMessagePort] is associated with an
- /// isolate spawned outside of current isolate group, spawned via [spawnUri].
+ /// This operation is potentially dangerous and should be used judiciously.
+ /// The isolate stops operating *immediately*. It throws if the optional
+ /// [message] does not adhere to the limitations on what can be sent from one
+ /// isolate to another. It also throws if a [finalMessagePort] is associated
+ /// with an isolate spawned outside of current isolate group, spawned via
+ /// [spawnUri].
///
/// If successful, a call to this method does not return. Pending `finally`
/// blocks are not executed, control flow will not go back to the event loop,
@@ -574,10 +575,10 @@
/// the current isolate. The isolate terminates immediately after
/// that [SendPort.send] call returns.
///
- /// (If the port is a native port, one provided by [ReceivePort.sendPort]
- /// or [RawReceivePort.sendPort], the system may be able to send this final
+ /// If the port is a native port -- one provided by [ReceivePort.sendPort] or
+ /// [RawReceivePort.sendPort] -- the system may be able to send this final
/// message more efficiently than normal port communication between live
- /// isolates.)
+ /// isolates.
external static Never exit([SendPort? finalMessagePort, Object? message]);
}
diff --git a/tests/language/const/constant_type_variable_error_test.dart b/tests/language/const/constant_type_variable_error_test.dart
index c0e7770..6e2438b 100644
--- a/tests/language/const/constant_type_variable_error_test.dart
+++ b/tests/language/const/constant_type_variable_error_test.dart
@@ -8,41 +8,49 @@
// constant expressions or potentially constant type expressions.
class A<X> {
- final Object x1, x2, x3, x4, x5, x6, x7, x8, x9;
+ final Object x1, x2, x3, x4, x5, x6, x7, x8;
const A()
: x1 = const [X],
//^
// [analyzer] unspecified
- // [cfe] unspecified
+ // ^
+ // [cfe] Type variables can't be used as constants.
x2 = const <X>[],
//^
// [analyzer] unspecified
- // [cfe] unspecified
+ // ^
+ // [cfe] Type variables can't be used as constants.
x3 = const {X},
//^
// [analyzer] unspecified
- // [cfe] unspecified
+ // ^
+ // [cfe] Type variables can't be used as constants.
x4 = const <X>{},
//^
// [analyzer] unspecified
- // [cfe] unspecified
+ // ^
+ // [cfe] Type variables can't be used as constants.
x5 = const {X: null},
//^
// [analyzer] unspecified
- // [cfe] unspecified
+ // ^
+ // [cfe] Type variables can't be used as constants.
x6 = const <X, String?>{},
//^
// [analyzer] unspecified
- // [cfe] unspecified
+ // ^
+ // [cfe] Type variables can't be used as constants.
x7 = const B<X>(),
//^
// [analyzer] unspecified
- // [cfe] unspecified
+ // ^
+ // [cfe] Type variables can't be used as constants.
x8 = const C(X);
//^
// [analyzer] unspecified
- // [cfe] unspecified
+ // ^
+ // [cfe] Type variables can't be used as constants.
}
class B<X> {
diff --git a/tools/VERSION b/tools/VERSION
index d089db4..c6199a3 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 211
+PRERELEASE 212
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/gn.py b/tools/gn.py
index cecd030..3090333 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -212,6 +212,7 @@
# Use tcmalloc only when targeting Linux and when not using ASAN.
gn_args['dart_use_tcmalloc'] = ((gn_args['target_os'] == 'linux') and
+ (gn_args['target_cpu'] != 'arm') and
sanitizer == 'none')
if gn_args['target_os'] == 'linux':