Version 2.13.0-144.0.dev
Merge commit '33cabf43133fe2cece89bca00cc84171a5fd1d2a' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 6fffc20..48079d1 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
"constraint, update this by running tools/generate_package_config.dart."
],
"configVersion": 2,
- "generated": "2021-03-12T09:00:31.497265",
+ "generated": "2021-03-15T10:48:35.022974",
"generator": "tools/generate_package_config.dart",
"packages": [
{
@@ -220,7 +220,7 @@
"name": "dart_style",
"rootUri": "../third_party/pkg_tested/dart_style",
"packageUri": "lib/",
- "languageVersion": "2.9"
+ "languageVersion": "2.12"
},
{
"name": "dartdev",
@@ -695,13 +695,13 @@
"name": "test_descriptor",
"rootUri": "../third_party/pkg/test_descriptor",
"packageUri": "lib/",
- "languageVersion": "2.0"
+ "languageVersion": "2.12"
},
{
"name": "test_process",
"rootUri": "../third_party/pkg/test_process",
"packageUri": "lib/",
- "languageVersion": "2.0"
+ "languageVersion": "2.12"
},
{
"name": "test_reflective_loader",
diff --git a/DEPS b/DEPS
index 09155e8..17c6ed1 100644
--- a/DEPS
+++ b/DEPS
@@ -98,7 +98,7 @@
# and land the review.
#
# For more details, see https://github.com/dart-lang/sdk/issues/30164
- "dart_style_tag": "1.3.11", # Please see the note above before updating.
+ "dart_style_tag": "a1d65dd9c4b83c9702ba409465879b94caeb04ea",
"chromedriver_tag": "83.0.4103.39",
"dartdoc_rev" : "174021f3d76c2a8500b54977c80f32c5bbc099f1",
@@ -155,8 +155,8 @@
"stream_channel_tag": "d7251e61253ec389ee6e045ee1042311bced8f1d",
"string_scanner_rev": "1b63e6e5db5933d7be0a45da6e1129fe00262734",
"sync_http_rev": "b59c134f2e34d12acac110d4f17f83e5a7db4330",
- "test_descriptor_tag": "1.1.1",
- "test_process_tag": "1.0.3",
+ "test_descriptor_tag": "2.0.0",
+ "test_process_tag": "2.0.0",
"term_glyph_rev": "6a0f9b6fb645ba75e7a00a4e20072678327a0347",
"test_reflective_loader_rev": "54e930a11c372683792e22bddad79197728c91ce",
"test_rev": "e673623f45d75ccec750d35271b0b4d1423e9fac",
diff --git a/benchmarks/FfiMemory/dart/FfiMemory.dart b/benchmarks/FfiMemory/dart/FfiMemory.dart
index 1b822fb..26ff8e7 100644
--- a/benchmarks/FfiMemory/dart/FfiMemory.dart
+++ b/benchmarks/FfiMemory/dart/FfiMemory.dart
@@ -390,6 +390,30 @@
}
}
+class PointerUint32Unaligned extends BenchmarkBase {
+ Pointer<Uint32> pointer = nullptr;
+ Pointer<Uint32> unalignedPointer = nullptr;
+ PointerUint32Unaligned() : super('FfiMemory.PointerUint32Unaligned');
+
+ @override
+ void setup() {
+ pointer = calloc(N + 1);
+ unalignedPointer = Pointer.fromAddress(pointer.address + 1);
+ }
+
+ @override
+ void teardown() => calloc.free(pointer);
+
+ @override
+ void run() {
+ doStoreUint32(unalignedPointer, N);
+ final int x = doLoadUint32(unalignedPointer, N);
+ if (x != N) {
+ throw Exception('$name: Unexpected result: $x');
+ }
+ }
+}
+
class PointerInt64 extends BenchmarkBase {
Pointer<Int64> pointer = nullptr;
PointerInt64() : super('FfiMemory.PointerInt64');
@@ -527,6 +551,7 @@
() => PointerUint16(),
() => PointerInt32(),
() => PointerUint32(),
+ () => PointerUint32Unaligned(),
() => PointerInt64(),
() => PointerInt64Mint(),
() => PointerUint64(),
diff --git a/benchmarks/FfiMemory/dart2/FfiMemory.dart b/benchmarks/FfiMemory/dart2/FfiMemory.dart
index f788959..8ed6302 100644
--- a/benchmarks/FfiMemory/dart2/FfiMemory.dart
+++ b/benchmarks/FfiMemory/dart2/FfiMemory.dart
@@ -390,6 +390,30 @@
}
}
+class PointerUint32Unaligned extends BenchmarkBase {
+ Pointer<Float> pointer;
+ Pointer<Uint32> unalignedPointer;
+ PointerUint32Unaligned() : super('FfiMemory.PointerUint32Unaligned');
+
+ @override
+ void setup() {
+ pointer = calloc(N + 1);
+ unalignedPointer = Pointer.fromAddress(pointer.address + 1);
+ }
+
+ @override
+ void teardown() => calloc.free(pointer);
+
+ @override
+ void run() {
+ doStoreUint32(unalignedPointer, N);
+ final int x = doLoadUint32(unalignedPointer, N);
+ if (x != N) {
+ throw Exception('$name: Unexpected result: $x');
+ }
+ }
+}
+
class PointerInt64 extends BenchmarkBase {
Pointer<Int64> pointer;
PointerInt64() : super('FfiMemory.PointerInt64');
@@ -527,6 +551,7 @@
() => PointerUint16(),
() => PointerInt32(),
() => PointerUint32(),
+ () => PointerUint32Unaligned(),
() => PointerInt64(),
() => PointerInt64Mint(),
() => PointerUint64(),
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/for_in_loop_type_not_iterable_nullability_error.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/for_in_loop_type_not_iterable_nullability_error.dart
index 639222f..3b89bde7 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/for_in_loop_type_not_iterable_nullability_error.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/for_in_loop_type_not_iterable_nullability_error.dart
@@ -11,9 +11,80 @@
List<int>? bad;
}
-test(C1 c) {
+forStatement(C1 c) {
if (c.bad == null) return;
for (var x
in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
. /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad) {}
}
+
+forElementInList(C1 c) {
+ if (c.bad == null) return;
+ [
+ for (var x
+ in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+ null
+ ];
+}
+
+forElementInSet(C1 c) {
+ if (c.bad == null) return;
+ <dynamic>{
+ for (var x
+ in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+ null
+ };
+}
+
+forElementInMap(C1 c) {
+ if (c.bad == null) return;
+ <dynamic, dynamic>{
+ for (var x
+ in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+ null,
+ null
+ };
+}
+
+forElementInAmbiguousSet_resolvableDuringParsing(C1 c) {
+ if (c.bad == null) return;
+ ({
+ for (var x
+ in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+ null
+ });
+}
+
+forElementInAmbiguousMap_resolvableDuringParsing(C1 c) {
+ if (c.bad == null) return;
+ ({
+ for (var x
+ in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+ null: null
+ });
+}
+
+forElementInAmbiguousSet_notResolvableDuringParsing(C1 c, List list) {
+ if (c.bad == null) return;
+ ({
+ for (var x
+ in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+ ...list
+ });
+}
+
+forElementInAmbiguousMap_notResolvableDuringParsing(C1 c, Map map) {
+ if (c.bad == null) return;
+ ({
+ for (var x
+ in /*analyzer.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ c
+ . /*cfe.notPromoted(propertyNotPromoted(target: member:C1.bad, type: List<int>?))*/ bad)
+ ...map
+ });
+}
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
index c67d3f7..d55238b 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
@@ -1573,3 +1573,135 @@
@override
String toString() => jsonEncoder.convert(toJson());
}
+
+class SnippetTextEdit implements TextEdit, ToJsonable {
+ static const jsonHandler =
+ LspJsonHandler(SnippetTextEdit.canParse, SnippetTextEdit.fromJson);
+
+ SnippetTextEdit(
+ {@required this.insertTextFormat,
+ @required this.range,
+ @required this.newText}) {
+ if (insertTextFormat == null) {
+ throw 'insertTextFormat is required but was not provided';
+ }
+ if (range == null) {
+ throw 'range is required but was not provided';
+ }
+ if (newText == null) {
+ throw 'newText is required but was not provided';
+ }
+ }
+ static SnippetTextEdit fromJson(Map<String, dynamic> json) {
+ final insertTextFormat = json['insertTextFormat'] != null
+ ? InsertTextFormat.fromJson(json['insertTextFormat'])
+ : null;
+ final range = json['range'] != null ? Range.fromJson(json['range']) : null;
+ final newText = json['newText'];
+ return SnippetTextEdit(
+ insertTextFormat: insertTextFormat, range: range, newText: newText);
+ }
+
+ final InsertTextFormat insertTextFormat;
+
+ /// The string to be inserted. For delete operations use an empty string.
+ final String newText;
+
+ /// The range of the text document to be manipulated. To insert text into a
+ /// document create a range where start === end.
+ final Range range;
+
+ Map<String, dynamic> toJson() {
+ var __result = <String, dynamic>{};
+ __result['insertTextFormat'] = insertTextFormat?.toJson() ??
+ (throw 'insertTextFormat is required but was not set');
+ __result['range'] =
+ range?.toJson() ?? (throw 'range is required but was not set');
+ __result['newText'] =
+ newText ?? (throw 'newText is required but was not set');
+ return __result;
+ }
+
+ static bool canParse(Object obj, LspJsonReporter reporter) {
+ if (obj is Map<String, dynamic>) {
+ reporter.push('insertTextFormat');
+ try {
+ if (!obj.containsKey('insertTextFormat')) {
+ reporter.reportError('must not be undefined');
+ return false;
+ }
+ if (obj['insertTextFormat'] == null) {
+ reporter.reportError('must not be null');
+ return false;
+ }
+ if (!(InsertTextFormat.canParse(obj['insertTextFormat'], reporter))) {
+ reporter.reportError('must be of type InsertTextFormat');
+ return false;
+ }
+ } finally {
+ reporter.pop();
+ }
+ reporter.push('range');
+ try {
+ if (!obj.containsKey('range')) {
+ reporter.reportError('must not be undefined');
+ return false;
+ }
+ if (obj['range'] == null) {
+ reporter.reportError('must not be null');
+ return false;
+ }
+ if (!(Range.canParse(obj['range'], reporter))) {
+ reporter.reportError('must be of type Range');
+ return false;
+ }
+ } finally {
+ reporter.pop();
+ }
+ reporter.push('newText');
+ try {
+ if (!obj.containsKey('newText')) {
+ reporter.reportError('must not be undefined');
+ return false;
+ }
+ if (obj['newText'] == null) {
+ reporter.reportError('must not be null');
+ return false;
+ }
+ if (!(obj['newText'] is String)) {
+ reporter.reportError('must be of type String');
+ return false;
+ }
+ } finally {
+ reporter.pop();
+ }
+ return true;
+ } else {
+ reporter.reportError('must be of type SnippetTextEdit');
+ return false;
+ }
+ }
+
+ @override
+ bool operator ==(Object other) {
+ if (other is SnippetTextEdit && other.runtimeType == SnippetTextEdit) {
+ return insertTextFormat == other.insertTextFormat &&
+ range == other.range &&
+ newText == other.newText &&
+ true;
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ var hash = 0;
+ hash = JenkinsSmiHash.combine(hash, insertTextFormat.hashCode);
+ hash = JenkinsSmiHash.combine(hash, range.hashCode);
+ hash = JenkinsSmiHash.combine(hash, newText.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+
+ @override
+ String toString() => jsonEncoder.convert(toJson());
+}
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index 215bf08..d3c551b 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -30666,14 +30666,17 @@
? OptionalVersionedTextDocumentIdentifier.fromJson(json['textDocument'])
: null;
final edits = json['edits']
- ?.map((item) => TextEdit.canParse(item, nullLspJsonReporter)
- ? Either2<TextEdit, AnnotatedTextEdit>.t1(
- item != null ? TextEdit.fromJson(item) : null)
+ ?.map((item) => SnippetTextEdit.canParse(item, nullLspJsonReporter)
+ ? Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t1(
+ item != null ? SnippetTextEdit.fromJson(item) : null)
: (AnnotatedTextEdit.canParse(item, nullLspJsonReporter)
- ? Either2<TextEdit, AnnotatedTextEdit>.t2(
+ ? Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t2(
item != null ? AnnotatedTextEdit.fromJson(item) : null)
- : (throw '''${item} was not one of (TextEdit, AnnotatedTextEdit)''')))
- ?.cast<Either2<TextEdit, AnnotatedTextEdit>>()
+ : (TextEdit.canParse(item, nullLspJsonReporter)
+ ? Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t3(
+ item != null ? TextEdit.fromJson(item) : null)
+ : (throw '''${item} was not one of (SnippetTextEdit, AnnotatedTextEdit, TextEdit)'''))))
+ ?.cast<Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>>()
?.toList();
return TextDocumentEdit(textDocument: textDocument, edits: edits);
}
@@ -30681,7 +30684,7 @@
/// The edits to be applied.
/// @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the
/// client capability `workspace.workspaceEdit.changeAnnotationSupport`
- final List<Either2<TextEdit, AnnotatedTextEdit>> edits;
+ final List<Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>> edits;
/// The text document to change.
final OptionalVersionedTextDocumentIdentifier textDocument;
@@ -30726,10 +30729,12 @@
return false;
}
if (!((obj['edits'] is List &&
- (obj['edits'].every((item) => (TextEdit.canParse(item, reporter) ||
- AnnotatedTextEdit.canParse(item, reporter))))))) {
+ (obj['edits'].every((item) =>
+ (SnippetTextEdit.canParse(item, reporter) ||
+ AnnotatedTextEdit.canParse(item, reporter) ||
+ TextEdit.canParse(item, reporter))))))) {
reporter.reportError(
- 'must be of type List<Either2<TextEdit, AnnotatedTextEdit>>');
+ 'must be of type List<Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>>');
return false;
}
} finally {
@@ -30749,8 +30754,9 @@
listEqual(
edits,
other.edits,
- (Either2<TextEdit, AnnotatedTextEdit> a,
- Either2<TextEdit, AnnotatedTextEdit> b) =>
+ (Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit> a,
+ Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>
+ b) =>
a == b) &&
true;
}
@@ -31777,6 +31783,9 @@
if (AnnotatedTextEdit.canParse(json, nullLspJsonReporter)) {
return AnnotatedTextEdit.fromJson(json);
}
+ if (SnippetTextEdit.canParse(json, nullLspJsonReporter)) {
+ return SnippetTextEdit.fromJson(json);
+ }
final range = json['range'] != null ? Range.fromJson(json['range']) : null;
final newText = json['newText'];
return TextEdit(range: range, newText: newText);
diff --git a/pkg/analysis_server/lib/src/lsp/client_capabilities.dart b/pkg/analysis_server/lib/src/lsp/client_capabilities.dart
index 2c16de4..1047961 100644
--- a/pkg/analysis_server/lib/src/lsp/client_capabilities.dart
+++ b/pkg/analysis_server/lib/src/lsp/client_capabilities.dart
@@ -78,6 +78,7 @@
final Set<SymbolKind> workspaceSymbolKinds;
final Set<CompletionItemKind> completionItemKinds;
final Set<InsertTextMode> completionInsertTextModes;
+ final bool experimentalSnippetTextEdit;
LspClientCapabilities(this.raw)
: applyEdit = raw?.workspace?.applyEdit ?? false,
@@ -125,7 +126,10 @@
workDoneProgress = raw.window?.workDoneProgress ?? false,
workspaceSymbolKinds = _listToSet(
raw?.workspace?.symbol?.symbolKind?.valueSet,
- defaults: defaultSupportedSymbolKinds);
+ defaults: defaultSupportedSymbolKinds),
+ experimentalSnippetTextEdit =
+ raw.experimental is Map<String, dynamic> &&
+ raw.experimental['snippetTextEdit'] == true;
static Set<MarkupKind> _completionDocumentationFormats(
ClientCapabilities raw) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
index 6ac4547..581c499 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
@@ -87,7 +87,7 @@
return fileModifiedError;
}
- final edit = createWorkspaceEdit(server, change.edits);
+ final edit = createWorkspaceEdit(server, change);
return await sendWorkspaceEditToClient(edit);
} on InconsistentAnalysisException {
return fileModifiedError;
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index f51367f..f7afd25 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -143,7 +143,7 @@
title: assist.change.message,
kind: toCodeActionKind(assist.change.id, CodeActionKind.Refactor),
diagnostics: const [],
- edit: createWorkspaceEdit(server, assist.change.edits),
+ edit: createWorkspaceEdit(server, assist.change),
);
}
@@ -156,7 +156,7 @@
title: fix.change.message,
kind: toCodeActionKind(fix.change.id, CodeActionKind.QuickFix),
diagnostics: [diagnostic],
- edit: createWorkspaceEdit(server, fix.change.edits),
+ edit: createWorkspaceEdit(server, fix.change),
);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index 3c3ea2c..cafa2b6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -146,7 +146,8 @@
// a command that the client will call to apply those edits later.
Command command;
if (otherFilesChanges.isNotEmpty) {
- final workspaceEdit = createWorkspaceEdit(server, otherFilesChanges);
+ final workspaceEdit =
+ createPlainWorkspaceEdit(server, otherFilesChanges);
command = Command(
title: 'Add import',
command: Commands.sendWorkspaceEdit,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
index eae5c8c..d1c3aca 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
@@ -187,7 +187,7 @@
return fileModifiedError;
}
- final workspaceEdit = createWorkspaceEdit(server, change.edits);
+ final workspaceEdit = createWorkspaceEdit(server, change);
return success(workspaceEdit);
});
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
index 2beb369..3d32e86 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_will_rename_files.dart
@@ -53,7 +53,7 @@
}
final change = await refactoring.createChange();
- final edit = createWorkspaceEdit(server, change.edits);
+ final edit = createWorkspaceEdit(server, change);
return success(edit);
}
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 9e59ec6..a409c06 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -108,10 +108,12 @@
return output.join('');
}
+/// Creates a [lsp.WorkspaceEdit] from simple [server.SourceFileEdit]s.
+///
/// Note: This code will fetch the version of each document being modified so
/// it's important to call this immediately after computing edits to ensure
/// the document is not modified before the version number is read.
-lsp.WorkspaceEdit createWorkspaceEdit(
+lsp.WorkspaceEdit createPlainWorkspaceEdit(
lsp.LspAnalysisServer server, List<server.SourceFileEdit> edits) {
return toWorkspaceEdit(
server.clientCapabilities,
@@ -126,6 +128,52 @@
.toList());
}
+/// Creates a [lsp.WorkspaceEdit] from a [server.SourceChange] that can include
+/// experimental [server.SnippetTextEdit]s if the client has indicated support
+/// for these in the experimental section of their client capabilities.
+///
+/// Note: This code will fetch the version of each document being modified so
+/// it's important to call this immediately after computing edits to ensure
+/// the document is not modified before the version number is read.
+lsp.WorkspaceEdit createWorkspaceEdit(
+ lsp.LspAnalysisServer server, server.SourceChange change) {
+ // In order to return snippets, we must ensure we are only modifying a single
+ // existing file with a single edit and that there is a linked edit group with
+ // only one position and no suggestions.
+ if (!server.clientCapabilities.experimentalSnippetTextEdit ||
+ change.edits.length != 1 ||
+ change.edits.first.fileStamp == -1 || // new file
+ change.edits.first.edits.length != 1 ||
+ change.linkedEditGroups.isEmpty ||
+ change.linkedEditGroups.first.positions.length != 1 ||
+ change.linkedEditGroups.first.suggestions.isNotEmpty) {
+ return createPlainWorkspaceEdit(server, change.edits);
+ }
+
+ // Additionally, the selection must fall within the edit offset.
+ final edit = change.edits.first.edits.first;
+ final selectionOffset = change.linkedEditGroups.first.positions.first.offset;
+ final selectionLength = change.linkedEditGroups.first.length;
+
+ if (selectionOffset < edit.offset ||
+ selectionOffset + selectionLength > edit.offset + edit.length) {
+ return createPlainWorkspaceEdit(server, change.edits);
+ }
+
+ return toWorkspaceEdit(
+ server.clientCapabilities,
+ change.edits
+ .map((e) => FileEditInformation(
+ server.getVersionedDocumentIdentifier(e.file),
+ server.getLineInfo(e.file),
+ e.edits,
+ selectionOffsetRelative: selectionOffset - edit.offset,
+ selectionLength: selectionLength,
+ newFile: e.fileStamp == -1,
+ ))
+ .toList());
+}
+
lsp.CompletionItemKind declarationKindToCompletionItemKind(
Set<lsp.CompletionItemKind> supportedCompletionKinds,
dec.DeclarationKind kind,
@@ -1224,6 +1272,21 @@
);
}
+lsp.SnippetTextEdit toSnippetTextEdit(
+ LspClientCapabilities capabilities,
+ server.LineInfo lineInfo,
+ server.SourceEdit edit,
+ int selectionOffsetRelative,
+ int selectionLength) {
+ assert(selectionOffsetRelative != null);
+ return lsp.SnippetTextEdit(
+ insertTextFormat: lsp.InsertTextFormat.Snippet,
+ range: toRange(lineInfo, edit.offset, edit.length),
+ newText: buildSnippetStringWithTabStops(
+ edit.replacement, [selectionOffsetRelative, selectionLength ?? 0]),
+ );
+}
+
ErrorOr<server.SourceRange> toSourceRange(
server.LineInfo lineInfo, Range range) {
if (range == null) {
@@ -1247,14 +1310,33 @@
return success(server.SourceRange(startOffset, endOffset - startOffset));
}
-lsp.TextDocumentEdit toTextDocumentEdit(FileEditInformation edit) {
+lsp.TextDocumentEdit toTextDocumentEdit(
+ LspClientCapabilities capabilities, FileEditInformation edit) {
return lsp.TextDocumentEdit(
- textDocument: edit.doc,
- edits: edit.edits
- .map((e) => Either2<lsp.TextEdit, lsp.AnnotatedTextEdit>.t1(
- toTextEdit(edit.lineInfo, e)))
- .toList(),
- );
+ textDocument: edit.doc,
+ edits: edit.edits
+ .map((e) => toTextDocumentEditEdit(capabilities, edit.lineInfo, e,
+ selectionOffsetRelative: edit.selectionOffsetRelative,
+ selectionLength: edit.selectionLength))
+ .toList());
+}
+
+Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit, lsp.TextEdit>
+ toTextDocumentEditEdit(
+ LspClientCapabilities capabilities,
+ server.LineInfo lineInfo,
+ server.SourceEdit edit, {
+ int selectionOffsetRelative,
+ int selectionLength,
+}) {
+ if (!capabilities.experimentalSnippetTextEdit ||
+ selectionOffsetRelative == null) {
+ return Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit, lsp.TextEdit>.t3(
+ toTextEdit(lineInfo, edit));
+ }
+ return Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit, lsp.TextEdit>.t1(
+ toSnippetTextEdit(capabilities, lineInfo, edit, selectionOffsetRelative,
+ selectionLength));
}
lsp.TextEdit toTextEdit(server.LineInfo lineInfo, server.SourceEdit edit) {
@@ -1286,7 +1368,7 @@
changes.add(createUnion);
}
- final textDocEdit = toTextDocumentEdit(edit);
+ final textDocEdit = toTextDocumentEdit(capabilities, edit);
final textDocEditUnion = Either4<lsp.TextDocumentEdit, lsp.CreateFile,
lsp.RenameFile, lsp.DeleteFile>.t1(textDocEdit);
changes.add(textDocEditUnion);
diff --git a/pkg/analysis_server/lib/src/lsp/source_edits.dart b/pkg/analysis_server/lib/src/lsp/source_edits.dart
index e1cc013..d97576f 100644
--- a/pkg/analysis_server/lib/src/lsp/source_edits.dart
+++ b/pkg/analysis_server/lib/src/lsp/source_edits.dart
@@ -307,6 +307,12 @@
final List<server.SourceEdit> edits;
final bool newFile;
+ /// The selection offset, relative to the edit.
+ final int selectionOffsetRelative;
+ final int selectionLength;
+
FileEditInformation(this.doc, this.lineInfo, this.edits,
- {this.newFile = false});
+ {this.newFile = false,
+ this.selectionOffsetRelative,
+ this.selectionLength});
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 30182b7..5f512c5 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -38,7 +38,6 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
@@ -338,7 +337,7 @@
@override
bool get inConstantContext {
var entity = target.entity;
- return entity is ExpressionImpl && entity.inConstantContext;
+ return entity is Expression && entity.inConstantContext;
}
@override
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
index c8c935b..b2d6d98 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/source/source_range.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer_plugin/utilities/assist/assist.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
@@ -143,8 +142,7 @@
@override
List<String> get _leadingLines {
- var keyword =
- (widgetExpr as ExpressionImpl).inConstantContext ? '' : ' const';
+ var keyword = widgetExpr.inConstantContext ? '' : ' const';
return ['padding:$keyword EdgeInsets.all(8.0),'];
}
diff --git a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
index 03def9f..b70a2c2 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -2,7 +2,9 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -16,6 +18,15 @@
@reflectiveTest
class AssistsCodeActionsTest extends AbstractCodeActionsTest {
+ @override
+ void setUp() {
+ super.setUp();
+ writePackageConfig(
+ projectFolderPath,
+ flutter: true,
+ );
+ }
+
Future<void> test_appliesCorrectEdits_withDocumentChangesSupport() async {
// This code should get an assist to add a show combinator.
const content = '''
@@ -107,4 +118,171 @@
await getCodeActions(pubspecFileUri.toString(), range: startOfDocRange);
expect(codeActions, isEmpty);
}
+
+ Future<void> test_snippetTextEdits_supported() async {
+ // This tests experimental support for including Snippets in TextEdits.
+ // https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
+ //
+ // This allows setting the cursor position/selection in TextEdits included
+ // in CodeActions, for example Flutter's "Wrap with widget" assist that
+ // should select the text "widget".
+
+ const content = '''
+ import 'package:flutter/widgets.dart';
+ build() {
+ return Container(
+ child: Row(
+ children: [^
+ Text('111'),
+ Text('222'),
+ Container(),
+ ],
+ ),
+ );
+ }
+ ''';
+
+ // For testing, the snippet will be inserted literally into the text, as
+ // this requires some magic on the client. The expected text should therefore
+ // contain the snippets in the standard format.
+ const expectedContent = r'''
+ import 'package:flutter/widgets.dart';
+ build() {
+ return Container(
+ child: Row(
+ children: [
+ ${0:widget}(
+ children: [
+ Text('111'),
+ Text('222'),
+ Container(),
+ ],
+ ),
+ ],
+ ),
+ );
+ }
+ ''';
+
+ newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+ workspaceCapabilities:
+ withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+ experimentalCapabilities: {
+ 'snippetTextEdit': true,
+ },
+ );
+
+ final marker = positionFromMarker(content);
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ range: Range(start: marker, end: marker));
+ final assist = findEditAction(codeActions,
+ CodeActionKind('refactor.flutter.wrap.generic'), 'Wrap with widget...');
+
+ // Ensure the edit came back, and using documentChanges.
+ expect(assist, isNotNull);
+ expect(assist.edit.documentChanges, isNotNull);
+ expect(assist.edit.changes, isNull);
+
+ // Ensure applying the changes will give us the expected content.
+ final contents = {
+ mainFilePath: withoutMarkers(content),
+ };
+ applyDocumentChanges(contents, assist.edit.documentChanges);
+ expect(contents[mainFilePath], equals(expectedContent));
+
+ // Also ensure there was a single edit that was correctly marked
+ // as a SnippetTextEdit.
+ final textEdits = _extractTextDocumentEdits(assist.edit.documentChanges)
+ .expand((tde) => tde.edits)
+ .map((edit) => edit.map(
+ (e) => e,
+ (e) => throw 'Expected SnippetTextEdit, got AnnotatedTextEdit',
+ (e) => throw 'Expected SnippetTextEdit, got TextEdit',
+ ))
+ .toList();
+ expect(textEdits, hasLength(1));
+ expect(textEdits.first.insertTextFormat, equals(InsertTextFormat.Snippet));
+ }
+
+ Future<void> test_snippetTextEdits_unsupported() async {
+ // This tests experimental support for including Snippets in TextEdits
+ // is not active when the client capabilities do not advertise support for it.
+ // https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
+
+ const content = '''
+ import 'package:flutter/widgets.dart';
+ build() {
+ return Container(
+ child: Row(
+ children: [^
+ Text('111'),
+ Text('222'),
+ Container(),
+ ],
+ ),
+ );
+ }
+ ''';
+
+ newFile(mainFilePath, content: withoutMarkers(content));
+ await initialize(
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+ workspaceCapabilities:
+ withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+ );
+
+ final marker = positionFromMarker(content);
+ final codeActions = await getCodeActions(mainFileUri.toString(),
+ range: Range(start: marker, end: marker));
+ final assist = findEditAction(codeActions,
+ CodeActionKind('refactor.flutter.wrap.generic'), 'Wrap with widget...');
+
+ // Ensure the edit came back, and using documentChanges.
+ expect(assist, isNotNull);
+ expect(assist.edit.documentChanges, isNotNull);
+ expect(assist.edit.changes, isNull);
+
+ // Extract just TextDocumentEdits, create/rename/delete are not relevant.
+ final textDocumentEdits =
+ _extractTextDocumentEdits(assist.edit.documentChanges);
+ final textEdits = textDocumentEdits
+ .expand((tde) => tde.edits)
+ .map((edit) => edit.map((e) => e, (e) => e, (e) => e))
+ .toList();
+
+ // Ensure the edit does _not_ have a format of Snippet, nor does it include
+ // any $ characters that would indicate snippet text.
+ for (final edit in textEdits) {
+ expect(edit, isNot(TypeMatcher<SnippetTextEdit>()));
+ expect(edit.newText, isNot(contains(r'$')));
+ }
+ }
+
+ List<TextDocumentEdit> _extractTextDocumentEdits(
+ Either2<
+ List<TextDocumentEdit>,
+ List<
+ Either4<TextDocumentEdit, CreateFile, RenameFile,
+ DeleteFile>>>
+ documentChanges) =>
+ documentChanges.map(
+ // Already TextDocumentEdits
+ (edits) => edits,
+ // Extract TextDocumentEdits from union of resource changes
+ (changes) => changes
+ .map(
+ (change) => change.map(
+ (textDocEdit) => textDocEdit,
+ (create) => null,
+ (rename) => null,
+ (delete) => null,
+ ),
+ )
+ .where((e) => e != null)
+ .toList(),
+ );
}
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 2cf21e5..dd35465 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -650,10 +650,10 @@
});
}
- String applyTextEdit(
- String content, Either2<TextEdit, AnnotatedTextEdit> change) {
+ String applyTextEdit(String content,
+ Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit> change) {
// Both sites of the union can cast to TextEdit.
- final edit = change.map((e) => e, (e) => e);
+ final edit = change.map((e) => e, (e) => e, (e) => e);
final startPos = edit.range.start;
final endPos = edit.range.end;
final lineInfo = LineInfo.fromContent(content);
@@ -714,8 +714,8 @@
);
for (final change in sortedChanges) {
- newContent = applyTextEdit(
- newContent, Either2<TextEdit, AnnotatedTextEdit>.t1(change));
+ newContent = applyTextEdit(newContent,
+ Either3<SnippetTextEdit, AnnotatedTextEdit, TextEdit>.t3(change));
}
return newContent;
@@ -1217,6 +1217,7 @@
TextDocumentClientCapabilities textDocumentCapabilities,
ClientCapabilitiesWorkspace workspaceCapabilities,
ClientCapabilitiesWindow windowCapabilities,
+ Map<String, Object> experimentalCapabilities,
Map<String, Object> initializationOptions,
bool throwOnFailure = true,
bool allowEmptyRootUri = false,
@@ -1225,6 +1226,7 @@
workspace: workspaceCapabilities,
textDocument: textDocumentCapabilities,
window: windowCapabilities,
+ experimental: experimentalCapabilities,
);
// Handle any standard incoming requests that aren't test-specific, for example
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
index 782aa26..ace8ef1 100644
--- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart
+++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -272,6 +272,26 @@
],
baseType: 'CompletionItemResolutionInfo',
),
+ // Custom types for experimental SnippetTextEdits
+ // https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
+ interface(
+ 'SnippetTextEdit',
+ [
+ field('insertTextFormat', type: 'InsertTextFormat'),
+ ],
+ baseType: 'TextEdit',
+ ),
+ TypeAlias(
+ null,
+ Token.identifier('TextDocumentEditEdits'),
+ ArrayType(
+ UnionType([
+ Type.identifier('SnippetTextEdit'),
+ Type.identifier('AnnotatedTextEdit'),
+ Type.identifier('TextEdit'),
+ ]),
+ ),
+ )
];
return customTypes;
}
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript.dart b/pkg/analysis_server/tool/lsp_spec/typescript.dart
index 575d66e..801b093 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript.dart
@@ -124,6 +124,9 @@
},
'ServerCapabilities': {
'changeNotifications': 'bool',
+ },
+ 'TextDocumentEdit': {
+ 'edits': 'TextDocumentEditEdits',
}
};
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index d44c693..8b10921 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.3.0-dev
+* Added `Expression.inConstantContext` to API.
+* Updated documentation comments for some getters that don't return `null`.
+
## 1.2.0
* Deprecated all setters in API of AST. Use `parseString()` instead.
* `AnalysisSession.getErrors()` does not return `null`, check its `state`.
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 64526cc..41b1d1c 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -2144,6 +2144,29 @@
///
/// Clients may not extend, implement or mix-in this class.
abstract class Expression implements CollectionElement {
+ /// An expression _e_ is said to _occur in a constant context_,
+ /// * if _e_ is an element of a constant list literal, or a key or value of an
+ /// entry of a constant map literal.
+ /// * if _e_ is an actual argument of a constant object expression or of a
+ /// metadata annotation.
+ /// * if _e_ is the initializing expression of a constant variable
+ /// declaration.
+ /// * if _e_ is a switch case expression.
+ /// * if _e_ is an immediate subexpression of an expression _e1_ which occurs
+ /// in a constant context, unless _e1_ is a `throw` expression or a function
+ /// literal.
+ ///
+ /// This roughly means that everything which is inside a syntactically
+ /// constant expression is in a constant context. A `throw` expression is
+ /// currently not allowed in a constant expression, but extensions affecting
+ /// that status may be considered. A similar situation arises for function
+ /// literals.
+ ///
+ /// Note that the default value of an optional formal parameter is _not_ a
+ /// constant context. This choice reserves some freedom to modify the
+ /// semantics of default values.
+ bool get inConstantContext;
+
/// Return `true` if this expression is syntactically valid for the LHS of an
/// [AssignmentExpression].
bool get isAssignable;
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 85778f6..edfcd2e 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -531,8 +531,8 @@
/// element, e.g. a synthetic property accessor), return itself.
Element? get declaration;
- /// Return the display name of this element, or `null` if this element does
- /// not have a name.
+ /// Return the display name of this element, possibly the empty string if
+ /// this element does not have a name.
///
/// In most cases the name and the display name are the same. Differences
/// though are cases such as setters where the name of some setter `set f(x)`
@@ -1041,9 +1041,7 @@
Element get enclosingElement;
/// Return `true` if this executable element did not have an explicit return
- /// type specified for it in the original source. Note that if there was no
- /// explicit return type, and if the element model is fully populated, then
- /// the [returnType] will not be `null`.
+ /// type specified for it in the original source.
bool get hasImplicitReturnType;
/// Return `true` if this executable element is abstract. Executable elements
@@ -1231,9 +1229,7 @@
/// element.
List<ParameterElement> get parameters;
- /// Return the return type defined by this element. If the element model is
- /// fully populated, then the [returnType] will not be `null`, even if no
- /// return type was explicitly specified.
+ /// Return the return type defined by this element.
DartType get returnType;
/// Return the type defined by this element.
@@ -1874,9 +1870,7 @@
/// > implicitly static.
bool get isStatic;
- /// Return the declared type of this variable, or `null` if the variable did
- /// not have a declared type (such as if it was declared using the keyword
- /// 'var').
+ /// Return the declared type of this variable.
DartType get type;
/// Return a representation of the value of this variable, forcing the value
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index e38573d..575cac0 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3490,27 +3490,7 @@
@override
DartType? staticType;
- /// An expression _e_ is said to _occur in a constant context_,
- /// * if _e_ is an element of a constant list literal, or a key or value of an
- /// entry of a constant map literal.
- /// * if _e_ is an actual argument of a constant object expression or of a
- /// metadata annotation.
- /// * if _e_ is the initializing expression of a constant variable
- /// declaration.
- /// * if _e_ is a switch case expression.
- /// * if _e_ is an immediate subexpression of an expression _e1_ which occurs
- /// in a constant context, unless _e1_ is a `throw` expression or a function
- /// literal.
- ///
- /// This roughly means that everything which is inside a syntactically
- /// constant expression is in a constant context. A `throw` expression is
- /// currently not allowed in a constant expression, but extensions affecting
- /// that status may be considered. A similar situation arises for function
- /// literals.
- ///
- /// Note that the default value of an optional formal parameter is _not_ a
- /// constant context. This choice reserves some freedom to modify the
- /// semantics of default values.
+ @override
bool get inConstantContext {
AstNode child = this;
while (child is Expression ||
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 14c858c..cb24558 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -617,6 +617,10 @@
});
}
+ if (isThirdParty) {
+ options.hint = false;
+ }
+
return options;
}
diff --git a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
index 336b180..e0c34fd 100644
--- a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
+++ b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
@@ -9,7 +9,6 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:pub_semver/pub_semver.dart';
@@ -113,8 +112,7 @@
@override
void visitAsExpression(AsExpression node) {
- if (checkConstantUpdate2018 &&
- (node as AsExpressionImpl).inConstantContext) {
+ if (checkConstantUpdate2018 && node.inConstantContext) {
_errorReporter.reportErrorForNode(
HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT, node);
}
@@ -131,15 +129,14 @@
} else if ((operatorType == TokenType.AMPERSAND ||
operatorType == TokenType.BAR ||
operatorType == TokenType.CARET) &&
- (node as BinaryExpressionImpl).inConstantContext) {
+ node.inConstantContext) {
if (node.leftOperand.typeOrThrow.isDartCoreBool) {
_errorReporter.reportErrorForToken(
HintCode.SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT,
node.operator,
[node.operator.lexeme]);
}
- } else if (operatorType == TokenType.EQ_EQ &&
- (node as BinaryExpressionImpl).inConstantContext) {
+ } else if (operatorType == TokenType.EQ_EQ && node.inConstantContext) {
bool primitive(Expression node) {
DartType type = node.typeOrThrow;
return type.isDartCoreBool ||
@@ -204,8 +201,7 @@
@override
void visitIsExpression(IsExpression node) {
- if (checkConstantUpdate2018 &&
- (node as IsExpressionImpl).inConstantContext) {
+ if (checkConstantUpdate2018 && node.inConstantContext) {
_errorReporter.reportErrorForNode(
HintCode.SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT, node);
}
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 02e11bc..e4fea47 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -21,14 +21,6 @@
show CompileTimeErrorCode, StrongModeCode;
import 'package:analyzer/src/task/inference_error.dart';
-DartType _elementType(Element? e) {
- if (e == null) {
- // Malformed code - just return dynamic.
- return DynamicTypeImpl.instance;
- }
- return (e as dynamic).type;
-}
-
Element? _getKnownElement(Expression expression) {
if (expression is ParenthesizedExpression) {
return _getKnownElement(expression.expression);
@@ -86,7 +78,7 @@
// so no need to insert an error for this here.
continue;
}
- checkArgument(arg, _elementType(element));
+ checkArgument(arg, element.type);
}
}
@@ -244,7 +236,6 @@
node.visitChildren(this);
}
- // Check invocations
/// Check constructor declaration to ensure correct super call placement.
@override
void visitConstructorDeclaration(ConstructorDeclaration node) {
@@ -270,8 +261,9 @@
void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
var field = node.fieldName;
var element = field.staticElement;
- DartType staticType = _elementType(element);
- checkAssignment(node.expression, staticType);
+ if (element != null) {
+ checkAssignment(node.expression, _elementType(element));
+ }
node.visitChildren(this);
}
@@ -279,9 +271,10 @@
void visitDefaultFormalParameter(DefaultFormalParameter node) {
// Check that defaults have the proper subtype.
var parameter = node.parameter;
- var parameterType = _elementType(parameter.declaredElement);
var defaultValue = node.defaultValue;
- if (defaultValue != null) {
+ var element = parameter.declaredElement;
+ if (defaultValue != null && element != null) {
+ var parameterType = _elementType(element);
checkAssignment(defaultValue, parameterType);
}
@@ -363,7 +356,7 @@
var arguments = node.argumentList;
var element = node.constructorName.staticElement;
if (element != null) {
- var type = _elementType(element) as FunctionType;
+ var type = element.type;
checkArgumentList(arguments, type);
}
node.visitChildren(this);
@@ -709,7 +702,7 @@
FunctionType functionType;
var parent = body.parent;
if (parent is Declaration) {
- functionType = _elementType(parent.declaredElement) as FunctionType;
+ functionType = _elementType(parent.declaredElement!) as FunctionType;
} else {
assert(parent is FunctionExpression);
functionType = (parent as FunctionExpression).staticType as FunctionType;
@@ -974,6 +967,21 @@
to: loopVariableElement.type, from: elementType);
}
}
+
+ static DartType _elementType(Element e) {
+ if (e is ConstructorElement) {
+ return e.type;
+ } else if (e is FieldElement) {
+ return e.type;
+ } else if (e is MethodElement) {
+ return e.type;
+ } else if (e is ParameterElement) {
+ return e.type;
+ } else if (e is PropertyAccessorElement) {
+ return e.type;
+ }
+ throw StateError('${e.runtimeType} is unhandled type');
+ }
}
class _TopLevelInitializerValidator extends RecursiveAstVisitor<void> {
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 5be43d5..325dd01 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 1.2.0
+version: 1.3.0-dev
description: This package provides a library that performs static analysis of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
diff --git a/pkg/analyzer/test/src/dart/micro/file_resolution.dart b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
index 67ea722..55d7031 100644
--- a/pkg/analyzer/test/src/dart/micro/file_resolution.dart
+++ b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
@@ -65,7 +65,8 @@
@override
Future<ResolvedUnitResult> resolveFile(String path) async {
- return fileResolver.resolve(path: path);
+ result = fileResolver.resolve(path: path);
+ return result;
}
@override
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 5decd67..15b8ebd 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -481,6 +481,15 @@
]);
}
+ test_hint_in_third_party() async {
+ var aPath = convertPath('/workspace/third_party/dart/aaa/lib/a.dart');
+ newFile(aPath, content: r'''
+import 'dart:math';
+''');
+ await resolveFile(aPath);
+ assertNoErrorsInResult();
+ }
+
test_linkLibraries_getErrors() {
addTestFile(r'''
var a = b;
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
index 5f103da..ec6150f 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
@@ -6,7 +6,6 @@
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../dart/resolution/context_collection_resolution.dart';
import 'sdk_constraint_verifier_support.dart';
main() {
@@ -22,18 +21,6 @@
'${ExperimentStatus.currentVersion.major}.'
'${ExperimentStatus.currentVersion.minor}';
- @override
- void setUp() {
- super.setUp();
- writeTestPackageAnalysisOptionsFile(
- AnalysisOptionsFileConfig(
- experiments: [
- EnableString.triple_shift,
- ],
- ),
- );
- }
-
test_const_equals() async {
// TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
// UNDEFINED_OPERATOR when triple_shift is enabled by default.
@@ -75,7 +62,7 @@
test_nonConst_equals() async {
// TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
- // UNDEFINED_OPERATOR when constant update is enabled by default.
+ // UNDEFINED_OPERATOR when triple_shift is enabled by default.
await verifyVersion('2.5.0', '''
var a = 42 >>> 3;
''', expectedErrors: [
@@ -85,7 +72,7 @@
test_nonConst_lessThan() async {
// TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
- // UNDEFINED_OPERATOR when constant update is enabled by default.
+ // UNDEFINED_OPERATOR when triple_shift is enabled by default.
await verifyVersion('2.2.0', '''
var a = 42 >>> 3;
''', expectedErrors: [
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index e921146..571e8ce 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -20,7 +20,6 @@
import 'common_elements.dart' show ElementEnvironment;
import 'deferred_load.dart' show DeferredLoadTask, OutputUnitData;
import 'diagnostics/code_location.dart';
-import 'diagnostics/diagnostic_listener.dart' show DiagnosticReporter;
import 'diagnostics/messages.dart' show Message, MessageTemplate;
import 'dump_info.dart' show DumpInfoTask;
import 'elements/entities.dart';
diff --git a/pkg/compiler/lib/src/helpers/helpers.dart b/pkg/compiler/lib/src/helpers/helpers.dart
index 910485e9..a59366a 100644
--- a/pkg/compiler/lib/src/helpers/helpers.dart
+++ b/pkg/compiler/lib/src/helpers/helpers.dart
@@ -10,7 +10,6 @@
import '../common.dart';
import '../diagnostics/invariant.dart' show DEBUG_MODE;
import '../util/util.dart';
-import 'trace.dart';
export 'debug_collection.dart';
export 'expensive_map.dart';
diff --git a/pkg/compiler/lib/src/ir/debug.dart b/pkg/compiler/lib/src/ir/debug.dart
index bb24302..3b9e11a 100644
--- a/pkg/compiler/lib/src/ir/debug.dart
+++ b/pkg/compiler/lib/src/ir/debug.dart
@@ -7,7 +7,6 @@
library kernel.debug;
import 'package:kernel/ast.dart';
-import 'package:kernel/visitor.dart';
import '../util/util.dart' show Indentation, Tagging;
diff --git a/pkg/compiler/lib/src/js_backend/annotations.dart b/pkg/compiler/lib/src/js_backend/annotations.dart
index 8955a8d..f702ca37 100644
--- a/pkg/compiler/lib/src/js_backend/annotations.dart
+++ b/pkg/compiler/lib/src/js_backend/annotations.dart
@@ -7,8 +7,6 @@
import 'package:kernel/ast.dart' as ir;
import '../common.dart';
-import '../diagnostics/diagnostic_listener.dart';
-import '../diagnostics/messages.dart';
import '../elements/entities.dart';
import '../ir/annotations.dart';
import '../ir/util.dart';
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 4d0546c..9fea86f 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -18,7 +18,6 @@
import '../js_emitter/code_emitter_task.dart';
import '../js_model/type_recipe.dart' show TypeExpressionRecipe;
import '../options.dart';
-import 'field_analysis.dart' show JFieldAnalysis;
import 'namer.dart';
import 'runtime_types_new.dart' show RecipeEncoder;
import 'runtime_types_resolution.dart';
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index fee1573..9596fd0 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -11,7 +11,6 @@
import '../common/backend_api.dart' show ImpactTransformer;
import '../common/codegen.dart' show CodegenImpact;
import '../common/resolution.dart' show ResolutionImpact;
-import '../common_elements.dart' show ElementEnvironment;
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 44b6cd1..d63ee32 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -15,7 +15,6 @@
import '../ir/closure.dart';
import '../ir/static_type_provider.dart';
import '../ir/util.dart';
-import '../js_model/closure.dart' show JRecordField;
import '../js_model/elements.dart' show JGeneratorBody;
import '../native/behavior.dart';
import '../serialization/serialization.dart';
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 868ef6f..66f8efc 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -10,7 +10,6 @@
import '../common/names.dart';
import '../common_elements.dart' show JCommonElements, JElementEnvironment;
import '../deferred_load.dart';
-import '../diagnostics/diagnostic_listener.dart';
import '../elements/entities.dart';
import '../elements/entity_utils.dart' as utils;
import '../elements/names.dart';
diff --git a/pkg/compiler/lib/src/source_file_provider.dart b/pkg/compiler/lib/src/source_file_provider.dart
index f8b1da3..9a7fe7f 100644
--- a/pkg/compiler/lib/src/source_file_provider.dart
+++ b/pkg/compiler/lib/src/source_file_provider.dart
@@ -11,7 +11,6 @@
import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
-import '../compiler.dart' as api show Diagnostic;
import '../compiler_new.dart' as api;
import '../compiler_new.dart';
import 'colors.dart' as colors;
diff --git a/pkg/compiler/test/analyses/analysis_helper.dart b/pkg/compiler/test/analyses/analysis_helper.dart
index fb096c3..43fb4db 100644
--- a/pkg/compiler/test/analyses/analysis_helper.dart
+++ b/pkg/compiler/test/analyses/analysis_helper.dart
@@ -11,9 +11,6 @@
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
-import 'package:compiler/src/diagnostics/messages.dart';
-import 'package:compiler/src/diagnostics/source_span.dart';
import 'package:compiler/src/ir/constants.dart';
import 'package:compiler/src/ir/scope.dart';
import 'package:compiler/src/ir/static_type.dart';
diff --git a/pkg/compiler/test/closure/closure_test.dart b/pkg/compiler/test/closure/closure_test.dart
index 231025d..78c02dc 100644
--- a/pkg/compiler/test/closure/closure_test.dart
+++ b/pkg/compiler/test/closure/closure_test.dart
@@ -11,7 +11,6 @@
import 'package:compiler/src/closure.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/js_model/element_map.dart';
import 'package:compiler/src/js_model/js_world.dart';
diff --git a/pkg/compiler/test/codegen/expect_annotations_test.dart b/pkg/compiler/test/codegen/expect_annotations_test.dart
index a3df294..5587f3f 100644
--- a/pkg/compiler/test/codegen/expect_annotations_test.dart
+++ b/pkg/compiler/test/codegen/expect_annotations_test.dart
@@ -10,7 +10,6 @@
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/inferrer/abstract_value_domain.dart';
-import 'package:compiler/src/inferrer/types.dart';
import 'package:compiler/src/world.dart' show JClosedWorld;
import '../inference/type_mask_test_helper.dart';
import '../helpers/memory_compiler.dart';
diff --git a/pkg/compiler/test/deferred/closures_test.dart b/pkg/compiler/test/deferred/closures_test.dart
index 5969125..c672c81 100644
--- a/pkg/compiler/test/deferred/closures_test.dart
+++ b/pkg/compiler/test/deferred/closures_test.dart
@@ -11,7 +11,6 @@
import 'package:expect/expect.dart';
import '../helpers/memory_compiler.dart';
-import '../helpers/output_collector.dart';
void main() {
asyncTest(() async {
diff --git a/pkg/compiler/test/deferred/constant_emission_test_helper.dart b/pkg/compiler/test/deferred/constant_emission_test_helper.dart
index ce54b1b..d8fc00a 100644
--- a/pkg/compiler/test/deferred/constant_emission_test_helper.dart
+++ b/pkg/compiler/test/deferred/constant_emission_test_helper.dart
@@ -7,7 +7,6 @@
// Test that the additional runtime type support is output to the right
// Files when using deferred loading.
-import 'package:compiler/compiler_new.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/constants/values.dart';
import 'package:compiler/src/deferred_load.dart';
@@ -17,7 +16,6 @@
import 'package:compiler/src/util/util.dart';
import 'package:expect/expect.dart';
import '../helpers/memory_compiler.dart';
-import '../helpers/output_collector.dart';
import '../helpers/program_lookup.dart';
class OutputUnitDescriptor {
diff --git a/pkg/compiler/test/deferred/emit_type_checks_test.dart b/pkg/compiler/test/deferred/emit_type_checks_test.dart
index 38150fc..d4184ad8 100644
--- a/pkg/compiler/test/deferred/emit_type_checks_test.dart
+++ b/pkg/compiler/test/deferred/emit_type_checks_test.dart
@@ -13,7 +13,6 @@
import 'package:compiler/src/js_model/js_strategy.dart';
import 'package:expect/expect.dart';
import '../helpers/memory_compiler.dart';
-import '../helpers/output_collector.dart';
void main() {
runTest() async {
diff --git a/pkg/compiler/test/equivalence/id_testing_test.dart b/pkg/compiler/test/equivalence/id_testing_test.dart
index ff453fe..5789c7c 100644
--- a/pkg/compiler/test/equivalence/id_testing_test.dart
+++ b/pkg/compiler/test/equivalence/id_testing_test.dart
@@ -5,7 +5,6 @@
// @dart = 2.7
import 'dart:io';
-import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
diff --git a/pkg/compiler/test/helpers/compiler_helper.dart b/pkg/compiler/test/helpers/compiler_helper.dart
index 8faa745..514b1ca 100644
--- a/pkg/compiler/test/helpers/compiler_helper.dart
+++ b/pkg/compiler/test/helpers/compiler_helper.dart
@@ -17,7 +17,6 @@
import 'package:expect/expect.dart';
import 'package:_fe_analyzer_shared/src/util/link.dart' show Link;
import 'memory_compiler.dart';
-import 'output_collector.dart';
export 'package:compiler/src/diagnostics/messages.dart';
export 'package:compiler/src/diagnostics/source_span.dart';
diff --git a/pkg/compiler/test/helpers/d8_helper.dart b/pkg/compiler/test/helpers/d8_helper.dart
index dae47ad..d02ff9e 100644
--- a/pkg/compiler/test/helpers/d8_helper.dart
+++ b/pkg/compiler/test/helpers/d8_helper.dart
@@ -11,7 +11,6 @@
import 'dart:async';
import 'dart:io';
-import 'package:compiler/compiler_new.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/dart2js.dart' as dart2js;
import 'package:_fe_analyzer_shared/src/util/filenames.dart';
diff --git a/pkg/compiler/test/jumps/jump_test.dart b/pkg/compiler/test/jumps/jump_test.dart
index b848bd7..e483cba 100644
--- a/pkg/compiler/test/jumps/jump_test.dart
+++ b/pkg/compiler/test/jumps/jump_test.dart
@@ -8,7 +8,6 @@
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/elements/jumps.dart';
import 'package:compiler/src/js_model/element_map.dart';
diff --git a/pkg/compiler/test/model/cfe_constant_test.dart b/pkg/compiler/test/model/cfe_constant_test.dart
index 4ae3771..d9dfbf0 100644
--- a/pkg/compiler/test/model/cfe_constant_test.dart
+++ b/pkg/compiler/test/model/cfe_constant_test.dart
@@ -5,7 +5,6 @@
// @dart = 2.7
import 'dart:io';
-import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
diff --git a/pkg/compiler/test/sourcemaps/helpers/sourcemap_helper.dart b/pkg/compiler/test/sourcemaps/helpers/sourcemap_helper.dart
index f5e0509..cc8df9a 100644
--- a/pkg/compiler/test/sourcemaps/helpers/sourcemap_helper.dart
+++ b/pkg/compiler/test/sourcemaps/helpers/sourcemap_helper.dart
@@ -22,7 +22,6 @@
import 'package:compiler/src/js_model/js_strategy.dart';
import 'package:compiler/src/source_file_provider.dart';
import '../../helpers/memory_compiler.dart';
-import '../../helpers/output_collector.dart';
class SourceFileSink implements OutputSink {
final String filename;
diff --git a/pkg/compiler/test/sourcemaps/stacktrace_test.dart b/pkg/compiler/test/sourcemaps/stacktrace_test.dart
index 6785cc0..7468227 100644
--- a/pkg/compiler/test/sourcemaps/stacktrace_test.dart
+++ b/pkg/compiler/test/sourcemaps/stacktrace_test.dart
@@ -9,7 +9,6 @@
import 'package:args/args.dart';
import 'package:async_helper/async_helper.dart';
-import 'package:compiler/compiler_new.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/dart2js.dart' as entry;
diff --git a/pkg/compiler/test/sourcemaps/stepping_test.dart b/pkg/compiler/test/sourcemaps/stepping_test.dart
index 28712e6..c6a0504 100644
--- a/pkg/compiler/test/sourcemaps/stepping_test.dart
+++ b/pkg/compiler/test/sourcemaps/stepping_test.dart
@@ -10,7 +10,6 @@
import 'package:_fe_analyzer_shared/src/testing/annotated_code_helper.dart';
import 'package:args/args.dart';
import 'package:async_helper/async_helper.dart';
-import 'package:compiler/compiler_new.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/dart2js.dart' as entry;
import 'package:expect/expect.dart';
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index ec0a9bb..45d2b4d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -1009,6 +1009,8 @@
ExecutionStatus status = statement.accept(statementEvaluator);
if (status is ReturnStatus) {
return status.value;
+ } else if (status is AbortStatus) {
+ return status.error;
}
return createInvalidExpressionConstant(statement,
'No valid constant returned from the execution of $statement.');
@@ -3342,7 +3344,7 @@
@override
ExecutionStatus visitIfStatement(IfStatement node) {
Constant condition = evaluate(node.condition);
- if (condition is AbortConstant) return new ReturnStatus(condition);
+ if (condition is AbortConstant) return new AbortStatus(condition);
if (condition is BoolConstant) {
if (condition.value) {
return node.then.accept(this);
@@ -3352,7 +3354,7 @@
return const ProceedStatus();
}
} else {
- return new ReturnStatus(exprEvaluator.createErrorConstant(
+ return new AbortStatus(exprEvaluator.createErrorConstant(
node.condition,
templateConstEvalInvalidType.withArguments(
condition,
@@ -3365,7 +3367,7 @@
@override
ExecutionStatus visitExpressionStatement(ExpressionStatement node) {
Constant value = evaluate(node.expression);
- if (value is AbortConstant) return new ReturnStatus(value);
+ if (value is AbortConstant) return new AbortStatus(value);
return const ProceedStatus();
}
@@ -3376,7 +3378,7 @@
@override
ExecutionStatus visitVariableDeclaration(VariableDeclaration node) {
Constant value = evaluate(node.initializer);
- if (value is AbortConstant) return new ReturnStatus(value);
+ if (value is AbortConstant) return new AbortStatus(value);
exprEvaluator.env.addVariableValue(node, value);
return const ProceedStatus();
}
@@ -3549,6 +3551,12 @@
ReturnStatus(this.value);
}
+/// Status with an exception or error that the statement has thrown.
+class AbortStatus extends ExecutionStatus {
+ final AbortConstant error;
+ AbortStatus(this.error);
+}
+
/// An intermediate result that is used within the [ConstantEvaluator].
class IntermediateValue implements Constant {
dynamic value;
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart
new file mode 100644
index 0000000..fb50083
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart
@@ -0,0 +1,3 @@
+main() {
+ if (n is int or
+}
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.expect
new file mode 100644
index 0000000..6c4db58
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.expect
@@ -0,0 +1,49 @@
+Problems reported:
+
+parser/error_recovery/issue_45327.crash:2:16: Expected ';' after this.
+ if (n is int or
+ ^^
+
+parser/error_recovery/issue_45327.crash:2:6: Can't find ')' to match '('.
+ if (n is int or
+ ^
+
+beginCompilationUnit(main)
+ beginMetadataStar(main)
+ endMetadataStar(0)
+ beginTopLevelMember(main)
+ beginTopLevelMethod(UnmatchedToken((), null)
+ handleNoType(UnmatchedToken(())
+ handleIdentifier(main, topLevelFunctionDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.TopLevelMethod)
+ endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ beginIfStatement(if)
+ handleIdentifier(n, expression)
+ handleNoTypeArguments(is)
+ handleNoArguments(is)
+ handleSend(n, is)
+ beginIsOperatorType(is)
+ handleIdentifier(int, typeReference)
+ handleNoTypeArguments(or)
+ handleType(int, null)
+ endIsOperatorType(is)
+ handleIsOperator(is, null)
+ handleParenthesizedCondition(()
+ beginThenStatement(or)
+ handleIdentifier(or, expression)
+ handleNoTypeArguments(})
+ handleNoArguments(})
+ handleSend(or, })
+ handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], or, or)
+ handleExpressionStatement(;)
+ endThenStatement(;)
+ endIfStatement(if, null)
+ endBlockFunctionBody(1, {, })
+ endTopLevelMethod(main, null, })
+ endTopLevelDeclaration()
+ handleErrorToken(UnmatchedToken(())
+ handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.intertwined.expect
new file mode 100644
index 0000000..841133c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.intertwined.expect
@@ -0,0 +1,101 @@
+parseUnit(UnmatchedToken(())
+ skipErrorTokens(UnmatchedToken(())
+ listener: beginCompilationUnit(main)
+ syntheticPreviousToken(main)
+ parseTopLevelDeclarationImpl(UnmatchedToken((), Instance of 'DirectiveContext')
+ parseMetadataStar(UnmatchedToken(())
+ listener: beginMetadataStar(main)
+ listener: endMetadataStar(0)
+ parseTopLevelMemberImpl(UnmatchedToken(())
+ listener: beginTopLevelMember(main)
+ isReservedKeyword(()
+ parseTopLevelMethod(UnmatchedToken((), null, UnmatchedToken((), Instance of 'NoType', null, main, false)
+ listener: beginTopLevelMethod(UnmatchedToken((), null)
+ listener: handleNoType(UnmatchedToken(())
+ ensureIdentifierPotentiallyRecovered(UnmatchedToken((), topLevelFunctionDeclaration, false)
+ listener: handleIdentifier(main, topLevelFunctionDeclaration)
+ parseMethodTypeVar(main)
+ listener: handleNoTypeVariables(()
+ parseGetterOrFormalParameters(main, main, false, MemberKind.TopLevelMethod)
+ parseFormalParameters(main, MemberKind.TopLevelMethod)
+ parseFormalParametersRest((, MemberKind.TopLevelMethod)
+ listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+ listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ parseFunctionBody(), false, false)
+ listener: beginBlockFunctionBody({)
+ notEofOrValue(}, if)
+ parseStatement({)
+ parseStatementX({)
+ parseIfStatement({)
+ listener: beginIfStatement(if)
+ ensureParenthesizedCondition(if)
+ parseExpressionInParenthesisRest(()
+ parseExpression(()
+ parsePrecedenceExpression((, 1, true)
+ parseUnaryExpression((, true)
+ parsePrimary((, expression)
+ parseSendOrFunctionLiteral((, expression)
+ parseSend((, expression)
+ ensureIdentifier((, expression)
+ listener: handleIdentifier(n, expression)
+ listener: handleNoTypeArguments(is)
+ parseArgumentsOpt(n)
+ listener: handleNoArguments(is)
+ listener: handleSend(n, is)
+ parseIsOperatorRest(n)
+ listener: beginIsOperatorType(is)
+ computeTypeAfterIsOrAs(is)
+ listener: handleIdentifier(int, typeReference)
+ listener: handleNoTypeArguments(or)
+ listener: handleType(int, null)
+ listener: endIsOperatorType(is)
+ listener: handleIsOperator(is, null)
+ skipChainedAsIsOperators(int)
+ rewriter()
+ parsePrecedenceExpression(||, 6, true)
+ parseUnaryExpression(||, true)
+ parsePrimary(||, expression)
+ parseSend(||, expression)
+ ensureIdentifier(||, expression)
+ reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
+ rewriter()
+ parseArgumentsOpt()
+ ensureCloseParen(int, ()
+ rewriter()
+ listener: handleParenthesizedCondition(()
+ listener: beginThenStatement(or)
+ parseStatement())
+ parseStatementX())
+ parseExpressionStatementOrDeclarationAfterModifiers(), ), null, null, null, false)
+ looksLikeLocalFunction(or)
+ parseExpressionStatement())
+ parseExpression())
+ parsePrecedenceExpression(), 1, true)
+ parseUnaryExpression(), true)
+ parsePrimary(), expression)
+ parseSendOrFunctionLiteral(), expression)
+ parseSend(), expression)
+ ensureIdentifier(), expression)
+ listener: handleIdentifier(or, expression)
+ listener: handleNoTypeArguments(})
+ parseArgumentsOpt(or)
+ listener: handleNoArguments(})
+ listener: handleSend(or, })
+ ensureSemicolon(or)
+ reportRecoverableError(or, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], or, or)
+ rewriter()
+ listener: handleExpressionStatement(;)
+ listener: endThenStatement(;)
+ listener: endIfStatement(if, null)
+ notEofOrValue(}, })
+ listener: endBlockFunctionBody(1, {, })
+ listener: endTopLevelMethod(main, null, })
+ listener: endTopLevelDeclaration()
+ reportAllErrorTokens(UnmatchedToken(())
+ listener: handleErrorToken(UnmatchedToken(())
+ listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
+ listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.parser.expect
new file mode 100644
index 0000000..2e09cb4
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.parser.expect
@@ -0,0 +1,11 @@
+NOTICE: Stream was rewritten by parser!
+
+main() {
+if (n is int )or
+;}
+
+
+[UnmatchedToken]main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]n[StringToken] is[KeywordToken] int[StringToken] )[SyntheticToken]or[StringToken]
+;[SyntheticToken]}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.scanner.expect
new file mode 100644
index 0000000..321f988
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327.crash_dart.scanner.expect
@@ -0,0 +1,9 @@
+main() {
+if (n is int or
+)}
+
+
+[UnmatchedToken]main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]n[StringToken] is[KeywordToken] int[StringToken] or[StringToken]
+)[SyntheticToken]}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart
new file mode 100644
index 0000000..2afc4b5
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart
@@ -0,0 +1,5 @@
+class Foo<T> {
+ foo(Object? key) {
+ if (key is! T or
+ }
+}
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.expect
new file mode 100644
index 0000000..a9b75e9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.expect
@@ -0,0 +1,82 @@
+Problems reported:
+
+parser/error_recovery/issue_45327_prime_1.crash:3:19: Expected ';' after this.
+ if (key is! T or
+ ^^
+
+parser/error_recovery/issue_45327_prime_1.crash:3:8: Can't find ')' to match '('.
+ if (key is! T or
+ ^
+
+beginCompilationUnit(class)
+ beginMetadataStar(class)
+ endMetadataStar(0)
+ beginClassOrNamedMixinApplicationPrelude(class)
+ handleIdentifier(Foo, classOrMixinDeclaration)
+ beginTypeVariables(<)
+ beginMetadataStar(T)
+ endMetadataStar(0)
+ handleIdentifier(T, typeVariableDeclaration)
+ beginTypeVariable(T)
+ handleTypeVariablesDefined(T, 1)
+ handleNoType(T)
+ endTypeVariable(>, 0, null, null)
+ endTypeVariables(<, >)
+ beginClassDeclaration(class, null, Foo)
+ handleNoType(>)
+ handleClassExtends(null, 1)
+ handleClassNoWithClause()
+ handleClassOrMixinImplements(null, 0)
+ handleClassHeader(class, class, null)
+ beginClassOrMixinBody(DeclarationKind.Class, {)
+ beginMetadataStar(foo)
+ endMetadataStar(0)
+ beginMember()
+ beginMethod(null, null, null, null, null, foo)
+ handleNoType({)
+ handleIdentifier(foo, methodDeclaration)
+ handleNoTypeVariables(()
+ beginFormalParameters((, MemberKind.NonStaticMethod)
+ beginMetadataStar(Object)
+ endMetadataStar(0)
+ beginFormalParameter(Object, MemberKind.NonStaticMethod, null, null, null)
+ handleIdentifier(Object, typeReference)
+ handleNoTypeArguments(?)
+ handleType(Object, ?)
+ handleIdentifier(key, formalParameterDeclaration)
+ handleFormalParameterWithoutValue())
+ endFormalParameter(null, null, key, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ endFormalParameters(1, (, ), MemberKind.NonStaticMethod)
+ handleNoInitializers()
+ handleAsyncModifier(null, null)
+ beginBlockFunctionBody({)
+ beginIfStatement(if)
+ handleIdentifier(key, expression)
+ handleNoTypeArguments(is)
+ handleNoArguments(is)
+ handleSend(key, is)
+ beginIsOperatorType(is)
+ handleIdentifier(T, typeReference)
+ handleNoTypeArguments(or)
+ handleType(T, null)
+ endIsOperatorType(is)
+ handleIsOperator(is, !)
+ handleParenthesizedCondition(()
+ beginThenStatement(or)
+ handleIdentifier(or, expression)
+ handleNoTypeArguments(})
+ handleNoArguments(})
+ handleSend(or, })
+ handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], or, or)
+ handleExpressionStatement(;)
+ endThenStatement(;)
+ endIfStatement(if, null)
+ endBlockFunctionBody(1, {, })
+ endClassMethod(null, foo, (, null, })
+ endMember()
+ endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+ endClassDeclaration(class, })
+ endTopLevelDeclaration()
+ handleErrorToken(UnmatchedToken(())
+ handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.intertwined.expect
new file mode 100644
index 0000000..d794537
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.intertwined.expect
@@ -0,0 +1,153 @@
+parseUnit(UnmatchedToken(())
+ skipErrorTokens(UnmatchedToken(())
+ listener: beginCompilationUnit(class)
+ syntheticPreviousToken(class)
+ parseTopLevelDeclarationImpl(UnmatchedToken((), Instance of 'DirectiveContext')
+ parseMetadataStar(UnmatchedToken(())
+ listener: beginMetadataStar(class)
+ listener: endMetadataStar(0)
+ parseTopLevelKeywordDeclaration(UnmatchedToken((), class, Instance of 'DirectiveContext')
+ parseClassDeclarationModifiers(UnmatchedToken((), class)
+ parseClassOrNamedMixinApplication(null, class)
+ listener: beginClassOrNamedMixinApplicationPrelude(class)
+ ensureIdentifier(class, classOrMixinDeclaration)
+ listener: handleIdentifier(Foo, classOrMixinDeclaration)
+ listener: beginTypeVariables(<)
+ listener: beginMetadataStar(T)
+ listener: endMetadataStar(0)
+ listener: handleIdentifier(T, typeVariableDeclaration)
+ listener: beginTypeVariable(T)
+ listener: handleTypeVariablesDefined(T, 1)
+ listener: handleNoType(T)
+ listener: endTypeVariable(>, 0, null, null)
+ listener: endTypeVariables(<, >)
+ listener: beginClassDeclaration(class, null, Foo)
+ parseClass(>, class, class, Foo)
+ parseClassHeaderOpt(>, class, class)
+ parseClassExtendsOpt(>)
+ listener: handleNoType(>)
+ listener: handleClassExtends(null, 1)
+ parseWithClauseOpt(>)
+ listener: handleClassNoWithClause()
+ parseClassOrMixinImplementsOpt(>)
+ listener: handleClassOrMixinImplements(null, 0)
+ listener: handleClassHeader(class, class, null)
+ parseClassOrMixinOrExtensionBody(>, DeclarationKind.Class, Foo)
+ listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+ notEofOrValue(}, foo)
+ parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, Foo)
+ parseMetadataStar({)
+ listener: beginMetadataStar(foo)
+ listener: endMetadataStar(0)
+ listener: beginMember()
+ isReservedKeyword(()
+ parseMethod({, null, null, null, null, null, null, {, Instance of 'NoType', null, foo, DeclarationKind.Class, Foo, false)
+ listener: beginMethod(null, null, null, null, null, foo)
+ listener: handleNoType({)
+ ensureIdentifierPotentiallyRecovered({, methodDeclaration, false)
+ listener: handleIdentifier(foo, methodDeclaration)
+ parseQualifiedRestOpt(foo, methodDeclarationContinuation)
+ parseMethodTypeVar(foo)
+ listener: handleNoTypeVariables(()
+ parseGetterOrFormalParameters(foo, foo, false, MemberKind.NonStaticMethod)
+ parseFormalParameters(foo, MemberKind.NonStaticMethod)
+ parseFormalParametersRest((, MemberKind.NonStaticMethod)
+ listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+ parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ parseMetadataStar(()
+ listener: beginMetadataStar(Object)
+ listener: endMetadataStar(0)
+ listener: beginFormalParameter(Object, MemberKind.NonStaticMethod, null, null, null)
+ listener: handleIdentifier(Object, typeReference)
+ listener: handleNoTypeArguments(?)
+ listener: handleType(Object, ?)
+ ensureIdentifier(?, formalParameterDeclaration)
+ listener: handleIdentifier(key, formalParameterDeclaration)
+ listener: handleFormalParameterWithoutValue())
+ listener: endFormalParameter(null, null, key, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+ listener: endFormalParameters(1, (, ), MemberKind.NonStaticMethod)
+ parseInitializersOpt())
+ listener: handleNoInitializers()
+ parseAsyncModifierOpt())
+ listener: handleAsyncModifier(null, null)
+ inPlainSync()
+ inPlainSync()
+ parseFunctionBody(), false, true)
+ listener: beginBlockFunctionBody({)
+ notEofOrValue(}, if)
+ parseStatement({)
+ parseStatementX({)
+ parseIfStatement({)
+ listener: beginIfStatement(if)
+ ensureParenthesizedCondition(if)
+ parseExpressionInParenthesisRest(()
+ parseExpression(()
+ parsePrecedenceExpression((, 1, true)
+ parseUnaryExpression((, true)
+ parsePrimary((, expression)
+ parseSendOrFunctionLiteral((, expression)
+ parseSend((, expression)
+ ensureIdentifier((, expression)
+ listener: handleIdentifier(key, expression)
+ listener: handleNoTypeArguments(is)
+ parseArgumentsOpt(key)
+ listener: handleNoArguments(is)
+ listener: handleSend(key, is)
+ parseIsOperatorRest(key)
+ listener: beginIsOperatorType(is)
+ computeTypeAfterIsOrAs(!)
+ listener: handleIdentifier(T, typeReference)
+ listener: handleNoTypeArguments(or)
+ listener: handleType(T, null)
+ listener: endIsOperatorType(is)
+ listener: handleIsOperator(is, !)
+ skipChainedAsIsOperators(T)
+ rewriter()
+ parsePrecedenceExpression(||, 6, true)
+ parseUnaryExpression(||, true)
+ parsePrimary(||, expression)
+ parseSend(||, expression)
+ ensureIdentifier(||, expression)
+ reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
+ rewriter()
+ parseArgumentsOpt()
+ ensureCloseParen(T, ()
+ rewriter()
+ listener: handleParenthesizedCondition(()
+ listener: beginThenStatement(or)
+ parseStatement())
+ parseStatementX())
+ parseExpressionStatementOrDeclarationAfterModifiers(), ), null, null, null, false)
+ looksLikeLocalFunction(or)
+ parseExpressionStatement())
+ parseExpression())
+ parsePrecedenceExpression(), 1, true)
+ parseUnaryExpression(), true)
+ parsePrimary(), expression)
+ parseSendOrFunctionLiteral(), expression)
+ parseSend(), expression)
+ ensureIdentifier(), expression)
+ listener: handleIdentifier(or, expression)
+ listener: handleNoTypeArguments(})
+ parseArgumentsOpt(or)
+ listener: handleNoArguments(})
+ listener: handleSend(or, })
+ ensureSemicolon(or)
+ reportRecoverableError(or, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+ listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], or, or)
+ rewriter()
+ listener: handleExpressionStatement(;)
+ listener: endThenStatement(;)
+ listener: endIfStatement(if, null)
+ notEofOrValue(}, })
+ listener: endBlockFunctionBody(1, {, })
+ listener: endClassMethod(null, foo, (, null, })
+ listener: endMember()
+ notEofOrValue(}, })
+ listener: endClassOrMixinBody(DeclarationKind.Class, 1, {, })
+ listener: endClassDeclaration(class, })
+ listener: endTopLevelDeclaration()
+ reportAllErrorTokens(UnmatchedToken(())
+ listener: handleErrorToken(UnmatchedToken(())
+ listener: handleRecoverableError(Message[UnmatchedToken, Can't find ')' to match '('., null, {string: ), lexeme: (}], UnmatchedToken((), UnmatchedToken(())
+ listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.parser.expect
new file mode 100644
index 0000000..8515a43
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.parser.expect
@@ -0,0 +1,15 @@
+NOTICE: Stream was rewritten by parser!
+
+class Foo<T> {
+foo(Object? key) {
+if (key is! T )or
+;}
+}
+
+
+[UnmatchedToken]class[KeywordToken] Foo[StringToken]<[BeginToken]T[StringToken]>[SimpleToken] {[BeginToken]
+foo[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] key[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]key[StringToken] is[KeywordToken]![SimpleToken] T[StringToken] )[SyntheticToken]or[StringToken]
+;[SyntheticToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.scanner.expect
new file mode 100644
index 0000000..b7836d3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_45327_prime_1.crash_dart.scanner.expect
@@ -0,0 +1,13 @@
+class Foo<T> {
+foo(Object? key) {
+if (key is! T or
+)}
+}
+
+
+[UnmatchedToken]class[KeywordToken] Foo[StringToken]<[BeginToken]T[StringToken]>[SimpleToken] {[BeginToken]
+foo[StringToken]([BeginToken]Object[StringToken]?[SimpleToken] key[StringToken])[SimpleToken] {[BeginToken]
+if[KeywordToken] ([BeginToken]key[StringToken] is[KeywordToken]![SimpleToken] T[StringToken] or[StringToken]
+)[SyntheticToken]}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline.expect b/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline.expect
index e109be7..0224cb7 100644
--- a/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline.expect
@@ -1,15 +1,19 @@
class A<T> {
const A();
}
+
class B<S, T> {
const B();
}
+
class C<T extends num> {
const C();
}
+
class D<S extends num, T extends S> {
const D();
}
+
@A<int, num>()
@B<int>()
@C<String>()
diff --git a/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d5e1444
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/generic_metadata.dart.textual_outline_modelled.expect
@@ -0,0 +1,32 @@
+class A<T> {
+ const A();
+}
+
+class B<S, T> {
+ const B();
+}
+
+class C<T extends num> {
+ const C();
+}
+
+class D<S extends num, T extends S> {
+ const D();
+}
+
+@A()
+@A<int>()
+@B()
+@B<int, String>()
+@C()
+@C<num>()
+@C<int>()
+@D()
+@D<num, num>()
+@D<num, int>()
+main() {}
+@A<int, num>()
+@B<int>()
+@C<String>()
+@D<int, num>()
+test() {}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 6fef290..b703c23 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -62,7 +62,6 @@
general/null_safety_invalid_experiment_and_language_version: FormatterCrash
general/type_parameters_on_void: FormatterCrash
general/var_as_type_name: FormatterCrash
-generic_metadata/generic_metadata: FormatterCrash
inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1: FormatterCrash
inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1: FormatterCrash
late_lowering/covariant_late_field: FormatterCrash
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index 11032aa..c40fde0 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -884,6 +884,13 @@
}
@override
+ R visitExtensionReference(Extension node) {
+ throw new UnimplementedError(
+ 'Unimplemented ${runtimeType}.visitExtensionReference for '
+ '${node} (${node.runtimeType})');
+ }
+
+ @override
R defaultConstantReference(Constant node) {
throw new UnimplementedError(
'Unimplemented ${runtimeType}.defaultConstantReference for '
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart b/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
index 1cb4d54..183f332 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
@@ -7708,7 +7708,7 @@
''';
String _migration_js;
-// migration_dart md5 is 'a1ff0191d3960968e178bcb372181074'
+// migration_dart md5 is '542403f76ced1ab36ca5079ac60b8199'
String _migration_js_base64 = '''
KGZ1bmN0aW9uIGRhcnRQcm9ncmFtKCl7ZnVuY3Rpb24gY29weVByb3BlcnRpZXMoYSxiKXt2YXIgcz1P
YmplY3Qua2V5cyhhKQpmb3IodmFyIHI9MDtyPHMubGVuZ3RoO3IrKyl7dmFyIHE9c1tyXQpiW3FdPWFb
@@ -9339,20 +9339,20 @@
c2UgcmV0dXJuIGF9LApPdDpmdW5jdGlvbihhKXtzd2l0Y2goYS5yKXtjYXNlIEMuY3c6YnJlYWsKY2Fz
ZSBDLldEOmEucj1DLlhqCmJyZWFrCmNhc2UgQy5YajphLnI9Qy5XRApicmVhawpjYXNlIEMuZGM6dGhy
b3cgSC5iKFAuUFYoIkZpbGUgIitILkVqKGEuYykrIiBzaG91bGQgbm90IGhhdmUgaW5kZXRlcm1pbmF0
-ZSBtaWdyYXRpb24gc3RhdHVzIikpfX0sCnhuOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPSJkaXNhYmxl
-ZCIscD1iLmdMKCkKTC50YShhLHApCmlmKGIuYz09JC5EOSgpLmlubmVyVGV4dCl7cz1iIGluc3RhbmNl
-b2YgTC5jRCYmIUgub1QoYi54KQpyPUouWUUoYSkKaWYocylyLmdQKGEpLmkoMCxxKQplbHNlIHIuZ1Ao
-YSkuUigwLHEpCkwudGEoJC5jMCgpLHApfX0sCnRhOmZ1bmN0aW9uKGEsYil7dmFyIHMscj0iY2hlY2tf
-Ym94IixxPSJ0aXRsZSIscD0ib3B0ZWQtb3V0IixvPSJtaWdyYXRpbmciCnN3aXRjaChiKXtjYXNlIEMu
-Y3c6YS5pbm5lclRleHQ9cgpzPUouWUUoYSkKcy5nUChhKS5pKDAsImFscmVhZHktbWlncmF0ZWQiKQpz
-LmdQKGEpLmkoMCwiZGlzYWJsZWQiKQphLnNldEF0dHJpYnV0ZShxLCJBbHJlYWR5IG1pZ3JhdGVkIikK
-YnJlYWsKY2FzZSBDLldEOmEuaW5uZXJUZXh0PXIKcz1KLllFKGEpCnMuZ1AoYSkuUigwLHApCnMuZ1Ao
-YSkuaSgwLG8pCmEuc2V0QXR0cmlidXRlKHEsIk1pZ3JhdGluZyB0byBudWxsIHNhZmV0eSIpCmJyZWFr
-CmNhc2UgQy5YajphLmlubmVyVGV4dD0iY2hlY2tfYm94X291dGxpbmVfYmxhbmsiCnM9Si5ZRShhKQpz
-LmdQKGEpLlIoMCxvKQpzLmdQKGEpLmkoMCxwKQphLnNldEF0dHJpYnV0ZShxLCJPcHRpbmcgb3V0IG9m
-IG51bGwgc2FmZXR5IikKYnJlYWsKZGVmYXVsdDphLmlubmVyVGV4dD0iaW5kZXRlcm1pbmF0ZV9jaGVj
-a19ib3giCnM9Si5ZRShhKQpzLmdQKGEpLlIoMCxvKQpzLmdQKGEpLmkoMCxwKQphLnNldEF0dHJpYnV0
-ZShxLCJNaXhlZCBzdGF0dXNlcyBvZiAnbWlncmF0aW5nJyBhbmQgJ29wdGluZyBvdXQnIikKYnJlYWt9
+ZSBtaWdyYXRpb24gc3RhdHVzIikpfX0sCnRhOmZ1bmN0aW9uKGEsYil7dmFyIHMscj0iY2hlY2tfYm94
+IixxPSJ0aXRsZSIscD0ib3B0ZWQtb3V0IixvPSJtaWdyYXRpbmciCnN3aXRjaChiKXtjYXNlIEMuY3c6
+YS5pbm5lclRleHQ9cgpzPUouWUUoYSkKcy5nUChhKS5pKDAsImFscmVhZHktbWlncmF0ZWQiKQpzLmdQ
+KGEpLmkoMCwiZGlzYWJsZWQiKQphLnNldEF0dHJpYnV0ZShxLCJBbHJlYWR5IG1pZ3JhdGVkIikKYnJl
+YWsKY2FzZSBDLldEOmEuaW5uZXJUZXh0PXIKcz1KLllFKGEpCnMuZ1AoYSkuUigwLHApCnMuZ1AoYSku
+aSgwLG8pCmEuc2V0QXR0cmlidXRlKHEsIk1pZ3JhdGluZyB0byBudWxsIHNhZmV0eSIpCmJyZWFrCmNh
+c2UgQy5YajphLmlubmVyVGV4dD0iY2hlY2tfYm94X291dGxpbmVfYmxhbmsiCnM9Si5ZRShhKQpzLmdQ
+KGEpLlIoMCxvKQpzLmdQKGEpLmkoMCxwKQphLnNldEF0dHJpYnV0ZShxLCJPcHRpbmcgb3V0IG9mIG51
+bGwgc2FmZXR5IikKYnJlYWsKZGVmYXVsdDphLmlubmVyVGV4dD0iaW5kZXRlcm1pbmF0ZV9jaGVja19i
+b3giCnM9Si5ZRShhKQpzLmdQKGEpLlIoMCxvKQpzLmdQKGEpLmkoMCxwKQphLnNldEF0dHJpYnV0ZShx
+LCJNaXhlZCBzdGF0dXNlcyBvZiAnbWlncmF0aW5nJyBhbmQgJ29wdGluZyBvdXQnIikKYnJlYWt9fSwK
+eG46ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9ImRpc2FibGVkIixwPWIuZ0woKQpMLnRhKGEscCkKaWYo
+Yi5jPT0kLkQ5KCkuaW5uZXJUZXh0KXtzPWIgaW5zdGFuY2VvZiBMLmNEJiYhSC5vVChiLngpCnI9Si5Z
+RShhKQppZihzKXIuZ1AoYSkuaSgwLHEpCmVsc2Ugci5nUChhKS5SKDAscSkKTC50YSgkLmMwKCkscCl9
fSwKQlg6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9e30KcS5hPWEKYT1MLkVuKGEpCnEuYT1hCkouZHIo
JC5EOSgpLGEpCnM9ZG9jdW1lbnQKSC5EaCh0LmcsdC5oLCJUIiwicXVlcnlTZWxlY3RvckFsbCIpCnM9
bmV3IFcud3oocy5xdWVyeVNlbGVjdG9yQWxsKCIubmF2LXBhbmVsIC5uYXYtbGluayIpLHQuUikKcy5L
@@ -11572,11 +11572,11 @@
dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIuZWRpdC1wYW5lbCAucGFuZWwtY29udGVudCIpfSkKcigk
LCJUUiIsIkRXIixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiZm9vdGVyIil9
KQpyKCQsIkVZIiwiZmkiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCJoZWFk
-ZXIiKX0pCnIoJCwiYXYiLCJEOSIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3Io
-IiN1bml0LW5hbWUiKX0pCnIoJCwidDAiLCJiTiIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5
-U2VsZWN0b3IoIiNtaWdyYXRlLXVuaXQtc3RhdHVzLWljb24tbGFiZWwiKX0pCnIoJCwiYkEiLCJjMCIs
-ZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiNtaWdyYXRlLXVuaXQtc3RhdHVz
-LWljb24iKX0pCnIoJCwiZmUiLCJLRyIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEwuWEEoKX0pCnMoJCwi
+ZXIiKX0pCnIoJCwiYkEiLCJjMCIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3Io
+IiNtaWdyYXRlLXVuaXQtc3RhdHVzLWljb24iKX0pCnIoJCwidDAiLCJiTiIsZnVuY3Rpb24oKXtyZXR1
+cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiNtaWdyYXRlLXVuaXQtc3RhdHVzLWljb24tbGFiZWwiKX0p
+CnIoJCwiYXYiLCJEOSIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiN1bml0
+LW5hbWUiKX0pCnIoJCwiZmUiLCJLRyIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEwuWEEoKX0pCnMoJCwi
ZW8iLCJuVSIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IE0ubEkoJC5IaygpKX0pCnMoJCwieXIiLCJiRCIs
ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEUuT0YoUC5udSgiLyIpLFAubnUoIlteL10kIiksUC5udSgiXi8i
KSl9KQpzKCQsIk1rIiwiS2siLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLklWKFAubnUoIlsvXFxcXF0i
diff --git a/pkg/nnbd_migration/lib/src/front_end/web/migration.dart b/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
index 672b45c..c01ccee 100644
--- a/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
@@ -129,20 +129,20 @@
final Element headerPanel = document.querySelector('header');
-final Element unitName = document.querySelector('#unit-name');
+final Element migrateUnitStatusIcon =
+ document.querySelector('#migrate-unit-status-icon');
final Element migrateUnitStatusIconLabel =
document.querySelector('#migrate-unit-status-icon-label');
-final Element migrateUnitStatusIcon =
- document.querySelector('#migrate-unit-status-icon');
+List<NavigationTreeNode> /*?*/ navigationTree;
+
+final Element unitName = document.querySelector('#unit-name');
String get rootPath => querySelector('.root').text.trim();
String get sdkVersion => document.getElementById('sdk-version').text;
-List<NavigationTreeNode> /*?*/ navigationTree;
-
void addArrowClickHandler(Element arrow) {
var childList = (arrow.parentNode as Element).querySelector(':scope > ul');
// Animating height from "auto" to "0" is not supported by CSS [1], so all we
@@ -730,25 +730,6 @@
}
}
-/// Updates the navigation [icon] and current file icon according to the current
-/// migration status of [entity].
-void updateIconsForNode(Element icon, NavigationTreeNode entity) {
- var status = entity.migrationStatus;
- updateIconForStatus(icon, status);
- // Update the status at the top of the file view if [entity] represents the
- // current file.
- var unitPath = unitName.innerText;
- if (entity.path == unitPath) {
- if (entity is NavigationTreeFileNode &&
- !entity.migrationStatusCanBeChanged) {
- icon.classes.add('disabled');
- } else {
- icon.classes.remove('disabled');
- }
- updateIconForStatus(migrateUnitStatusIcon, status);
- }
-}
-
/// Updates [icon] according to [status].
void updateIconForStatus(Element icon, UnitMigrationStatus status) {
switch (status) {
@@ -781,6 +762,25 @@
}
}
+/// Updates the navigation [icon] and current file icon according to the current
+/// migration status of [entity].
+void updateIconsForNode(Element icon, NavigationTreeNode entity) {
+ var status = entity.migrationStatus;
+ updateIconForStatus(icon, status);
+ // Update the status at the top of the file view if [entity] represents the
+ // current file.
+ var unitPath = unitName.innerText;
+ if (entity.path == unitPath) {
+ if (entity is NavigationTreeFileNode &&
+ !entity.migrationStatusCanBeChanged) {
+ icon.classes.add('disabled');
+ } else {
+ icon.classes.remove('disabled');
+ }
+ updateIconForStatus(migrateUnitStatusIcon, status);
+ }
+}
+
/// Update the heading and navigation links.
///
/// Call this after updating page content on a navigation.
diff --git a/pkg/nnbd_migration/tool/codegen/extract_resource.dart b/pkg/nnbd_migration/tool/codegen/extract_resource.dart
new file mode 100644
index 0000000..3b60593
--- /dev/null
+++ b/pkg/nnbd_migration/tool/codegen/extract_resource.dart
@@ -0,0 +1,128 @@
+// 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.
+
+// This script provides a quick way, via the command line, to extract one of the
+// resources encoded in the file lib/src/front_end/resources/resources.g.dart.
+
+import 'dart:convert';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:analyzer/dart/analysis/utilities.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:args/args.dart';
+import 'package:path/path.dart' as path;
+
+main(List<String> args) {
+ var argResults = argParser.parse(args);
+ if (argResults['help'] as bool) {
+ fail(null, showUsage: true);
+ }
+ if (argResults.rest.isNotEmpty) {
+ fail('Unexpected extra arguments', showUsage: true);
+ }
+ bool list = argResults['list'] as bool;
+ String path = argResults['path'] as String;
+ String resource = argResults['resource'] as String;
+ if (list && resource != null) {
+ fail('Only one of --resource and --list may be provided');
+ } else if (!list && resource == null) {
+ fail('Either --resource or --list must be provided');
+ }
+ var file = locateResourcesFile(path);
+ var parseResult =
+ parseString(content: file.readAsStringSync(), path: file.path);
+ final variableNameRegExp = RegExp(r'^_(.*)_base64$');
+ for (var declaration in parseResult.unit.declarations) {
+ if (declaration is TopLevelVariableDeclaration) {
+ for (var variable in declaration.variables.variables) {
+ if (variable.initializer == null) continue;
+ var match = variableNameRegExp.matchAsPrefix(variable.name.name);
+ if (match == null) continue;
+ var shortName = match.group(1);
+ if (list) {
+ stdout.writeln(shortName);
+ } else if (resource == shortName) {
+ stdout.add(decodeVariableDeclaration(variable));
+ return;
+ }
+ }
+ }
+ }
+ if (list) {
+ return;
+ } else {
+ fail('Resource $resource not found in ${file.path}');
+ }
+}
+
+final argParser = ArgParser()
+ ..addOption('resource',
+ abbr: 'r', valueHelp: 'RESOURCE', help: 'Extract resource RESOURCE')
+ ..addFlag('list',
+ negatable: false, abbr: 'l', help: 'List which resources are present')
+ ..addOption('path',
+ abbr: 'p',
+ valueHelp: 'PATH',
+ help:
+ 'Search for resources.g.dart inside PATH rather than current working '
+ 'directory')
+ ..addFlag('help', negatable: false, abbr: 'h');
+
+Uint8List decodeVariableDeclaration(VariableDeclaration variable) {
+ var initializer = variable.initializer as StringLiteral;
+ var stringValue = initializer.stringValue;
+ return base64.decode(stringValue.replaceAll('\n', '').trim());
+}
+
+void fail(String message, {bool showUsage = false}) {
+ if (message != null) {
+ stderr.writeln(message);
+ }
+ if (showUsage) {
+ stderr.writeln('''
+usage: dart pkg/nnbd_migration/tool/codegen/extract_resource.dart -r <resource>
+
+Reads the file `resources.g.dart` from the appropriate directory, extracts the
+embedded resource named `<resource>`, and prints it to standard out.
+''');
+ stderr.writeln(argParser.usage);
+ }
+ exit(1);
+}
+
+/// Tries to guess the location of `resources.g.dart` using optional [pathHint]
+/// as a starting point.
+File locateResourcesFile(String pathHint) {
+ pathHint ??= '.';
+ final pathParts =
+ 'pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart'
+ .split('/');
+ var currentPath = path.normalize(pathHint);
+ while (true) {
+ for (int i = 0; i <= pathParts.length; i++) {
+ var pathToTry = path.normalize(path.join(
+ currentPath, path.joinAll(pathParts.sublist(pathParts.length - i))));
+ var file = File(pathToTry);
+ var type = file.statSync().type;
+ if (type == FileSystemEntityType.notFound && i == 0) {
+ fail('No such file or directory: $pathToTry');
+ }
+ if (type == FileSystemEntityType.link) {
+ type = File(file.resolveSymbolicLinksSync()).statSync().type;
+ }
+ if (type == FileSystemEntityType.file) {
+ return file;
+ }
+ }
+ if (currentPath == '.') {
+ currentPath = Directory.current.path;
+ }
+ var nextPath = path.dirname(currentPath);
+ if (nextPath == currentPath) {
+ fail('Could not find file `resources.g.dart` starting at $pathHint');
+ }
+ currentPath = nextPath;
+ }
+}
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index d390576..ef653b0 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1069,7 +1069,6 @@
s->Push(data->untag()->parent_function_);
s->Push(data->untag()->closure_);
s->Push(data->untag()->default_type_arguments_);
- s->Push(data->untag()->default_type_arguments_info_);
}
void WriteAlloc(Serializer* s) {
@@ -1093,7 +1092,8 @@
WriteField(data, parent_function_);
WriteField(data, closure_);
WriteField(data, default_type_arguments_);
- WriteField(data, default_type_arguments_info_);
+ s->WriteUnsigned(
+ static_cast<intptr_t>(data->untag()->default_type_arguments_kind_));
}
}
@@ -1134,8 +1134,8 @@
data->untag()->closure_ = static_cast<InstancePtr>(d->ReadRef());
data->untag()->default_type_arguments_ =
static_cast<TypeArgumentsPtr>(d->ReadRef());
- data->untag()->default_type_arguments_info_ =
- static_cast<SmiPtr>(d->ReadRef());
+ data->untag()->default_type_arguments_kind_ =
+ static_cast<ClosureData::DefaultTypeArgumentsKind>(d->ReadUnsigned());
}
}
};
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 2821fad..8aa57f7 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -2768,7 +2768,7 @@
case Slot::Kind::kClosure_instantiator_type_arguments:
case Slot::Kind::kClosure_hash:
case Slot::Kind::kClosureData_default_type_arguments:
- case Slot::Kind::kClosureData_default_type_arguments_info:
+ case Slot::Kind::kClosureData_default_type_arguments_kind:
case Slot::Kind::kCapturedVariable:
case Slot::Kind::kDartField:
case Slot::Kind::kFunction_data:
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index cac72cc..e39dff8 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2742,8 +2742,9 @@
switch (r) {
case kTagged:
return RangeBoundary::kRangeBoundarySmi;
+ case kUnboxedUint8: // Overapproximate Uint8 as Int16.
+ return RangeBoundary::kRangeBoundaryInt16;
case kUnboxedInt32:
- case kUnboxedUint8: // Overapproximate Uint8 as Int32.
return RangeBoundary::kRangeBoundaryInt32;
case kUnboxedInt64:
case kUnboxedUint32: // Overapproximate Uint32 as Int64.
@@ -2821,6 +2822,7 @@
UNREACHABLE();
break;
+ case Slot::Kind::kClosureData_default_type_arguments_kind:
case Slot::Kind::kFunction_kind_tag:
case Slot::Kind::kFunction_packed_fields:
case Slot::Kind::kTypeParameter_flags:
@@ -2841,9 +2843,6 @@
case Slot::Kind::kArgumentsDescriptor_size:
*range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
break;
-
- case Slot::Kind::kClosureData_default_type_arguments_info:
- *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
}
}
diff --git a/runtime/vm/compiler/backend/range_analysis.h b/runtime/vm/compiler/backend/range_analysis.h
index ab21d74..b0037f4 100644
--- a/runtime/vm/compiler/backend/range_analysis.h
+++ b/runtime/vm/compiler/backend/range_analysis.h
@@ -32,6 +32,7 @@
enum RangeSize {
kRangeBoundarySmi,
+ kRangeBoundaryInt16,
kRangeBoundaryInt32,
kRangeBoundaryInt64,
};
@@ -97,6 +98,8 @@
switch (size) {
case kRangeBoundarySmi:
return FromConstant(compiler::target::kSmiMin);
+ case kRangeBoundaryInt16:
+ return FromConstant(kMinInt16);
case kRangeBoundaryInt32:
return FromConstant(kMinInt32);
case kRangeBoundaryInt64:
@@ -110,6 +113,8 @@
switch (size) {
case kRangeBoundarySmi:
return FromConstant(compiler::target::kSmiMax);
+ case kRangeBoundaryInt16:
+ return FromConstant(kMaxInt16);
case kRangeBoundaryInt32:
return FromConstant(kMaxInt32);
case kRangeBoundaryInt64:
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 3a2a1cd..8096b2d 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -83,7 +83,6 @@
V(Closure, UntaggedClosure, function, Function, FINAL) \
V(Closure, UntaggedClosure, context, Context, FINAL) \
V(Closure, UntaggedClosure, hash, Context, VAR) \
- V(ClosureData, UntaggedClosureData, default_type_arguments_info, Smi, FINAL) \
V(Function, UntaggedFunction, data, Dynamic, FINAL) \
V(FunctionType, UntaggedFunctionType, parameter_names, Array, FINAL) \
V(FunctionType, UntaggedFunctionType, parameter_types, Array, FINAL) \
@@ -125,6 +124,8 @@
//
// Note: As the underlying field is unboxed, these slots cannot be nullable.
#define UNBOXED_NATIVE_SLOTS_LIST(V) \
+ V(ClosureData, UntaggedClosureData, default_type_arguments_kind, Uint8, \
+ FINAL) \
V(Function, UntaggedFunction, kind_tag, Uint32, FINAL) \
V(Function, UntaggedFunction, packed_fields, Uint32, FINAL) \
V(FunctionType, UntaggedFunctionType, packed_fields, Uint32, FINAL) \
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index dce6e90..c8e01c4 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -900,7 +900,7 @@
} else if (type_ != NULL) {
type_name = type_->IsDynamicType()
? "*"
- : String::Handle(type_->UserVisibleName()).ToCString();
+ : String::Handle(type_->ScrubbedName()).ToCString();
} else if (!is_nullable()) {
type_name = "!null";
}
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
index 7c0d3ad..215ced2 100644
--- a/runtime/vm/compiler/frontend/constant_reader.cc
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -122,6 +122,9 @@
KernelReaderHelper reader(Z, &H, script_, H.constants_table(), 0);
reader.ReadUInt(); // skip variable-sized int for adjusted constant offset
reader.SetOffset(reader.ReaderOffset() + constant_offset);
+ // No function types returned as part of any types built should reference
+ // free parent type args, ensured by clearing the enclosing function type.
+ ActiveEnclosingFunctionScope scope(active_class_, nullptr);
// Construct constant from raw bytes.
Instance& instance = Instance::Handle(Z);
const intptr_t constant_tag = reader.ReadByte();
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index db41553..7437768 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1598,9 +1598,8 @@
StoreInstanceFieldInstr::Kind::kInitializing);
}
- // The function signature cannot have uninstantiated function type parameters,
- // because the function cannot be local and have parent generic functions.
- ASSERT(target.HasInstantiatedSignature(kFunctions));
+ // The function cannot be local and have parent generic functions.
+ ASSERT(!target.HasGenericParent());
// Allocate a context that closes over `this`.
// Note: this must be kept in sync with ScopeBuilder::BuildScopes.
@@ -2095,8 +2094,6 @@
LocalVariable* parameter_names = nullptr;
LocalVariable* parameter_types = nullptr;
LocalVariable* type_parameters = nullptr;
- LocalVariable* closure_data = nullptr;
- LocalVariable* default_tav_info = nullptr;
LocalVariable* instantiator_type_args = nullptr;
LocalVariable* parent_function_type_args = nullptr;
};
@@ -2216,38 +2213,40 @@
// Load the defaults, instantiating or replacing them with the other type
// arguments as appropriate.
Fragment store_default;
- store_default += LoadLocal(info.default_tav_info);
- static_assert(
- Function::DefaultTypeArgumentsKindField::shift() == 0,
- "Need to generate shift for DefaultTypeArgumentsKindField bit field");
- store_default += IntConstant(Function::DefaultTypeArgumentsKindField::mask());
- store_default += SmiBinaryOp(Token::kBIT_AND);
+ store_default += LoadLocal(info.closure);
+ store_default += LoadNativeField(Slot::Closure_function());
+ store_default += LoadNativeField(Slot::Function_data());
+ LocalVariable* closure_data = MakeTemporary("closure_data");
+
+ store_default += LoadLocal(closure_data);
+ const auto& slot = Slot::ClosureData_default_type_arguments_kind();
+ store_default += LoadNativeField(slot);
+ store_default += Box(slot.representation());
LocalVariable* default_tav_kind = MakeTemporary("default_tav_kind");
- // One read-only stack values (default_tav_kind) that must be dropped after
- // rejoining at done.
+ // Two locals to drop after join, closure_data and default_tav_kind.
JoinEntryInstr* done = BuildJoinEntry();
store_default += LoadLocal(default_tav_kind);
TargetEntryInstr *is_instantiated, *is_not_instantiated;
store_default += IntConstant(static_cast<intptr_t>(
- Function::DefaultTypeArgumentsKind::kIsInstantiated));
+ ClosureData::DefaultTypeArgumentsKind::kIsInstantiated));
store_default += BranchIfEqual(&is_instantiated, &is_not_instantiated);
store_default.current = is_not_instantiated; // Check next case.
store_default += LoadLocal(default_tav_kind);
TargetEntryInstr *needs_instantiation, *can_share;
store_default += IntConstant(static_cast<intptr_t>(
- Function::DefaultTypeArgumentsKind::kNeedsInstantiation));
+ ClosureData::DefaultTypeArgumentsKind::kNeedsInstantiation));
store_default += BranchIfEqual(&needs_instantiation, &can_share);
store_default.current = can_share; // Check next case.
store_default += LoadLocal(default_tav_kind);
TargetEntryInstr *can_share_instantiator, *can_share_function;
store_default += IntConstant(static_cast<intptr_t>(
- Function::DefaultTypeArgumentsKind::kSharesInstantiatorTypeArguments));
+ ClosureData::DefaultTypeArgumentsKind::kSharesInstantiatorTypeArguments));
store_default += BranchIfEqual(&can_share_instantiator, &can_share_function);
Fragment instantiated(is_instantiated);
- instantiated += LoadLocal(info.closure_data);
+ instantiated += LoadLocal(closure_data);
instantiated += LoadNativeField(Slot::ClosureData_default_type_arguments());
instantiated += StoreLocal(info.vars->function_type_args);
instantiated += Drop();
@@ -2260,7 +2259,7 @@
// can be used within the defaults).
do_instantiation += LoadLocal(info.parent_function_type_args);
// Load the default type arguments to instantiate.
- do_instantiation += LoadLocal(info.closure_data);
+ do_instantiation += LoadLocal(closure_data);
do_instantiation +=
LoadNativeField(Slot::ClosureData_default_type_arguments());
do_instantiation += InstantiateDynamicTypeArguments();
@@ -2284,6 +2283,7 @@
store_default.current = done; // Return here after branching.
store_default += DropTemporary(&default_tav_kind);
+ store_default += DropTemporary(&closure_data);
Fragment store_delayed;
store_delayed += LoadLocal(info.closure);
@@ -2723,13 +2723,6 @@
// full set of function type arguments, then check the local function type
// arguments against the closure function's type parameter bounds.
Fragment generic;
- generic += LoadLocal(info.closure);
- generic += LoadNativeField(Slot::Closure_function());
- generic += LoadNativeField(Slot::Function_data());
- info.closure_data = MakeTemporary("closure_data");
- generic += LoadLocal(info.closure_data);
- generic += LoadNativeField(Slot::ClosureData_default_type_arguments_info());
- info.default_tav_info = MakeTemporary("default_tav_info");
// Calculate the local function type arguments and store them in
// info.vars->function_type_args.
generic += BuildClosureCallDefaultTypeHandling(info);
@@ -2738,13 +2731,10 @@
// Load the parent function type args.
generic += LoadLocal(info.parent_function_type_args);
// Load the number of parent type parameters.
- generic += LoadLocal(info.default_tav_info);
- static_assert(Function::NumParentTypeParametersField::shift() > 0,
- "No need to shift for NumParentTypeParametersField bit field");
- generic += IntConstant(Function::NumParentTypeParametersField::shift());
- generic += SmiBinaryOp(Token::kSHR);
- generic += IntConstant(Function::NumParentTypeParametersField::mask());
- generic += SmiBinaryOp(Token::kBIT_AND);
+ generic += LoadLocal(info.signature);
+ generic += BuildExtractUnboxedSlotBitFieldIntoSmi<
+ UntaggedFunctionType::PackedNumParentTypeArguments>(
+ Slot::FunctionType_packed_fields());
// Load the number of total type parameters.
LocalVariable* num_parents = MakeTemporary();
generic += LoadLocal(info.type_parameters);
@@ -2757,8 +2747,6 @@
PrependTypeArgumentsFunction(), 4, ICData::kStatic);
generic += StoreLocal(info.vars->function_type_args);
generic += Drop();
- generic += DropTemporary(&info.default_tav_info);
- generic += DropTemporary(&info.closure_data);
// Now that we have the full set of function type arguments, check them
// against the type parameter bounds. However, if the local function type
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 5078854..b7126d7 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -3054,22 +3054,26 @@
// Suspend finalization of types inside this one. They will be finalized after
// the whole function type is constructed.
- //
- // TODO(31213): Test further when nested generic function types
- // are supported by fasta.
bool finalize = finalize_;
finalize_ = false;
+ intptr_t type_parameter_count = 0;
if (!simple) {
+ type_parameter_count = helper_->ReadListLength();
LoadAndSetupTypeParameters(
active_class_, Object::null_function(), Object::null_class(), signature,
- helper_->ReadListLength(), active_class_->klass->nnbd_mode());
+ type_parameter_count, active_class_->klass->nnbd_mode());
}
ActiveTypeParametersScope scope(
active_class_, &signature,
TypeArguments::Handle(Z, signature.type_parameters()), Z);
+ if (!simple) {
+ LoadAndSetupBounds(active_class_, Object::null_function(),
+ Object::null_class(), signature, type_parameter_count);
+ }
+
intptr_t required_count;
intptr_t all_count;
intptr_t positional_count;
@@ -3324,7 +3328,6 @@
? Nullability::kNonNullable
: Nullability::kLegacy;
- // Step a)
// - Create array of [TypeParameter] objects (without bound).
// - Create array of [String] objects.
type_parameters = TypeArguments::New(type_parameter_count);
@@ -3354,20 +3357,35 @@
} else {
name = H.DartIdentifier(lib, helper.name_index_).ptr();
}
+ // Bounds are filled later in LoadAndSetupBounds as bound types may
+ // reference type parameters which are not created yet.
parameter = TypeParameter::New(
parameterized_class, offset, offset + i, name, null_bound,
helper.IsGenericCovariantImpl(), nullability);
type_parameters.SetTypeAt(i, parameter);
}
}
+}
- const FunctionType* enclosing = NULL;
- if (!parameterized_signature.IsNull()) {
- enclosing = ¶meterized_signature;
+void TypeTranslator::LoadAndSetupBounds(
+ ActiveClass* active_class,
+ const Function& function,
+ const Class& parameterized_class,
+ const FunctionType& parameterized_signature,
+ intptr_t type_parameter_count) {
+ ASSERT(parameterized_class.IsNull() != parameterized_signature.IsNull());
+ ASSERT(type_parameter_count >= 0);
+ if (type_parameter_count == 0) {
+ return;
}
- ActiveTypeParametersScope scope(active_class, enclosing, type_parameters, Z);
- // Step b) Fill in the bounds and default arguments of all [TypeParameter]s.
+ const TypeArguments& type_parameters =
+ TypeArguments::Handle(Z, !parameterized_class.IsNull()
+ ? parameterized_class.type_parameters()
+ : parameterized_signature.type_parameters());
+ TypeParameter& parameter = TypeParameter::Handle(Z);
+
+ // Fill in the bounds and default arguments of all [TypeParameter]s.
for (intptr_t i = 0; i < type_parameter_count; i++) {
TypeParameterHelper helper(helper_);
helper.ReadUntilExcludingAndSetJustRead(TypeParameterHelper::kBound);
@@ -3389,6 +3407,9 @@
// Fix bounds and default arguments in all derived type parameters (with
// different nullabilities).
+ const intptr_t offset = !parameterized_signature.IsNull()
+ ? parameterized_signature.NumParentTypeArguments()
+ : 0;
if (active_class->derived_type_parameters != nullptr) {
auto& derived = TypeParameter::Handle(Z);
auto& type = AbstractType::Handle(Z);
@@ -3535,15 +3556,22 @@
const FunctionType& signature = FunctionType::Handle(Z, function.signature());
ASSERT(!signature.IsNull());
+ intptr_t type_parameter_count = 0;
if (!is_factory) {
+ type_parameter_count = helper_->ReadListLength();
LoadAndSetupTypeParameters(active_class_, function, Class::Handle(Z),
- signature, helper_->ReadListLength(),
+ signature, type_parameter_count,
function.nnbd_mode());
- function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
}
ActiveTypeParametersScope scope(active_class_, function, &signature, Z);
+ if (!is_factory) {
+ LoadAndSetupBounds(active_class_, function, Class::Handle(Z), signature,
+ type_parameter_count);
+ function_node_helper->SetJustRead(FunctionNodeHelper::kTypeParameters);
+ }
+
function_node_helper->ReadUntilExcluding(
FunctionNodeHelper::kPositionalParameters);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index d5d39fe..03e6378 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -1478,6 +1478,12 @@
intptr_t type_parameter_count,
const NNBDMode nnbd_mode);
+ void LoadAndSetupBounds(ActiveClass* active_class,
+ const Function& function,
+ const Class& parameterized_class,
+ const FunctionType& parameterized_signature,
+ intptr_t type_parameter_count);
+
const Type& ReceiverType(const Class& klass);
void SetupFunctionParameters(const Class& klass,
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 3c934f6..7f0425a 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -1276,7 +1276,7 @@
class ClosureData : public AllStatic {
public:
static word default_type_arguments_offset();
- static word default_type_arguments_info_offset();
+ static word default_type_arguments_kind_offset();
static word InstanceSize();
static word NextFieldOffset();
};
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index efd12ee..70016d86 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -113,7 +113,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 20;
+ ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
24;
@@ -647,7 +647,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -1186,7 +1186,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 20;
+ ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
24;
@@ -1717,7 +1717,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -2257,7 +2257,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -2796,7 +2796,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -3336,7 +3336,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 20;
+ ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
24;
@@ -3864,7 +3864,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -4397,7 +4397,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 20;
+ ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
24;
@@ -4922,7 +4922,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -5456,7 +5456,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -5989,7 +5989,7 @@
static constexpr dart::compiler::target::word
ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- ClosureData_default_type_arguments_info_offset = 40;
+ ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word Code_saved_instructions_offset =
48;
@@ -6530,7 +6530,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 20;
+ AOT_ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 24;
@@ -7125,7 +7125,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -7726,7 +7726,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -8325,7 +8325,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -8923,7 +8923,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -9521,7 +9521,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 20;
+ AOT_ClosureData_default_type_arguments_kind_offset = 20;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 20;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 24;
@@ -10109,7 +10109,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -10703,7 +10703,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -11295,7 +11295,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
@@ -11886,7 +11886,7 @@
static constexpr dart::compiler::target::word
AOT_ClosureData_default_type_arguments_offset = 32;
static constexpr dart::compiler::target::word
- AOT_ClosureData_default_type_arguments_info_offset = 40;
+ AOT_ClosureData_default_type_arguments_kind_offset = 40;
static constexpr dart::compiler::target::word AOT_Code_object_pool_offset = 40;
static constexpr dart::compiler::target::word
AOT_Code_saved_instructions_offset = 48;
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index e708265..d2dac49 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -89,7 +89,7 @@
FIELD(Closure, hash_offset) \
FIELD(Closure, instantiator_type_arguments_offset) \
FIELD(ClosureData, default_type_arguments_offset) \
- FIELD(ClosureData, default_type_arguments_info_offset) \
+ FIELD(ClosureData, default_type_arguments_kind_offset) \
FIELD(Code, object_pool_offset) \
FIELD(Code, saved_instructions_offset) \
FIELD(Code, owner_offset) \
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 7a1788d..58072ba 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1424,6 +1424,9 @@
Object::null_function_type(),
type_parameter_count, klass->nnbd_mode());
+ T.LoadAndSetupBounds(&active_class_, Object::null_function(), *klass,
+ Object::null_function_type(), type_parameter_count);
+
// Set super type. Some classes (e.g., Object) do not have one.
Tag type_tag = helper_.ReadTag(); // read super class type (part 1).
if (type_tag == kSomething) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 4d07a98..e1e0d82 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7057,18 +7057,16 @@
}
FunctionPtr Function::parent_function() const {
- if (IsClosureFunction()) {
- const Object& obj = Object::Handle(untag()->data());
- ASSERT(!obj.IsNull());
- return ClosureData::Cast(obj).parent_function();
- }
- return Function::null();
+ if (!IsClosureFunction()) return Function::null();
+ const Object& obj = Object::Handle(untag()->data());
+ ASSERT(!obj.IsNull());
+ return ClosureData::Cast(obj).parent_function();
}
void Function::set_parent_function(const Function& value) const {
+ ASSERT(IsClosureFunction());
const Object& obj = Object::Handle(untag()->data());
ASSERT(!obj.IsNull());
- ASSERT(IsClosureFunction());
ClosureData::Cast(obj).set_parent_function(value);
}
@@ -7150,8 +7148,7 @@
ClosureData::Handle(ClosureData::RawCast(untag()->data()));
ASSERT(!closure_data.IsNull());
if (kind_out != nullptr) {
- *kind_out = DefaultTypeArgumentsKindField::decode(
- closure_data.default_type_arguments_info());
+ *kind_out = closure_data.default_type_arguments_kind();
}
return closure_data.default_type_arguments();
}
@@ -7163,13 +7160,9 @@
const auto& closure_data =
ClosureData::Handle(ClosureData::RawCast(untag()->data()));
ASSERT(!closure_data.IsNull());
- intptr_t updated_info = closure_data.default_type_arguments_info();
auto kind = DefaultTypeArgumentsKindFor(value);
ASSERT(kind != DefaultTypeArgumentsKind::kInvalid);
- updated_info = DefaultTypeArgumentsKindField::update(kind, updated_info);
- updated_info = NumParentTypeParametersField::update(NumParentTypeArguments(),
- updated_info);
- closure_data.set_default_type_arguments_info(updated_info);
+ closure_data.set_default_type_arguments_kind(kind);
// We could just store null for the ksharesFunction/kSharesInstantiator cases,
// assuming all clients retrieve the DefaultTypeArgumentsKind to distinguish.
closure_data.set_default_type_arguments(value);
@@ -7204,22 +7197,6 @@
return function.ptr();
}
-bool Function::HasGenericParent() const {
- if (IsImplicitClosureFunction()) {
- // The parent function of an implicit closure function is not the enclosing
- // function we are asking about here.
- return false;
- }
- Function& parent = Function::Handle(parent_function());
- while (!parent.IsNull()) {
- if (parent.IsGeneric()) {
- return true;
- }
- parent = parent.parent_function();
- }
- return false;
-}
-
FunctionPtr Function::implicit_closure_function() const {
if (IsClosureFunction() || IsFactory() || IsDispatcherOrImplicitAccessor() ||
IsFieldInitializer() || IsFfiTrampoline()) {
@@ -7721,17 +7698,9 @@
}
intptr_t Function::NumParentTypeArguments() const {
- if (IsImplicitClosureFunction()) {
- return 0;
- }
- Function& parent = Function::Handle(parent_function());
- intptr_t num_parent_type_args = 0;
- while (!parent.IsNull()) {
- num_parent_type_args += parent.NumTypeParameters();
- if (parent.IsImplicitClosureFunction()) break;
- parent = parent.parent_function();
- }
- return num_parent_type_args;
+ // Don't allocate handle in cases where we know it is 0.
+ if (!IsClosureFunction()) return 0;
+ return FunctionType::Handle(signature()).NumParentTypeArguments();
}
TypeParameterPtr Function::LookupTypeParameter(const String& type_name,
@@ -8420,32 +8389,30 @@
Heap::Space space,
TrailPtr trail) const {
ASSERT(IsFinalized() || IsBeingFinalized());
- // A FunctionType cannot be part of a cycle (self-referencing typedefs are not
- // allowed), therefore, the passed in trail does not need to be propagated to
- // calls instantiating types of the signature.
Zone* zone = Thread::Current()->zone();
- // See the comment on kCurrentAndEnclosingFree to understand why we don't
- // adjust 'num_free_fun_type_params' downward in this case.
const intptr_t num_parent_type_args = NumParentTypeArguments();
bool delete_type_parameters = false;
if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
+ // See the comment on kCurrentAndEnclosingFree to understand why we don't
+ // adjust 'num_free_fun_type_params' downward in this case.
num_free_fun_type_params = kAllFree;
delete_type_parameters = true;
} else {
ASSERT(!IsInstantiated(kAny, num_free_fun_type_params));
- if (IsGeneric() || HasGenericParent()) {
- // We only consider the function type parameters declared by the parents
- // of this signature function as free.
- if (num_parent_type_args < num_free_fun_type_params) {
- num_free_fun_type_params = num_parent_type_args;
- }
+ // We only consider the function type parameters declared by the parents
+ // of this signature function as free.
+ if (num_parent_type_args < num_free_fun_type_params) {
+ num_free_fun_type_params = num_parent_type_args;
}
}
- // TODO(regis): Is this correct to use num_parent_type_args here?
- // Or should it be 0 after instantiation?
+ // The number of parent type parameters that remain uninstantiated.
+ const intptr_t remaining_parent_type_params =
+ num_free_fun_type_params < num_parent_type_args
+ ? num_parent_type_args - num_free_fun_type_params
+ : 0;
FunctionType& sig = FunctionType::Handle(
- FunctionType::New(num_parent_type_args, nullability(), space));
+ FunctionType::New(remaining_parent_type_params, nullability(), space));
AbstractType& type = AbstractType::Handle(zone);
// Copy the type parameters and instantiate their bounds (if necessary).
@@ -8463,7 +8430,7 @@
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
- num_free_fun_type_params, space);
+ num_free_fun_type_params, space, trail);
// A returned null type indicates a failed instantiation in dead code
// that must be propagated up to the caller, the optimizing compiler.
if (type.IsNull()) {
@@ -8498,7 +8465,7 @@
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
- num_free_fun_type_params, space);
+ num_free_fun_type_params, space, trail);
// A returned null type indicates a failed instantiation in dead code that
// must be propagated up to the caller, the optimizing compiler.
if (type.IsNull()) {
@@ -8517,7 +8484,7 @@
if (!type.IsInstantiated(kAny, num_free_fun_type_params)) {
type = type.InstantiateFrom(instantiator_type_arguments,
function_type_arguments,
- num_free_fun_type_params, space);
+ num_free_fun_type_params, space, trail);
// A returned null type indicates a failed instantiation in dead code that
// must be propagated up to the caller, the optimizing compiler.
if (type.IsNull()) {
@@ -9090,7 +9057,7 @@
if (!HasInstantiatedSignature(kCurrentClass)) {
instantiator_type_arguments = receiver.GetTypeArguments();
}
- ASSERT(HasInstantiatedSignature(kFunctions)); // No generic parent function.
+ ASSERT(!HasGenericParent()); // No generic parent function.
return Closure::New(instantiator_type_arguments,
Object::null_type_arguments(), *this, context);
}
@@ -9188,13 +9155,18 @@
if (num_free_fun_type_params == kCurrentAndEnclosingFree) {
num_free_fun_type_params = kAllFree;
} else if (genericity != kCurrentClass) {
- if (IsGeneric() || HasGenericParent()) {
- // We only consider the function type parameters declared by the parents
- // of this signature function as free.
- const int num_parent_type_args = NumParentTypeArguments();
- if (num_parent_type_args < num_free_fun_type_params) {
- num_free_fun_type_params = num_parent_type_args;
- }
+ const intptr_t num_parent_type_args = NumParentTypeArguments();
+ if (num_parent_type_args > 0 && num_free_fun_type_params > 0) {
+ // The number of parent type arguments is cached in the FunctionType, so
+ // we can't consider any FunctionType with free parent type arguments as
+ // fully instantiated. Instead, the FunctionType must be instantiated to
+ // reduce the number of parent type arguments, even if they're unused in
+ // its component types.
+ return false;
+ }
+ // Don't consider local function type parameters as free.
+ if (num_free_fun_type_params > num_parent_type_args) {
+ num_free_fun_type_params = num_parent_type_args;
}
}
AbstractType& type = AbstractType::Handle(result_type());
@@ -9924,20 +9896,14 @@
untag()->set_default_type_arguments(value.ptr());
}
-intptr_t ClosureData::default_type_arguments_info() const {
- const SmiPtr value = untag()->default_type_arguments_info();
- if (value == Smi::null()) {
- static_assert(Function::DefaultTypeArgumentsKindField::decode(0) ==
- Function::DefaultTypeArgumentsKind::kInvalid,
- "Returning valid value for null Smi");
- return 0;
- }
- return Smi::Value(untag()->default_type_arguments_info());
+ClosureData::DefaultTypeArgumentsKind ClosureData::default_type_arguments_kind()
+ const {
+ return LoadNonPointer(&untag()->default_type_arguments_kind_);
}
-void ClosureData::set_default_type_arguments_info(intptr_t value) const {
- ASSERT(Smi::IsValid(value));
- untag()->set_default_type_arguments_info(Smi::New(value));
+void ClosureData::set_default_type_arguments_kind(
+ DefaultTypeArgumentsKind value) const {
+ StoreNonPointer(&untag()->default_type_arguments_kind_, value);
}
ClosureDataPtr ClosureData::New() {
@@ -19467,7 +19433,7 @@
case Nullability::kNonNullable:
return "";
case Nullability::kLegacy:
- return (FLAG_show_internal_names || name_visibility == kInternalName)
+ return (FLAG_show_internal_names || name_visibility != kUserVisibleName)
? "*"
: "";
default:
@@ -19489,6 +19455,13 @@
return Symbols::New(thread, printer.buffer());
}
+StringPtr AbstractType::ScrubbedName() const {
+ Thread* thread = Thread::Current();
+ ZoneTextBuffer printer(thread->zone());
+ PrintName(kScrubbedName, &printer);
+ return Symbols::New(thread, printer.buffer());
+}
+
void AbstractType::PrintName(NameVisibility name_visibility,
BaseTextBuffer* printer) const {
if (IsTypeRef()) {
@@ -19498,11 +19471,9 @@
ref_type.PrintName(name_visibility, printer);
return;
}
- ASSERT(name_visibility != kScrubbedName);
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Class& cls = Class::Handle(zone);
- String& name_str = String::Handle(zone);
if (IsTypeParameter()) {
const TypeParameter& type_param = TypeParameter::Cast(*this);
printer->AddString(String::Handle(type_param.name()).ToCString());
@@ -19528,14 +19499,7 @@
cls = type_class();
// Do not print the full vector, but only the declared type parameters.
num_type_params = cls.NumTypeParameters();
- if (name_visibility == kInternalName) {
- name_str = cls.Name();
- printer->AddString(name_str.ToCString());
- } else {
- ASSERT(name_visibility == kUserVisibleName);
- // Map internal types to their corresponding public interfaces.
- printer->AddString(cls.UserVisibleNameCString());
- }
+ printer->AddString(cls.NameCString(name_visibility));
if (num_type_params > num_args) {
first_type_param_index = 0;
if (!IsFinalized() || IsBeingFinalized()) {
@@ -21153,10 +21117,12 @@
return false;
}
// Compare bounds.
+ if (TestAndAddBuddyToTrail(&trail, other_type_param)) {
+ return true;
+ }
AbstractType& type = AbstractType::Handle(bound());
AbstractType& other_type = AbstractType::Handle(other_type_param.bound());
- if (!TestAndAddBuddyToTrail(&trail, other_type_param) &&
- !type.IsEquivalent(other_type, kind, trail)) {
+ if (!type.IsEquivalent(other_type, kind, trail)) {
return false;
}
if (kind == TypeEquality::kCanonical) {
@@ -21200,11 +21166,13 @@
}
}
// Compare bounds.
+ if (TestAndAddBuddyToTrail(&trail, other_type_param)) {
+ return true;
+ }
AbstractType& upper_bound = AbstractType::Handle(bound());
AbstractType& other_type_param_upper_bound =
AbstractType::Handle(other_type_param.bound());
- if (!TestAndAddBuddyToTrail(&trail, other_type_param) &&
- !upper_bound.IsEquivalent(other_type_param_upper_bound, kind, trail)) {
+ if (!upper_bound.IsEquivalent(other_type_param_upper_bound, kind, trail)) {
return false;
}
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 535c62e..740afd0 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2599,7 +2599,7 @@
// Generic dispatchers only set the number without actual type parameters.
bool IsGeneric() const { return NumTypeParameters() > 0; }
// Return true if any parent function of this function is generic.
- bool HasGenericParent() const;
+ bool HasGenericParent() const { return NumParentTypeArguments() > 0; }
// Not thread-safe; must be called in the main thread.
// Sets function's code and code's function.
@@ -2677,41 +2677,8 @@
// Enclosing function of this local function.
FunctionPtr parent_function() const;
- enum class DefaultTypeArgumentsKind : uint8_t {
- // Only here to make sure it's explicitly set appropriately.
- kInvalid = 0,
- // Must instantiate the default type arguments before use.
- kNeedsInstantiation,
- // The default type arguments are already instantiated.
- kIsInstantiated,
- // Use the instantiator type arguments that would be used to instantiate
- // the default type arguments, as instantiating produces the same result.
- kSharesInstantiatorTypeArguments,
- // Use the function type arguments that would be used to instantiate
- // the default type arguments, as instantiating produces the same result.
- kSharesFunctionTypeArguments,
- };
- static constexpr intptr_t kDefaultTypeArgumentsKindFieldSize = 3;
- static_assert(static_cast<uint8_t>(
- DefaultTypeArgumentsKind::kSharesFunctionTypeArguments) <
- (1 << kDefaultTypeArgumentsKindFieldSize),
- "Wrong bit size chosen for default TAV kind field");
-
- // Fields encoded in an integer stored alongside a default TAV. The size of
- // the integer should be <= the size of a target Smi.
- using DefaultTypeArgumentsKindField =
- BitField<intptr_t,
- DefaultTypeArgumentsKind,
- 0,
- kDefaultTypeArgumentsKindFieldSize>;
- // TODO(regis): Rename to NumParentTypeArgumentsField.
- // Just use the rest of the space for the number of parent type parameters.
- using NumParentTypeParametersField =
- BitField<intptr_t,
- intptr_t,
- DefaultTypeArgumentsKindField::kNextBit,
- compiler::target::kSmiBits -
- DefaultTypeArgumentsKindField::kNextBit>;
+ using DefaultTypeArgumentsKind =
+ UntaggedClosureData::DefaultTypeArgumentsKind;
// Returns a canonicalized vector of the type parameters instantiated
// to bounds. If non-generic, the empty type arguments vector is returned.
@@ -3763,10 +3730,13 @@
static intptr_t default_type_arguments_offset() {
return OFFSET_OF(UntaggedClosureData, default_type_arguments_);
}
- static intptr_t default_type_arguments_info_offset() {
- return OFFSET_OF(UntaggedClosureData, default_type_arguments_info_);
+ static intptr_t default_type_arguments_kind_offset() {
+ return OFFSET_OF(UntaggedClosureData, default_type_arguments_kind_);
}
+ using DefaultTypeArgumentsKind =
+ UntaggedClosureData::DefaultTypeArgumentsKind;
+
private:
ContextScopePtr context_scope() const { return untag()->context_scope_; }
void set_context_scope(const ContextScope& value) const;
@@ -3785,8 +3755,8 @@
}
void set_default_type_arguments(const TypeArguments& value) const;
- intptr_t default_type_arguments_info() const;
- void set_default_type_arguments_info(intptr_t value) const;
+ DefaultTypeArgumentsKind default_type_arguments_kind() const;
+ void set_default_type_arguments_kind(DefaultTypeArgumentsKind value) const;
static ClosureDataPtr New();
@@ -7712,6 +7682,10 @@
// Names of internal classes are mapped to their public interfaces.
virtual StringPtr UserVisibleName() const;
+ // The name of this type, including the names of its type arguments, if any.
+ // Privacy suffixes are dropped.
+ virtual StringPtr ScrubbedName() const;
+
// Return the internal or public name of this type, including the names of its
// type arguments, if any.
void PrintName(NameVisibility visibility, BaseTextBuffer* printer) const;
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 5bf6bc9..adc346f 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1216,9 +1216,29 @@
closure) // Closure object for static implicit closures.
// Instantiate-to-bounds TAV for use when no TAV is provided.
POINTER_FIELD(TypeArgumentsPtr, default_type_arguments)
- // Additional information about the instantiate-to-bounds TAV.
- POINTER_FIELD(SmiPtr, default_type_arguments_info)
- VISIT_TO(ObjectPtr, default_type_arguments_info)
+ VISIT_TO(ObjectPtr, default_type_arguments)
+
+ enum class DefaultTypeArgumentsKind : uint8_t {
+ // Only here to make sure it's explicitly set appropriately.
+ kInvalid = 0,
+ // Must instantiate the default type arguments before use.
+ kNeedsInstantiation,
+ // The default type arguments are already instantiated.
+ kIsInstantiated,
+ // Use the instantiator type arguments that would be used to instantiate
+ // the default type arguments, as instantiating produces the same result.
+ kSharesInstantiatorTypeArguments,
+ // Use the function type arguments that would be used to instantiate
+ // the default type arguments, as instantiating produces the same result.
+ kSharesFunctionTypeArguments,
+ };
+
+ // kernel_to_il.cc assumes we can load the untagged value and box it in a Smi.
+ static_assert(sizeof(DefaultTypeArgumentsKind) * kBitsPerByte <=
+ compiler::target::kSmiBits,
+ "Default type arguments kind must fit in a Smi");
+
+ DefaultTypeArgumentsKind default_type_arguments_kind_;
friend class Function;
};
@@ -2348,6 +2368,8 @@
static constexpr intptr_t kMaxOptionalParametersBits =
UntaggedFunction::kMaxOptionalParametersBits;
+ // The bit fields are public for use in kernel_to_il.cc.
+ public:
typedef BitField<uint32_t, uint8_t, 0, kMaxParentTypeArgumentsBits>
PackedNumParentTypeArguments;
typedef BitField<uint32_t,
@@ -2378,6 +2400,7 @@
"In-place mask for number of optional parameters cannot fit in "
"a Smi on the target architecture");
+ private:
ObjectPtr* to_snapshot(Snapshot::Kind kind) { return to(); }
friend class Function;
diff --git a/sdk_args.gni b/sdk_args.gni
index 2776011..736f414 100644
--- a/sdk_args.gni
+++ b/sdk_args.gni
@@ -18,7 +18,13 @@
#
# to out/ReleaseX64/args.gn. The path above can be extracted from the `.git`
# file under the git worktree folder.
- default_git_folder = "$_dart_root/.git"
+ # The script run here should take care of everything automatically though.
+ default_git_folder = exec_script("$_dart_root/tools/get_dot_git_folder.py",
+ [
+ rebase_path("$_dart_root/.git"),
+ "$_dart_root/.git",
+ ],
+ "trim string")
# Whether to enable the SDK hash check that will prevent loading a kernel
# into a VM which was built with a different SDK.
diff --git a/tests/ffi/unaligned_test.dart b/tests/ffi/unaligned_test.dart
new file mode 100644
index 0000000..3220003
--- /dev/null
+++ b/tests/ffi/unaligned_test.dart
@@ -0,0 +1,74 @@
+// 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.
+
+// This tests exercises misaligned reads/writes on memory.
+//
+// The only architecture on which this is known to fail is arm32 on Android.
+
+import 'dart:ffi';
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:ffi/ffi.dart';
+
+void main() {
+ print("hello");
+ testUnalignedInt16(); //# 01: ok
+ testUnalignedInt32(); //# 02: ok
+ testUnalignedInt64(); //# 03: ok
+ if (!Platform.isAndroid || sizeOf<Pointer>() == 8) {
+ // TODO(http://dartbug.com/45009): Support unaligned reads/writes on
+ // Android arm32.
+ testUnalignedFloat(); //# 04: ok
+ testUnalignedDouble(); //# 05: ok
+ }
+ _freeAll();
+}
+
+void testUnalignedInt16() {
+ final pointer = _allocateUnaligned<Int16>();
+ pointer.value = 20;
+ Expect.equals(20, pointer.value);
+}
+
+void testUnalignedInt32() {
+ final pointer = _allocateUnaligned<Int32>();
+ pointer.value = 20;
+ Expect.equals(20, pointer.value);
+}
+
+void testUnalignedInt64() {
+ final pointer = _allocateUnaligned<Int64>();
+ pointer.value = 20;
+ Expect.equals(20, pointer.value);
+}
+
+void testUnalignedFloat() {
+ final pointer = _allocateUnaligned<Float>();
+ pointer.value = 20.0;
+ Expect.approxEquals(20.0, pointer.value);
+}
+
+void testUnalignedDouble() {
+ final pointer = _allocateUnaligned<Double>();
+ pointer.value = 20.0;
+ Expect.equals(20.0, pointer.value);
+}
+
+final Set<Pointer> _pool = {};
+
+void _freeAll() {
+ for (final pointer in _pool) {
+ calloc.free(pointer);
+ }
+}
+
+/// Up to `size<T>() == 8`.
+Pointer<T> _allocateUnaligned<T extends NativeType>() {
+ final pointer = calloc<Int8>(16);
+ _pool.add(pointer);
+ final misaligned = pointer.elementAt(1).cast<T>();
+ Expect.equals(1, misaligned.address % 2);
+ return misaligned;
+}
diff --git a/tests/ffi_2/unaligned_test.dart b/tests/ffi_2/unaligned_test.dart
new file mode 100644
index 0000000..3220003
--- /dev/null
+++ b/tests/ffi_2/unaligned_test.dart
@@ -0,0 +1,74 @@
+// 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.
+
+// This tests exercises misaligned reads/writes on memory.
+//
+// The only architecture on which this is known to fail is arm32 on Android.
+
+import 'dart:ffi';
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+import 'package:ffi/ffi.dart';
+
+void main() {
+ print("hello");
+ testUnalignedInt16(); //# 01: ok
+ testUnalignedInt32(); //# 02: ok
+ testUnalignedInt64(); //# 03: ok
+ if (!Platform.isAndroid || sizeOf<Pointer>() == 8) {
+ // TODO(http://dartbug.com/45009): Support unaligned reads/writes on
+ // Android arm32.
+ testUnalignedFloat(); //# 04: ok
+ testUnalignedDouble(); //# 05: ok
+ }
+ _freeAll();
+}
+
+void testUnalignedInt16() {
+ final pointer = _allocateUnaligned<Int16>();
+ pointer.value = 20;
+ Expect.equals(20, pointer.value);
+}
+
+void testUnalignedInt32() {
+ final pointer = _allocateUnaligned<Int32>();
+ pointer.value = 20;
+ Expect.equals(20, pointer.value);
+}
+
+void testUnalignedInt64() {
+ final pointer = _allocateUnaligned<Int64>();
+ pointer.value = 20;
+ Expect.equals(20, pointer.value);
+}
+
+void testUnalignedFloat() {
+ final pointer = _allocateUnaligned<Float>();
+ pointer.value = 20.0;
+ Expect.approxEquals(20.0, pointer.value);
+}
+
+void testUnalignedDouble() {
+ final pointer = _allocateUnaligned<Double>();
+ pointer.value = 20.0;
+ Expect.equals(20.0, pointer.value);
+}
+
+final Set<Pointer> _pool = {};
+
+void _freeAll() {
+ for (final pointer in _pool) {
+ calloc.free(pointer);
+ }
+}
+
+/// Up to `size<T>() == 8`.
+Pointer<T> _allocateUnaligned<T extends NativeType>() {
+ final pointer = calloc<Int8>(16);
+ _pool.add(pointer);
+ final misaligned = pointer.elementAt(1).cast<T>();
+ Expect.equals(1, misaligned.address % 2);
+ return misaligned;
+}
diff --git a/tests/language/regress/regress45313_test.dart b/tests/language/regress/regress45313_test.dart
new file mode 100644
index 0000000..0c6a5a1
--- /dev/null
+++ b/tests/language/regress/regress45313_test.dart
@@ -0,0 +1,17 @@
+// 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.
+
+// SharedOptions=--enable-experiment=generic-metadata
+
+import "package:expect/expect.dart";
+
+typedef TEST_TYPEDEF<TT extends T Function<T>(T)> = void
+ Function<TTT extends TT>();
+void testme<TT extends T Function<T>(T)>() {}
+
+main() {
+ Expect.isTrue(testme is TEST_TYPEDEF);
+ TEST_TYPEDEF ttttt = testme;
+ Expect.isTrue(ttttt is TEST_TYPEDEF);
+}
diff --git a/tools/VERSION b/tools/VERSION
index b04191b..7948628 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 143
+PRERELEASE 144
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/get_dot_git_folder.py b/tools/get_dot_git_folder.py
new file mode 100755
index 0000000..443addbf
--- /dev/null
+++ b/tools/get_dot_git_folder.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+# 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.
+#
+# This python script is a wrapper around `git rev-parse --resolve-git-dir`.
+# This is used for the build system to work with git worktrees.
+
+import sys
+import subprocess
+import os
+import utils
+
+
+def main():
+ try:
+ if len(sys.argv) != 3:
+ raise Exception('Expects exactly 2 arguments.')
+ args = ['git', 'rev-parse', '--resolve-git-dir', sys.argv[1]]
+
+ windows = utils.GuessOS() == 'win32'
+ if windows:
+ process = subprocess.Popen(args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ shell=True)
+ else:
+ process = subprocess.Popen(args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ stdin=subprocess.PIPE,
+ shell=False)
+
+ outs, _ = process.communicate()
+
+ if process.returncode != 0:
+ raise Exception('Got non-0 exit code from git.')
+
+ print(outs.strip())
+ except:
+ # Fall back to fall-back path.
+ print(sys.argv[2])
+
+
+if __name__ == '__main__':
+ sys.exit(main())