Version 2.14.0-387.0.dev
Merge commit '4200f6d91500360b2ff5dc130810712deb041005' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_null_aware.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_null_aware.dart
index c6b7dd1..822442d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_null_aware.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_null_aware.dart
@@ -10,11 +10,24 @@
import 'package:analyzer_plugin/utilities/range_factory.dart';
class ReplaceWithNullAware extends CorrectionProducer {
+ /// The kind of correction to be made.
+ final _CorrectionKind correctionKind;
+
+ ReplaceWithNullAware(this.correctionKind);
+
@override
FixKind get fixKind => DartFixKind.REPLACE_WITH_NULL_AWARE;
@override
Future<void> compute(ChangeBuilder builder) async {
+ if (correctionKind == _CorrectionKind.inChain) {
+ await _computeInChain(builder);
+ } else if (correctionKind == _CorrectionKind.single) {
+ await _computeSingle(builder);
+ }
+ }
+
+ Future<void> _computeInChain(ChangeBuilder builder) async {
var node = coveredNode;
if (node is Expression) {
final node_final = node;
@@ -38,6 +51,37 @@
}
}
+ Future<void> _computeSingle(ChangeBuilder builder) async {
+ var node = coveredNode?.parent;
+ if (node is MethodInvocation) {
+ var operator = node.operator;
+ if (operator != null) {
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addSimpleReplacement(range.token(operator), '?.');
+ });
+ }
+ } else if (node is PrefixedIdentifier) {
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addSimpleReplacement(range.token(node.period), '?.');
+ });
+ } else if (node is PropertyAccess) {
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addSimpleReplacement(range.token(node.operator), '?.');
+ });
+ }
+ }
+
/// Return an instance of this class. Used as a tear-off in `FixProcessor`.
- static ReplaceWithNullAware newInstance() => ReplaceWithNullAware();
+ static ReplaceWithNullAware inChain() =>
+ ReplaceWithNullAware(_CorrectionKind.inChain);
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static ReplaceWithNullAware single() =>
+ ReplaceWithNullAware(_CorrectionKind.single);
+}
+
+/// The kinds of corrections supported by [ReplaceWithNullAware].
+enum _CorrectionKind {
+ inChain,
+ single,
}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index c04be05..e4e975c 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -930,12 +930,14 @@
],
CompileTimeErrorCode.UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE: [
AddNullCheck.newInstance,
+ ReplaceWithNullAware.single,
],
CompileTimeErrorCode.UNCHECKED_OPERATOR_INVOCATION_OF_NULLABLE_VALUE: [
AddNullCheck.newInstance,
],
CompileTimeErrorCode.UNCHECKED_PROPERTY_ACCESS_OF_NULLABLE_VALUE: [
AddNullCheck.newInstance,
+ ReplaceWithNullAware.single,
],
CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE: [
AddNullCheck.newInstance,
@@ -1045,7 +1047,7 @@
],
HintCode.CAN_BE_NULL_AFTER_NULL_AWARE: [
- ReplaceWithNullAware.newInstance,
+ ReplaceWithNullAware.inChain,
],
HintCode.DEAD_CODE: [
RemoveDeadCode.newInstance,
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_null_aware_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_null_aware_test.dart
index 282e085..84b84d5 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_with_null_aware_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_null_aware_test.dart
@@ -11,6 +11,8 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(ReplaceWithNullAwareTest);
+ defineReflectiveTests(UncheckedMethodInvocationOfNullableValueTest);
+ defineReflectiveTests(UncheckedPropertyAccessOfNullableValueTest);
});
}
@@ -61,3 +63,90 @@
''');
}
}
+
+@reflectiveTest
+class UncheckedMethodInvocationOfNullableValueTest extends FixProcessorTest {
+ @override
+ FixKind get kind => DartFixKind.REPLACE_WITH_NULL_AWARE;
+
+ Future<void> test_method() async {
+ await resolveTestCode('''
+class C {
+ List<int>? values;
+
+ void m() {
+ if (values != null) {
+ print(values.toList());
+ }
+ }
+}
+''');
+ await assertHasFix('''
+class C {
+ List<int>? values;
+
+ void m() {
+ if (values != null) {
+ print(values?.toList());
+ }
+ }
+}
+''');
+ }
+}
+
+@reflectiveTest
+class UncheckedPropertyAccessOfNullableValueTest extends FixProcessorTest {
+ @override
+ FixKind get kind => DartFixKind.REPLACE_WITH_NULL_AWARE;
+
+ Future<void> test_prefixedIdentifier() async {
+ await resolveTestCode('''
+class C {
+ List<int>? values;
+
+ void m() {
+ if (values != null) {
+ print(values.length);
+ }
+ }
+}
+''');
+ await assertHasFix('''
+class C {
+ List<int>? values;
+
+ void m() {
+ if (values != null) {
+ print(values?.length);
+ }
+ }
+}
+''');
+ }
+
+ Future<void> test_propertyAccess() async {
+ await resolveTestCode('''
+class C {
+ List<int>? values;
+
+ void m() {
+ if (values != null) {
+ print((values).length);
+ }
+ }
+}
+''');
+ await assertHasFix('''
+class C {
+ List<int>? values;
+
+ void m() {
+ if (values != null) {
+ print((values)?.length);
+ }
+ }
+}
+''');
+ }
+}
diff --git a/pkg/dartdev/test/commands/flag_test.dart b/pkg/dartdev/test/commands/flag_test.dart
index bfcc02c..5d9d0ab 100644
--- a/pkg/dartdev/test/commands/flag_test.dart
+++ b/pkg/dartdev/test/commands/flag_test.dart
@@ -82,8 +82,8 @@
var result = p.runSync(['--help', '--verbose']);
expect(result.exitCode, 0);
- expect(result.stdout, isEmpty);
- expect(result.stderr,
+ expect(result.stderr, isEmpty);
+ expect(result.stdout,
contains('The following options are only used for VM development'));
});
@@ -92,8 +92,8 @@
var result = p.runSync(['--help', '-v']);
expect(result.exitCode, 0);
- expect(result.stdout, isEmpty);
- expect(result.stderr,
+ expect(result.stderr, isEmpty);
+ expect(result.stdout,
contains('The following options are only used for VM development'));
});
diff --git a/pkg/dds/lib/src/dap/adapters/dart.dart b/pkg/dds/lib/src/dap/adapters/dart.dart
index e9710c3..72f7964 100644
--- a/pkg/dds/lib/src/dap/adapters/dart.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart.dart
@@ -107,6 +107,12 @@
/// yet been made.
DartDevelopmentService? _dds;
+ /// The [InitializeRequestArguments] provided by the client in the
+ /// `initialize` request.
+ ///
+ /// `null` if the `initialize` request has not yet been made.
+ InitializeRequestArguments? _initializeArgs;
+
/// Whether to use IPv6 for DAP/Debugger services.
final bool ipv6;
@@ -135,6 +141,13 @@
...?args.additionalProjectPaths,
].whereNotNull().toList();
+ /// Whether we have already sent the [TerminatedEvent] to the client.
+ ///
+ /// This is tracked so that we don't send multiple if there are multiple
+ /// events that suggest the session ended (such as a process exiting and the
+ /// VM Service closing).
+ bool _hasSentTerminatedEvent = false;
+
DartDebugAdapter(
ByteStreamServerChannel channel, {
this.ipv6 = false,
@@ -155,6 +168,12 @@
bool get evaluateToStringInDebugViews =>
args.evaluateToStringInDebugViews ?? false;
+ /// The [InitializeRequestArguments] provided by the client in the
+ /// `initialize` request.
+ ///
+ /// `null` if the `initialize` request has not yet been made.
+ InitializeRequestArguments? get initializeArgs => _initializeArgs;
+
/// [attachRequest] is called by the client when it wants us to to attach to
/// an existing app. This will only be called once (and only one of this or
/// launchRequest will be called).
@@ -236,6 +255,7 @@
// perhaps gated on a capability/argument).
this.vmService = vmService;
+ unawaited(vmService.onDone.then((_) => _handleVmServiceClosed()));
_subscriptions.addAll([
vmService.onIsolateEvent.listen(_handleIsolateEvent),
vmService.onDebugEvent.listen(_handleDebugEvent),
@@ -464,6 +484,16 @@
}
}
+ /// Sends a [TerminatedEvent] if one has not already been sent.
+ void handleSessionTerminate() {
+ if (_hasSentTerminatedEvent) {
+ return;
+ }
+
+ _hasSentTerminatedEvent = true;
+ sendEvent(TerminatedEventBody());
+ }
+
/// [initializeRequest] is the first call from the client during
/// initialization and allows exchanging capabilities and configuration
/// between client and server.
@@ -474,9 +504,12 @@
@override
Future<void> initializeRequest(
Request request,
- InitializeRequestArguments? args,
+ InitializeRequestArguments args,
void Function(Capabilities) sendResponse,
) async {
+ // Capture args so we can read capabilities later.
+ _initializeArgs = args;
+
// TODO(dantup): Capture/honor editor-specific settings like linesStartAt1
sendResponse(Capabilities(
exceptionBreakpointFilters: [
@@ -1052,6 +1085,16 @@
}
}
+ Future<void> _handleVmServiceClosed() async {
+ // Usually termination is handled by the subclass, but we use VM Service
+ // termination as a fallback for cases where this isn't possible (such as
+ // using `runInTerminal`). However, if we end the session too quickly, the
+ // editor might drop messages from stdout that haven't yet been processed
+ // so we use a short delay before handling termination this way.
+ await Future.delayed(const Duration(seconds: 1));
+ handleSessionTerminate();
+ }
+
/// Performs some setup that is common to both [launchRequest] and
/// [attachRequest].
Future<void> _prepareForLaunchOrAttach() async {
@@ -1130,6 +1173,7 @@
/// Specialised adapters (such as Flutter) will likely extend this class with
/// their own additional fields.
class DartLaunchRequestArguments extends LaunchRequestArguments {
+ final String? name;
final String program;
final List<String>? args;
final String? cwd;
@@ -1146,6 +1190,18 @@
/// as not-debuggable.
final List<String>? additionalProjectPaths;
+ /// Which console to run the program in.
+ ///
+ /// If "terminal" or "externalTerminal" will cause the program to be run by
+ /// the client by having the server call the `runInTerminal` request on the
+ /// client (as long as the client advertises support for
+ /// `runInTerminalRequest`).
+ ///
+ /// Otherwise will run inside the debug adapter and stdout/stderr will be
+ /// routed to the client using [OutputEvent]s. This is the default (and
+ /// simplest) way, but prevents the user from being able to type into `stdin`.
+ final String? console;
+
/// Whether SDK libraries should be marked as debuggable.
///
/// Treated as `false` if null, which means "step in" will not step into SDK
@@ -1187,12 +1243,14 @@
DartLaunchRequestArguments({
Object? restart,
bool? noDebug,
+ this.name,
required this.program,
this.args,
this.cwd,
this.vmServiceInfoFile,
this.vmServicePort,
this.vmAdditionalArgs,
+ this.console,
this.enableAsserts,
this.additionalProjectPaths,
this.debugSdkLibraries,
@@ -1203,12 +1261,14 @@
}) : super(restart: restart, noDebug: noDebug);
DartLaunchRequestArguments.fromMap(Map<String, Object?> obj)
- : program = obj['program'] as String,
+ : name = obj['name'] as String?,
+ program = obj['program'] as String,
args = (obj['args'] as List?)?.cast<String>(),
cwd = obj['cwd'] as String?,
vmServiceInfoFile = obj['vmServiceInfoFile'] as String?,
vmServicePort = obj['vmServicePort'] as int?,
vmAdditionalArgs = (obj['vmAdditionalArgs'] as List?)?.cast<String>(),
+ console = obj['console'] as String?,
enableAsserts = obj['enableAsserts'] as bool?,
additionalProjectPaths =
(obj['additionalProjectPaths'] as List?)?.cast<String>(),
@@ -1225,12 +1285,14 @@
@override
Map<String, Object?> toJson() => {
...super.toJson(),
+ if (name != null) 'name': name,
'program': program,
if (args != null) 'args': args,
if (cwd != null) 'cwd': cwd,
if (vmServiceInfoFile != null) 'vmServiceInfoFile': vmServiceInfoFile,
if (vmServicePort != null) 'vmServicePort': vmServicePort,
if (vmAdditionalArgs != null) 'vmAdditionalArgs': vmAdditionalArgs,
+ if (console != null) 'console': console,
if (enableAsserts != null) 'enableAsserts': enableAsserts,
if (additionalProjectPaths != null)
'additionalProjectPaths': additionalProjectPaths,
diff --git a/pkg/dds/lib/src/dap/adapters/dart_cli.dart b/pkg/dds/lib/src/dap/adapters/dart_cli.dart
index f0fcd43..80258ca 100644
--- a/pkg/dds/lib/src/dap/adapters/dart_cli.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart_cli.dart
@@ -141,6 +141,80 @@
this.usePackageConfigFile(packageConfig);
}
+ // If the client supports runInTerminal and args.console is set to either
+ // 'terminal' or 'runInTerminal' we won't run the process ourselves, but
+ // instead call the client to run it for us (this allows it to run in a
+ // terminal where the user can interact with `stdin`).
+ final canRunInTerminal =
+ initializeArgs?.supportsRunInTerminalRequest ?? false;
+
+ // The terminal kinds used by DAP are 'integrated' and 'external'.
+ final terminalKind = canRunInTerminal
+ ? args.console == 'terminal'
+ ? 'integrated'
+ : args.console == 'externalTerminal'
+ ? 'external'
+ : null
+ : null;
+
+ // TODO(dantup): Support passing env to both of these.
+
+ if (terminalKind != null) {
+ await launchInEditorTerminal(debug, terminalKind, vmPath, processArgs);
+ } else {
+ await launchAsProcess(vmPath, processArgs);
+ }
+ }
+
+ /// Calls the client (via a `runInTerminal` request) to spawn the process so
+ /// that it can run in a local terminal that the user can interact with.
+ Future<void> launchInEditorTerminal(
+ bool debug,
+ String terminalKind,
+ String vmPath,
+ List<String> processArgs,
+ ) async {
+ logger?.call('Spawning $vmPath with $processArgs in ${args.cwd}'
+ ' via client ${terminalKind} terminal');
+
+ // runInTerminal is a DAP request that goes from server-to-client that
+ // allows the DA to ask the client editor to run the debugee for us. In this
+ // case we will have no access to the process (although we get the PID) so
+ // for debugging will rely on the process writing the service-info file that
+ // we can detect with the normal watching code.
+ final requestArgs = RunInTerminalRequestArguments(
+ args: [vmPath, ...processArgs],
+ cwd: args.cwd ?? path.dirname(args.program),
+ kind: terminalKind,
+ title: args.name ?? 'Dart',
+ );
+ try {
+ final response = await sendRequest(requestArgs);
+ final body =
+ RunInTerminalResponseBody.fromJson(response as Map<String, Object?>);
+ logger?.call(
+ 'Client spawned process'
+ ' (proc: ${body.processId}, shell: ${body.shellProcessId})',
+ );
+ } catch (e) {
+ logger?.call('Client failed to spawn process $e');
+ sendOutput('console', '\nFailed to spawn process: $e');
+ handleSessionTerminate();
+ }
+
+ // When using `runInTerminal` and `noDebug`, we will not connect to the VM
+ // Service so we will have no way of knowing when the process completes, so
+ // we just send the termination event right away.
+ if (!debug) {
+ handleSessionTerminate();
+ }
+ }
+
+ /// Launches the program as a process controlled by the debug adapter.
+ ///
+ /// Output to `stdout`/`stderr` will be sent to the editor using
+ /// [OutputEvent]s.
+ Future<void> launchAsProcess(String vmPath, List<String> processArgs) async {
logger?.call('Spawning $vmPath with $processArgs in ${args.cwd}');
final process = await Process.start(
vmPath,
@@ -204,7 +278,7 @@
// Always add a leading newline since the last written text might not have
// had one.
sendOutput('console', '\nExited$codeSuffix.');
- sendEvent(TerminatedEventBody());
+ handleSessionTerminate();
}
void _handleStderr(List<int> data) {
diff --git a/pkg/dds/lib/src/dap/base_debug_adapter.dart b/pkg/dds/lib/src/dap/base_debug_adapter.dart
index a74f1f3..0bfa738 100644
--- a/pkg/dds/lib/src/dap/base_debug_adapter.dart
+++ b/pkg/dds/lib/src/dap/base_debug_adapter.dart
@@ -30,6 +30,10 @@
int _sequence = 1;
final ByteStreamServerChannel _channel;
+ /// Completers for requests that are sent from the server back to the editor
+ /// such as `runInTerminal`.
+ final _serverToClientRequestCompleters = <int, Completer<Object?>>{};
+
BaseDebugAdapter(this._channel) {
_channel.listen(_handleIncomingMessage);
}
@@ -174,13 +178,19 @@
/// Sends a request to the client, looking up the request type based on the
/// runtimeType of [arguments].
- void sendRequest(RequestArguments arguments) {
+ Future<Object?> sendRequest(RequestArguments arguments) {
final request = Request(
seq: _sequence++,
command: commandTypes[arguments.runtimeType]!,
arguments: arguments,
);
+
+ // Store a completer to be used when a response comes back.
+ final completer = Completer<Object?>();
+ _serverToClientRequestCompleters[request.seq] = completer;
_channel.sendRequest(request);
+
+ return completer.future;
}
Future<void> setBreakpointsRequest(
@@ -318,8 +328,16 @@
}
void _handleIncomingResponse(Response response) {
- // TODO(dantup): Implement this when the server sends requests to the client
- // (for example runInTerminalRequest).
+ final completer =
+ _serverToClientRequestCompleters.remove(response.requestSeq);
+
+ if (response.success) {
+ completer?.complete(response.body);
+ } else {
+ completer?.completeError(
+ response.message ?? 'Request ${response.requestSeq} failed',
+ );
+ }
}
/// Helpers for requests that have `void` arguments. The supplied args are
diff --git a/pkg/dds/test/dap/integration/debug_test.dart b/pkg/dds/test/dap/integration/debug_test.dart
index 41863f9..2266f6f 100644
--- a/pkg/dds/test/dap/integration/debug_test.dart
+++ b/pkg/dds/test/dap/integration/debug_test.dart
@@ -2,7 +2,10 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'dart:io';
+
import 'package:dds/src/dap/protocol_generated.dart';
+import 'package:pedantic/pedantic.dart';
import 'package:test/test.dart';
import 'test_client.dart';
@@ -51,6 +54,53 @@
]);
});
+ test('runs a simple script using runInTerminal request', () async {
+ final testFile = dap.createTestFile(emptyProgram);
+
+ // Set up a handler to handle the server calling the clients runInTerminal
+ // request and capture the args.
+ RunInTerminalRequestArguments? runInTerminalArgs;
+ Process? proc;
+ var processExited = false;
+ dap.client.handleRequest(
+ 'runInTerminal',
+ (args) async {
+ runInTerminalArgs = RunInTerminalRequestArguments.fromJson(
+ args as Map<String, Object?>,
+ );
+
+ // Run the requested process (emulating what the editor would do) so
+ // that the DA will pick up the service info file, connect to the VM,
+ // resume, and then detect its termination.
+ final runArgs = runInTerminalArgs!;
+ proc = await Process.start(
+ runArgs.args.first,
+ runArgs.args.skip(1).toList(),
+ workingDirectory: runArgs.cwd,
+ );
+ unawaited(proc!.exitCode.then((_) => processExited = true));
+
+ return RunInTerminalResponseBody(processId: proc!.pid);
+ },
+ );
+
+ // Run the script until we get a TerminatedEvent.
+ await Future.wait([
+ dap.client.event('terminated'),
+ dap.client.initialize(supportsRunInTerminalRequest: true),
+ dap.client.launch(testFile.path, console: "terminal"),
+ ], eagerError: true);
+
+ expect(runInTerminalArgs, isNotNull);
+ expect(proc, isNotNull);
+ expect(
+ runInTerminalArgs!.args,
+ containsAllInOrder([Platform.resolvedExecutable, testFile.path]),
+ );
+ expect(proc!.pid, isPositive);
+ expect(processExited, isTrue);
+ });
+
test('provides a list of threads', () async {
final client = dap.client;
final testFile = dap.createTestFile(simpleBreakpointProgram);
diff --git a/pkg/dds/test/dap/integration/no_debug_test.dart b/pkg/dds/test/dap/integration/no_debug_test.dart
index bb0af1d..dec3316 100644
--- a/pkg/dds/test/dap/integration/no_debug_test.dart
+++ b/pkg/dds/test/dap/integration/no_debug_test.dart
@@ -2,9 +2,13 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'dart:io';
+
+import 'package:dds/src/dap/protocol_generated.dart';
import 'package:test/test.dart';
import 'test_client.dart';
+import 'test_scripts.dart';
import 'test_support.dart';
main() {
@@ -41,6 +45,40 @@
'Exited.',
]);
});
+
+ test('runs a simple script using the runInTerminal request', () async {
+ final testFile = dap.createTestFile(emptyProgram);
+
+ // Set up a handler to handle the server calling the clients runInTerminal
+ // request and capture the args.
+ RunInTerminalRequestArguments? runInTerminalArgs;
+ dap.client.handleRequest(
+ 'runInTerminal',
+ (args) {
+ runInTerminalArgs = RunInTerminalRequestArguments.fromJson(
+ args as Map<String, Object?>,
+ );
+ return RunInTerminalResponseBody();
+ },
+ );
+
+ // Run the script until we get a TerminatedEvent.
+ await Future.wait([
+ dap.client.event('terminated'),
+ dap.client.initialize(supportsRunInTerminalRequest: true),
+ dap.client.launch(
+ testFile.path,
+ noDebug: true,
+ console: "terminal",
+ ),
+ ], eagerError: true);
+
+ expect(runInTerminalArgs, isNotNull);
+ expect(
+ runInTerminalArgs!.args,
+ containsAllInOrder([Platform.resolvedExecutable, testFile.path]),
+ );
+ });
// These tests can be slow due to starting up the external server process.
}, timeout: Timeout.none);
}
diff --git a/pkg/dds/test/dap/integration/test_client.dart b/pkg/dds/test/dap/integration/test_client.dart
index e1a4aec..dbb9305 100644
--- a/pkg/dds/test/dap/integration/test_client.dart
+++ b/pkg/dds/test/dap/integration/test_client.dart
@@ -31,6 +31,11 @@
final _eventController = StreamController<Event>.broadcast();
int _seq = 1;
+ /// Functions provided by tests to handle requests that may come from the
+ /// server (such as `runInTerminal`).
+ final _serverRequestHandlers =
+ <String, FutureOr<Object?> Function(Object?)>{};
+
DapTestClient._(
this._channel,
this._logger, {
@@ -97,14 +102,28 @@
return _eventController.stream.where((e) => e.event == event);
}
+ /// Records a handler for when the server sends a [request] request.
+ void handleRequest(
+ String request,
+ FutureOr<Object?> Function(Object?) handler,
+ ) {
+ _serverRequestHandlers[request] = handler;
+ }
+
/// Send an initialize request to the server.
///
/// This occurs before the request to start running/debugging a script and is
/// used to exchange capabilities and send breakpoints and other settings.
- Future<Response> initialize({String exceptionPauseMode = 'None'}) async {
+ Future<Response> initialize({
+ String exceptionPauseMode = 'None',
+ bool? supportsRunInTerminalRequest,
+ }) async {
final responses = await Future.wait([
event('initialized'),
- sendRequest(InitializeRequestArguments(adapterID: 'test')),
+ sendRequest(InitializeRequestArguments(
+ adapterID: 'test',
+ supportsRunInTerminalRequest: supportsRunInTerminalRequest,
+ )),
sendRequest(
SetExceptionBreakpointsArguments(
filters: [exceptionPauseMode],
@@ -122,6 +141,7 @@
String? cwd,
bool? noDebug,
List<String>? additionalProjectPaths,
+ String? console,
bool? debugSdkLibraries,
bool? debugExternalPackageLibraries,
bool? evaluateGettersInDebugViews,
@@ -134,6 +154,7 @@
cwd: cwd,
args: args,
additionalProjectPaths: additionalProjectPaths,
+ console: console,
debugSdkLibraries: debugSdkLibraries,
debugExternalPackageLibraries: debugExternalPackageLibraries,
evaluateGettersInDebugViews: evaluateGettersInDebugViews,
@@ -181,6 +202,21 @@
return _logIfSlow('Request "$command"', completer.future);
}
+ /// Sends a response to the server.
+ ///
+ /// This is used to respond to server-to-client requests such as
+ /// `runInTerminal`.
+ void sendResponse(Request request, Object? responseBody) {
+ final response = Response(
+ success: true,
+ requestSeq: request.seq,
+ seq: _seq++,
+ command: request.command,
+ body: responseBody,
+ );
+ _channel.sendResponse(response);
+ }
+
/// Sends a stackTrace request to the server to request the call stack for a
/// given thread.
///
@@ -200,7 +236,6 @@
File? file,
Future<Response> Function()? launch,
}) {
- // Launch script and wait for termination.
return Future.wait([
initialize(),
launch?.call() ?? this.launch(file!.path),
@@ -258,7 +293,7 @@
/// Handles an incoming message from the server, completing the relevant request
/// of raising the appropriate event.
- void _handleMessage(message) {
+ Future<void> _handleMessage(message) async {
if (message is Response) {
final pendingRequest = _pendingRequests.remove(message.requestSeq);
if (pendingRequest == null) {
@@ -277,8 +312,19 @@
// tests are waiting on something that will never come, they fail at
// a useful location.
if (message.event == 'terminated') {
- _eventController.close();
+ unawaited(_eventController.close());
}
+ } else if (message is Request) {
+ // The server sent a request to the client. Call the handler and then send
+ // back its result in a response.
+ final command = message.command;
+ final args = message.arguments;
+ final handler = _serverRequestHandlers[command];
+ if (handler == null) {
+ throw 'Test did not configure a handler for servers request: $command';
+ }
+ final result = await handler(args);
+ sendResponse(message, result);
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
index ada23ac..2452d86 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constructor_tearoff_lowering.dart
@@ -253,7 +253,19 @@
FreshTypeParameters freshTypeParameters) {
int fileOffset = tearOff.fileOffset;
+ List<TypeParameter> typeParameters;
+ if (target is Constructor) {
+ typeParameters = target.enclosingClass.typeParameters;
+ } else {
+ typeParameters = target.function!.typeParameters;
+ }
+
if (!freshTypeParameters.substitution.isEmpty) {
+ if (typeArguments.length != typeParameters.length) {
+ // Error case: Use default types as type arguments.
+ typeArguments = new List<DartType>.generate(typeParameters.length,
+ (int index) => typeParameters[index].defaultType);
+ }
if (typeArguments.isNotEmpty) {
// Translate [typeArgument] into the context of the synthesized procedure.
typeArguments = new List<DartType>.generate(
@@ -262,14 +274,21 @@
.substituteType(typeArguments[index]));
}
}
-
+ Map<TypeParameter, DartType> substitutionMap;
+ if (typeParameters.length == typeArguments.length) {
+ substitutionMap = new Map<TypeParameter, DartType>.fromIterables(
+ typeParameters, typeArguments);
+ } else {
+ // Error case: Substitute type parameters with `dynamic`.
+ substitutionMap = new Map<TypeParameter, DartType>.fromIterables(
+ typeParameters,
+ new List<DartType>.generate(
+ typeParameters.length, (int index) => const DynamicType()));
+ }
Arguments arguments = _createArguments(tearOff, typeArguments, fileOffset);
_createTearOffBody(tearOff, target, arguments);
return new SynthesizedFunctionNode(
- new Map<TypeParameter, DartType>.fromIterables(
- target.enclosingClass!.typeParameters, typeArguments),
- target.function!,
- tearOff.function,
+ substitutionMap, target.function!, tearOff.function,
identicalSignatures: false);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 82dbe5c..20372bb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -3218,8 +3218,8 @@
_helper.buildDartTypeArguments(typeArguments);
}
if (isGenericTypedefTearOff) {
- if (isProperRenameForClass(
- _helper.typeEnvironment, aliasBuilder!.typedef)) {
+ if (isProperRenameForClass(_helper.typeEnvironment,
+ aliasBuilder!.typedef, aliasBuilder.library.library)) {
return tearOffExpression;
}
Procedure? tearOffLowering =
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
index c19553b..2a2bf65 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator_helper.dart
@@ -33,6 +33,7 @@
FunctionNode,
Initializer,
InterfaceType,
+ Library,
Member,
Name,
Procedure,
@@ -186,7 +187,8 @@
}
/// Checks that a generic [typedef] for a generic class.
-bool isProperRenameForClass(TypeEnvironment typeEnvironment, Typedef typedef) {
+bool isProperRenameForClass(
+ TypeEnvironment typeEnvironment, Typedef typedef, Library typedefLibrary) {
DartType? rhsType = typedef.type;
if (rhsType is! InterfaceType) {
return false;
@@ -201,7 +203,7 @@
for (int i = 0; i < fromParameters.length; ++i) {
if (typeArguments[i] !=
new TypeParameterType.withDefaultNullabilityForLibrary(
- fromParameters[i], typedef.enclosingLibrary)) {
+ fromParameters[i], typedefLibrary)) {
return false;
}
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index fab3ab7..90d2f7b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -4790,7 +4790,8 @@
checkReturn =
TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
interfaceMember.enclosingClass!,
- interfaceMember.function.returnType);
+ interfaceMember.function
+ .computeFunctionType(inferrer.library.nonNullable));
} else if (interfaceMember is Field) {
checkReturn =
TypeInferrerImpl.returnedTypeParametersOccurNonCovariantly(
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
index 71176e5..bb99b32 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_helper.dart
@@ -59,32 +59,54 @@
// For mixin application constructors, the argument count is the same, but
// for redirecting tear off lowerings, the argument count of the tear off
- // can be less than that of the redirection target.
-
- assert(_synthesized.positionalParameters.length <=
- _original.positionalParameters.length);
- for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
- cloneInitializer(_original.positionalParameters[i],
- _synthesized.positionalParameters[i]);
- }
+ // can be less than that of the redirection target or, in errors cases, be
+ // unrelated.
if (identicalSignatures) {
+ assert(_synthesized.positionalParameters.length ==
+ _original.positionalParameters.length);
+ for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
+ cloneInitializer(_original.positionalParameters[i],
+ _synthesized.positionalParameters[i]);
+ }
assert(_synthesized.namedParameters.length ==
_original.namedParameters.length);
for (int i = 0; i < _synthesized.namedParameters.length; i++) {
cloneInitializer(
_original.namedParameters[i], _synthesized.namedParameters[i]);
}
- } else if (_synthesized.namedParameters.isNotEmpty) {
- Map<String, VariableDeclaration> originalParameters = {};
- for (int i = 0; i < _original.namedParameters.length; i++) {
- originalParameters[_original.namedParameters[i].name!] =
- _original.namedParameters[i];
+ } else {
+ for (int i = 0; i < _synthesized.positionalParameters.length; i++) {
+ VariableDeclaration synthesizedParameter =
+ _synthesized.positionalParameters[i];
+ if (i < _original.positionalParameters.length) {
+ cloneInitializer(
+ _original.positionalParameters[i], synthesizedParameter);
+ } else {
+ // Error case: use `null` as initializer.
+ synthesizedParameter.initializer = new NullLiteral()
+ ..parent = synthesizedParameter;
+ }
}
- for (int i = 0; i < _synthesized.namedParameters.length; i++) {
- cloneInitializer(
- originalParameters[_synthesized.namedParameters[i].name!]!,
- _synthesized.namedParameters[i]);
+ if (_synthesized.namedParameters.isNotEmpty) {
+ Map<String, VariableDeclaration> originalParameters = {};
+ for (int i = 0; i < _original.namedParameters.length; i++) {
+ originalParameters[_original.namedParameters[i].name!] =
+ _original.namedParameters[i];
+ }
+ for (int i = 0; i < _synthesized.namedParameters.length; i++) {
+ VariableDeclaration synthesizedParameter =
+ _synthesized.namedParameters[i];
+ VariableDeclaration? originalParameter =
+ originalParameters[synthesizedParameter.name!];
+ if (originalParameter != null) {
+ cloneInitializer(originalParameter, synthesizedParameter);
+ } else {
+ // Error case: use `null` as initializer.
+ synthesizedParameter.initializer = new NullLiteral()
+ ..parent = synthesizedParameter;
+ }
+ }
}
}
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
index 67ffb10..5bdcbaa 100644
--- a/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_type_alias_builder.dart
@@ -282,7 +282,8 @@
if (declaration is ClassBuilder &&
targetType is InterfaceType &&
typedef.typeParameters.isNotEmpty &&
- !isProperRenameForClass(library.loader.typeEnvironment, typedef)) {
+ !isProperRenameForClass(
+ library.loader.typeEnvironment, typedef, library.library)) {
tearOffs = {};
_tearOffDependencies = {};
declaration
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 150c716..14694ef 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -144,6 +144,8 @@
c7a
c8a
c8b
+c8c
+c8d
ca
cafebabe
calloc
@@ -386,6 +388,7 @@
f6b
f7a
f8a
+f8b
fac
faking
falling
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart
new file mode 100644
index 0000000..78a304a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart
@@ -0,0 +1,20 @@
+// 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.
+
+// From co19/Language/Types/Type_Aliases/scope_t02
+
+class A {}
+
+class C<T> {}
+
+typedef AAlias = A;
+typedef CAlias<T> = C<T>;
+
+typedef AAlias = A; // error
+typedef AAlias = C<String>; // error
+typedef CAlias<T> = C<T>; // error
+typedef CAlias = C<String>; // error
+typedef CAlias<T1, T2> = C<T1>; // error
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.strong.expect
new file mode 100644
index 0000000..a612cdc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.strong.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Error: 'AAlias' is already declared in this scope.
+// typedef AAlias = A; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:11:9: Context: Previous declaration of 'AAlias'.
+// typedef AAlias = A;
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:15:9: Error: 'AAlias' is already declared in this scope.
+// typedef AAlias = C<String>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Context: Previous declaration of 'AAlias'.
+// typedef AAlias = A; // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias<T> = C<T>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:12:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias<T> = C<T>;
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias = C<String>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias<T> = C<T>; // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:18:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias<T1, T2> = C<T1>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias = C<String>; // error
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef AAlias = self::A;
+typedef CAlias<T extends core::Object? = dynamic> = self::C<T%>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class C<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.strong.transformed.expect
new file mode 100644
index 0000000..a612cdc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.strong.transformed.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Error: 'AAlias' is already declared in this scope.
+// typedef AAlias = A; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:11:9: Context: Previous declaration of 'AAlias'.
+// typedef AAlias = A;
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:15:9: Error: 'AAlias' is already declared in this scope.
+// typedef AAlias = C<String>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Context: Previous declaration of 'AAlias'.
+// typedef AAlias = A; // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias<T> = C<T>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:12:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias<T> = C<T>;
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias = C<String>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias<T> = C<T>; // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:18:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias<T1, T2> = C<T1>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias = C<String>; // error
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef AAlias = self::A;
+typedef CAlias<T extends core::Object? = dynamic> = self::C<T%>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class C<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.textual_outline.expect
new file mode 100644
index 0000000..43abe4c
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+class A {}
+
+class C<T> {}
+
+typedef AAlias = A;
+typedef CAlias<T> = C<T>;
+typedef AAlias = A;
+typedef AAlias = C<String>;
+typedef CAlias<T> = C<T>;
+typedef CAlias = C<String>;
+typedef CAlias<T1, T2> = C<T1>;
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..213093e
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class A {}
+
+class C<T> {}
+
+main() {}
+typedef AAlias = A;
+typedef AAlias = A;
+typedef AAlias = C<String>;
+typedef CAlias<T> = C<T>;
+typedef CAlias<T> = C<T>;
+typedef CAlias<T1, T2> = C<T1>;
+typedef CAlias = C<String>;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.weak.expect
new file mode 100644
index 0000000..a612cdc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.weak.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Error: 'AAlias' is already declared in this scope.
+// typedef AAlias = A; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:11:9: Context: Previous declaration of 'AAlias'.
+// typedef AAlias = A;
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:15:9: Error: 'AAlias' is already declared in this scope.
+// typedef AAlias = C<String>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Context: Previous declaration of 'AAlias'.
+// typedef AAlias = A; // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias<T> = C<T>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:12:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias<T> = C<T>;
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias = C<String>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias<T> = C<T>; // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:18:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias<T1, T2> = C<T1>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias = C<String>; // error
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef AAlias = self::A;
+typedef CAlias<T extends core::Object? = dynamic> = self::C<T%>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class C<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.weak.outline.expect
new file mode 100644
index 0000000..47b5558
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.weak.outline.expect
@@ -0,0 +1,58 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Error: 'AAlias' is already declared in this scope.
+// typedef AAlias = A; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:11:9: Context: Previous declaration of 'AAlias'.
+// typedef AAlias = A;
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:15:9: Error: 'AAlias' is already declared in this scope.
+// typedef AAlias = C<String>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Context: Previous declaration of 'AAlias'.
+// typedef AAlias = A; // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias<T> = C<T>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:12:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias<T> = C<T>;
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias = C<String>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias<T> = C<T>; // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:18:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias<T1, T2> = C<T1>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias = C<String>; // error
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef AAlias = self::A;
+typedef CAlias<T extends core::Object? = dynamic> = self::C<T%>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class C<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T%>
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.weak.transformed.expect
new file mode 100644
index 0000000..a612cdc
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart.weak.transformed.expect
@@ -0,0 +1,59 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Error: 'AAlias' is already declared in this scope.
+// typedef AAlias = A; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:11:9: Context: Previous declaration of 'AAlias'.
+// typedef AAlias = A;
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:15:9: Error: 'AAlias' is already declared in this scope.
+// typedef AAlias = C<String>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:14:9: Context: Previous declaration of 'AAlias'.
+// typedef AAlias = A; // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias<T> = C<T>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:12:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias<T> = C<T>;
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias = C<String>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:16:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias<T> = C<T>; // error
+// ^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:18:9: Error: 'CAlias' is already declared in this scope.
+// typedef CAlias<T1, T2> = C<T1>; // error
+// ^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/duplicate_typedefs.dart:17:9: Context: Previous declaration of 'CAlias'.
+// typedef CAlias = C<String>; // error
+// ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef AAlias = self::A;
+typedef CAlias<T extends core::Object? = dynamic> = self::C<T%>;
+class A extends core::Object {
+ synthetic constructor •() → self::A
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff() → self::A
+ return new self::A::•();
+}
+class C<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T%>
+ : super core::Object::•()
+ ;
+ static method _#new#tearOff<T extends core::Object? = dynamic>() → self::C<self::C::_#new#tearOff::T%>
+ return new self::C::•<self::C::_#new#tearOff::T%>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart
new file mode 100644
index 0000000..6b12c8a
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2011, 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.
+
+abstract class Link<T> {
+ factory Link.create1() = LinkFactory<T>.create;
+ factory Link.create2() = LinkFactory<T, T>.create;
+ factory Link.create3(int i) = LinkFactory.create;
+ factory Link.create4({int i}) = LinkFactory.create;
+}
+
+class LinkFactory {
+ factory Link.create() {
+ return null;
+ }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.strong.expect
new file mode 100644
index 0000000..165ec42
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.strong.expect
@@ -0,0 +1,53 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:11:11: Error: The name of a constructor must match the name of the enclosing class.
+// factory Link.create() {
+// ^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:10:7: Context: The name of the enclosing class is 'LinkFactory'.
+// class LinkFactory {
+// ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:27: Error: Expected 0 type arguments.
+// factory Link.create() = LinkFactory<T>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:28: Error: Expected 0 type arguments.
+// factory Link.create2() = LinkFactory<T, T>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:12:12: Error: The value 'null' can't be returned from a function with return type 'LinkFactory' because 'LinkFactory' is not nullable.
+// - 'LinkFactory' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart'.
+// return null;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Link<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Link::create, self::Link::create2]/*isLegacy*/;
+ static factory create<T extends core::Object? = dynamic>() → self::Link<self::Link::create::T%>
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:27: Error: Expected 0 type arguments.
+ factory Link.create() = LinkFactory<T>.create;
+ ^";
+ static method _#create#tearOff<T extends core::Object? = dynamic>() → self::Link<self::Link::_#create#tearOff::T%>
+ return self::LinkFactory::create();
+ static factory create2<T extends core::Object? = dynamic>() → self::Link<self::Link::create2::T%>
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:28: Error: Expected 0 type arguments.
+ factory Link.create2() = LinkFactory<T, T>.create;
+ ^";
+ static method _#create2#tearOff<T extends core::Object? = dynamic>() → self::Link<self::Link::_#create2#tearOff::T%>
+ return self::LinkFactory::create();
+}
+class LinkFactory extends core::Object {
+ static factory create() → self::LinkFactory {
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:12:12: Error: The value 'null' can't be returned from a function with return type 'LinkFactory' because 'LinkFactory' is not nullable.
+ - 'LinkFactory' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart'.
+ return null;
+ ^" in null as{TypeError,ForNonNullableByDefault} self::LinkFactory;
+ }
+ static method _#create#tearOff() → self::LinkFactory
+ return self::LinkFactory::create();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.strong.transformed.expect
new file mode 100644
index 0000000..b814114
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.strong.transformed.expect
@@ -0,0 +1,57 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:11: Error: 'Link.create' is already declared in this scope.
+// factory Link.create() = LinkFactory<T, S>.create;
+// ^^^^^^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:11: Context: Previous declaration of 'Link.create'.
+// factory Link.create() = LinkFactory<T>.create;
+// ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:11:11: Error: The name of a constructor must match the name of the enclosing class.
+// factory Link.create() {
+// ^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:10:7: Context: The name of the enclosing class is 'LinkFactory'.
+// class LinkFactory {
+// ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:42: Error: Type 'S' not found.
+// factory Link.create() = LinkFactory<T, S>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:27: Error: Expected 0 type arguments.
+// factory Link.create() = LinkFactory<T, S>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:27: Error: Expected 0 type arguments.
+// factory Link.create() = LinkFactory<T>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:12:12: Error: The value 'null' can't be returned from a function with return type 'LinkFactory' because 'LinkFactory' is not nullable.
+// - 'LinkFactory' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart'.
+// return null;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Link<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Link::create]/*isLegacy*/;
+ static factory create<T extends core::Object? = dynamic>() → self::Link<self::Link::create::T%>
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:27: Error: Expected 0 type arguments.
+ factory Link.create() = LinkFactory<T>.create;
+ ^";
+ static method _#create#tearOff<T extends core::Object? = dynamic>() → self::Link<self::Link::_#create#tearOff::T%>;
+}
+class LinkFactory extends core::Object {
+ static factory create() → self::LinkFactory {
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:12:12: Error: The value 'null' can't be returned from a function with return type 'LinkFactory' because 'LinkFactory' is not nullable.
+ - 'LinkFactory' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart'.
+ return null;
+ ^" in let Null #t1 = null in #t1 == null ?{self::LinkFactory} #t1 as{TypeError,ForNonNullableByDefault} self::LinkFactory : #t1{self::LinkFactory};
+ }
+ static method _#create#tearOff() → self::LinkFactory
+ return self::LinkFactory::create();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.textual_outline.expect
new file mode 100644
index 0000000..fcd783b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+abstract class Link<T> {
+ factory Link.create1() = LinkFactory<T>.create;
+ factory Link.create2() = LinkFactory<T, T>.create;
+ factory Link.create3(int i) = LinkFactory.create;
+ factory Link.create4({int i}) = LinkFactory.create;
+}
+
+class LinkFactory {
+ factory Link.create() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fcd783b
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+abstract class Link<T> {
+ factory Link.create1() = LinkFactory<T>.create;
+ factory Link.create2() = LinkFactory<T, T>.create;
+ factory Link.create3(int i) = LinkFactory.create;
+ factory Link.create4({int i}) = LinkFactory.create;
+}
+
+class LinkFactory {
+ factory Link.create() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.weak.expect
new file mode 100644
index 0000000..165ec42
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.weak.expect
@@ -0,0 +1,53 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:11:11: Error: The name of a constructor must match the name of the enclosing class.
+// factory Link.create() {
+// ^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:10:7: Context: The name of the enclosing class is 'LinkFactory'.
+// class LinkFactory {
+// ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:27: Error: Expected 0 type arguments.
+// factory Link.create() = LinkFactory<T>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:28: Error: Expected 0 type arguments.
+// factory Link.create2() = LinkFactory<T, T>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:12:12: Error: The value 'null' can't be returned from a function with return type 'LinkFactory' because 'LinkFactory' is not nullable.
+// - 'LinkFactory' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart'.
+// return null;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Link<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Link::create, self::Link::create2]/*isLegacy*/;
+ static factory create<T extends core::Object? = dynamic>() → self::Link<self::Link::create::T%>
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:27: Error: Expected 0 type arguments.
+ factory Link.create() = LinkFactory<T>.create;
+ ^";
+ static method _#create#tearOff<T extends core::Object? = dynamic>() → self::Link<self::Link::_#create#tearOff::T%>
+ return self::LinkFactory::create();
+ static factory create2<T extends core::Object? = dynamic>() → self::Link<self::Link::create2::T%>
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:28: Error: Expected 0 type arguments.
+ factory Link.create2() = LinkFactory<T, T>.create;
+ ^";
+ static method _#create2#tearOff<T extends core::Object? = dynamic>() → self::Link<self::Link::_#create2#tearOff::T%>
+ return self::LinkFactory::create();
+}
+class LinkFactory extends core::Object {
+ static factory create() → self::LinkFactory {
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:12:12: Error: The value 'null' can't be returned from a function with return type 'LinkFactory' because 'LinkFactory' is not nullable.
+ - 'LinkFactory' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart'.
+ return null;
+ ^" in null as{TypeError,ForNonNullableByDefault} self::LinkFactory;
+ }
+ static method _#create#tearOff() → self::LinkFactory
+ return self::LinkFactory::create();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.weak.outline.expect
new file mode 100644
index 0000000..3de7ee2
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.weak.outline.expect
@@ -0,0 +1,45 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:11:11: Error: The name of a constructor must match the name of the enclosing class.
+// factory Link.create() {
+// ^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:10:7: Context: The name of the enclosing class is 'LinkFactory'.
+// class LinkFactory {
+// ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:27: Error: Expected 0 type arguments.
+// factory Link.create() = LinkFactory<T>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:28: Error: Expected 0 type arguments.
+// factory Link.create2() = LinkFactory<T, T>.create;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Link<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Link::create, self::Link::create2]/*isLegacy*/;
+ static factory create<T extends core::Object? = dynamic>() → self::Link<self::Link::create::T%>
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:27: Error: Expected 0 type arguments.
+ factory Link.create() = LinkFactory<T>.create;
+ ^";
+ static method _#create#tearOff<T extends core::Object? = dynamic>() → self::Link<self::Link::_#create#tearOff::T%>
+ return self::LinkFactory::create();
+ static factory create2<T extends core::Object? = dynamic>() → self::Link<self::Link::create2::T%>
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:28: Error: Expected 0 type arguments.
+ factory Link.create2() = LinkFactory<T, T>.create;
+ ^";
+ static method _#create2#tearOff<T extends core::Object? = dynamic>() → self::Link<self::Link::_#create2#tearOff::T%>
+ return self::LinkFactory::create();
+}
+class LinkFactory extends core::Object {
+ static factory create() → self::LinkFactory
+ ;
+ static method _#create#tearOff() → self::LinkFactory
+ return self::LinkFactory::create();
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.weak.transformed.expect
new file mode 100644
index 0000000..e14fbed
--- /dev/null
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart.weak.transformed.expect
@@ -0,0 +1,57 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:11: Error: 'Link.create' is already declared in this scope.
+// factory Link.create() = LinkFactory<T, S>.create;
+// ^^^^^^^^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:11: Context: Previous declaration of 'Link.create'.
+// factory Link.create() = LinkFactory<T>.create;
+// ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:11:11: Error: The name of a constructor must match the name of the enclosing class.
+// factory Link.create() {
+// ^^^^
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:10:7: Context: The name of the enclosing class is 'LinkFactory'.
+// class LinkFactory {
+// ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:42: Error: Type 'S' not found.
+// factory Link.create() = LinkFactory<T, S>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:7:27: Error: Expected 0 type arguments.
+// factory Link.create() = LinkFactory<T, S>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:27: Error: Expected 0 type arguments.
+// factory Link.create() = LinkFactory<T>.create;
+// ^
+//
+// pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:12:12: Error: The value 'null' can't be returned from a function with return type 'LinkFactory' because 'LinkFactory' is not nullable.
+// - 'LinkFactory' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart'.
+// return null;
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Link<T extends core::Object? = dynamic> extends core::Object {
+ static final field dynamic _redirecting# = <dynamic>[self::Link::create]/*isLegacy*/;
+ static factory create<T extends core::Object? = dynamic>() → self::Link<self::Link::create::T%>
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:6:27: Error: Expected 0 type arguments.
+ factory Link.create() = LinkFactory<T>.create;
+ ^";
+ static method _#create#tearOff<T extends core::Object? = dynamic>() → self::Link<self::Link::_#create#tearOff::T%>;
+}
+class LinkFactory extends core::Object {
+ static factory create() → self::LinkFactory {
+ return invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart:12:12: Error: The value 'null' can't be returned from a function with return type 'LinkFactory' because 'LinkFactory' is not nullable.
+ - 'LinkFactory' is from 'pkg/front_end/testcases/constructor_tearoffs/lowering/invalid_redirect.dart'.
+ return null;
+ ^" in null;
+ }
+ static method _#create#tearOff() → self::LinkFactory
+ return self::LinkFactory::create();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart
index 765da64..bb04095 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart
@@ -85,10 +85,12 @@
class Class8a<T> implements Class8b<T> {
Class8a();
+ factory Class8a.fact() => new Class8a();
}
class Class8b<T> {
factory Class8b() = Class8a<T>;
+ factory Class8b.fact() = Class8a<T>.fact;
}
testArgs() {
@@ -174,6 +176,15 @@
expect(true, c8b is Class8a<int>);
expect(true, c8b is Class8b<int>);
expect(false, c8b is Class8b<String>);
+
+ var f8b = Class8b.fact;
+ var c8c = f8b();
+ expect(true, c8c is Class8a);
+ expect(true, c8c is Class8b);
+ var c8d = f8b<int>();
+ expect(true, c8d is Class8a<int>);
+ expect(true, c8d is Class8b<int>);
+ expect(false, c8d is Class8b<String>);
}
expect(expected, actual) {
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.expect
index 8356f0d..c74b167 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.expect
@@ -2,43 +2,43 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:101:8: Error: Too few positional arguments: 1 required, 0 given.
// f3a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:102:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f3a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:117:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f4a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:131:8: Error: Too few positional arguments: 1 required, 0 given.
// f5a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:132:8: Error: Too many positional arguments: 2 allowed, but 3 found.
// Try removing the extra positional arguments.
// f5a(42, 87, 123); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too few positional arguments: 1 required, 0 given.
// f6a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Required named parameter 'field3' must be provided.
// f6a(42); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:146:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f6a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:147:8: Error: Too few positional arguments: 1 required, 0 given.
// f6a(field1: 87, field2: 87); // error
// ^
//
@@ -148,13 +148,21 @@
;
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::fact::T%>
+ return new self::Class8a::•<self::Class8a::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#fact#tearOff::T%>
+ return self::Class8a::fact<self::Class8a::_#fact#tearOff::T%>();
}
class Class8b<T extends core::Object? = dynamic> extends core::Object {
- static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•, self::Class8b::fact]/*isLegacy*/;
static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
return new self::Class8a::•<self::Class8b::•::T%>();
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::fact::T%>
+ return self::Class8a::fact<self::Class8b::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#fact#tearOff::T%>
+ return self::Class8a::fact<self::Class8b::_#fact#tearOff::T%>();
}
static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
static method main() → dynamic {
@@ -183,10 +191,10 @@
self::Class3 c3a = f3a(42){(core::int) → self::Class3};
self::expect(42, c3a.{self::Class3::field}{core::int});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:101:8: Error: Too few positional arguments: 1 required, 0 given.
f3a(); // error
^" in f3a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:102:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f3a(42, 87); // error
^" in f3a{<inapplicable>}.(42, 87);
@@ -202,7 +210,7 @@
self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
self::expect(42, c4b.{self::Class4::field}{core::int?});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:117:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f4a(42, 87); // error
^" in f4a{<inapplicable>}.(42, 87);
@@ -217,10 +225,10 @@
self::expect(87, c5b.{self::Class5::field1}{core::int});
self::expect(42, c5b.{self::Class5::field2}{core::int?});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:131:8: Error: Too few positional arguments: 1 required, 0 given.
f5a(); // error
^" in f5a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:132:8: Error: Too many positional arguments: 2 allowed, but 3 found.
Try removing the extra positional arguments.
f5a(42, 87, 123); // error
^" in f5a{<inapplicable>}.(42, 87, 123);
@@ -234,17 +242,17 @@
self::expect(null, c6a.{self::Class6::field2}{core::int?});
self::expect(87, c6a.{self::Class6::field3}{core::int});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too few positional arguments: 1 required, 0 given.
f6a(); // error
^" in f6a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Required named parameter 'field3' must be provided.
f6a(42); // error
^" in f6a{<inapplicable>}.(42);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:146:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f6a(42, 87); // error
^" in f6a{<inapplicable>}.(42, 87);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:147:8: Error: Too few positional arguments: 1 required, 0 given.
f6a(field1: 87, field2: 87); // error
^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
};
@@ -273,12 +281,20 @@
self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8b = #C10;
+ self::Class8b<dynamic> c8c = f8b<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8c is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8c is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8d = f8b<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8d is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8d is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8d is{ForNonNullableByDefault} self::Class8b<core::String>);
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
try {
f(){() → dynamic};
}
@@ -302,5 +318,6 @@
#C7 = static-tearoff self::Class6::_#new#tearOff
#C8 = static-tearoff self::Class7b::_#new#tearOff
#C9 = static-tearoff self::Class8b::_#new#tearOff
- #C10 = false
+ #C10 = static-tearoff self::Class8b::_#fact#tearOff
+ #C11 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.transformed.expect
index 6ee2990..46d6ccc 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.strong.transformed.expect
@@ -2,43 +2,43 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:101:8: Error: Too few positional arguments: 1 required, 0 given.
// f3a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:102:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f3a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:117:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f4a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:131:8: Error: Too few positional arguments: 1 required, 0 given.
// f5a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:132:8: Error: Too many positional arguments: 2 allowed, but 3 found.
// Try removing the extra positional arguments.
// f5a(42, 87, 123); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too few positional arguments: 1 required, 0 given.
// f6a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Required named parameter 'field3' must be provided.
// f6a(42); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:146:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f6a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:147:8: Error: Too few positional arguments: 1 required, 0 given.
// f6a(field1: 87, field2: 87); // error
// ^
//
@@ -148,13 +148,21 @@
;
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::fact::T%>
+ return new self::Class8a::•<self::Class8a::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#fact#tearOff::T%>
+ return self::Class8a::fact<self::Class8a::_#fact#tearOff::T%>();
}
class Class8b<T extends core::Object? = dynamic> extends core::Object {
- static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•, self::Class8b::fact]/*isLegacy*/;
static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
return new self::Class8a::•<self::Class8b::•::T%>();
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::fact::T%>
+ return self::Class8a::fact<self::Class8b::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#fact#tearOff::T%>
+ return self::Class8a::fact<self::Class8b::_#fact#tearOff::T%>();
}
static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
static method main() → dynamic {
@@ -183,10 +191,10 @@
self::Class3 c3a = f3a(42){(core::int) → self::Class3};
self::expect(42, c3a.{self::Class3::field}{core::int});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:101:8: Error: Too few positional arguments: 1 required, 0 given.
f3a(); // error
^" in f3a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:102:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f3a(42, 87); // error
^" in f3a{<inapplicable>}.(42, 87);
@@ -202,7 +210,7 @@
self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
self::expect(42, c4b.{self::Class4::field}{core::int?});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:117:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f4a(42, 87); // error
^" in f4a{<inapplicable>}.(42, 87);
@@ -217,10 +225,10 @@
self::expect(87, c5b.{self::Class5::field1}{core::int});
self::expect(42, c5b.{self::Class5::field2}{core::int?});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:131:8: Error: Too few positional arguments: 1 required, 0 given.
f5a(); // error
^" in f5a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:132:8: Error: Too many positional arguments: 2 allowed, but 3 found.
Try removing the extra positional arguments.
f5a(42, 87, 123); // error
^" in f5a{<inapplicable>}.(42, 87, 123);
@@ -234,17 +242,17 @@
self::expect(null, c6a.{self::Class6::field2}{core::int?});
self::expect(87, c6a.{self::Class6::field3}{core::int});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too few positional arguments: 1 required, 0 given.
f6a(); // error
^" in f6a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Required named parameter 'field3' must be provided.
f6a(42); // error
^" in f6a{<inapplicable>}.(42);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:146:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f6a(42, 87); // error
^" in f6a{<inapplicable>}.(42, 87);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:147:8: Error: Too few positional arguments: 1 required, 0 given.
f6a(field1: 87, field2: 87); // error
^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
};
@@ -273,12 +281,20 @@
self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8b = #C10;
+ self::Class8b<dynamic> c8c = f8b<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8c is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8c is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8d = f8b<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8d is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8d is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8d is{ForNonNullableByDefault} self::Class8b<core::String>);
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
try {
f(){() → dynamic};
}
@@ -302,5 +318,6 @@
#C7 = static-tearoff self::Class6::_#new#tearOff
#C8 = static-tearoff self::Class7b::_#new#tearOff
#C9 = static-tearoff self::Class8b::_#new#tearOff
- #C10 = false
+ #C10 = static-tearoff self::Class8b::_#fact#tearOff
+ #C11 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline.expect
index 2fa25d6..7cf5cb1 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline.expect
@@ -51,10 +51,12 @@
class Class8a<T> implements Class8b<T> {
Class8a();
+ factory Class8a.fact() => new Class8a();
}
class Class8b<T> {
factory Class8b() = Class8a<T>;
+ factory Class8b.fact() = Class8a<T>.fact;
}
testArgs() {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
index 0500e74..e522b6c 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.textual_outline_modelled.expect
@@ -46,10 +46,12 @@
class Class8a<T> implements Class8b<T> {
Class8a();
+ factory Class8a.fact() => new Class8a();
}
class Class8b<T> {
factory Class8b() = Class8a<T>;
+ factory Class8b.fact() = Class8a<T>.fact;
}
expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.expect
index 8356f0d..c74b167 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.expect
@@ -2,43 +2,43 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:101:8: Error: Too few positional arguments: 1 required, 0 given.
// f3a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:102:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f3a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:117:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f4a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:131:8: Error: Too few positional arguments: 1 required, 0 given.
// f5a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:132:8: Error: Too many positional arguments: 2 allowed, but 3 found.
// Try removing the extra positional arguments.
// f5a(42, 87, 123); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too few positional arguments: 1 required, 0 given.
// f6a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Required named parameter 'field3' must be provided.
// f6a(42); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:146:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f6a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:147:8: Error: Too few positional arguments: 1 required, 0 given.
// f6a(field1: 87, field2: 87); // error
// ^
//
@@ -148,13 +148,21 @@
;
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::fact::T%>
+ return new self::Class8a::•<self::Class8a::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#fact#tearOff::T%>
+ return self::Class8a::fact<self::Class8a::_#fact#tearOff::T%>();
}
class Class8b<T extends core::Object? = dynamic> extends core::Object {
- static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•, self::Class8b::fact]/*isLegacy*/;
static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
return new self::Class8a::•<self::Class8b::•::T%>();
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::fact::T%>
+ return self::Class8a::fact<self::Class8b::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#fact#tearOff::T%>
+ return self::Class8a::fact<self::Class8b::_#fact#tearOff::T%>();
}
static final field core::bool inSoundMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
static method main() → dynamic {
@@ -183,10 +191,10 @@
self::Class3 c3a = f3a(42){(core::int) → self::Class3};
self::expect(42, c3a.{self::Class3::field}{core::int});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:101:8: Error: Too few positional arguments: 1 required, 0 given.
f3a(); // error
^" in f3a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:102:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f3a(42, 87); // error
^" in f3a{<inapplicable>}.(42, 87);
@@ -202,7 +210,7 @@
self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
self::expect(42, c4b.{self::Class4::field}{core::int?});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:117:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f4a(42, 87); // error
^" in f4a{<inapplicable>}.(42, 87);
@@ -217,10 +225,10 @@
self::expect(87, c5b.{self::Class5::field1}{core::int});
self::expect(42, c5b.{self::Class5::field2}{core::int?});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:131:8: Error: Too few positional arguments: 1 required, 0 given.
f5a(); // error
^" in f5a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:132:8: Error: Too many positional arguments: 2 allowed, but 3 found.
Try removing the extra positional arguments.
f5a(42, 87, 123); // error
^" in f5a{<inapplicable>}.(42, 87, 123);
@@ -234,17 +242,17 @@
self::expect(null, c6a.{self::Class6::field2}{core::int?});
self::expect(87, c6a.{self::Class6::field3}{core::int});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too few positional arguments: 1 required, 0 given.
f6a(); // error
^" in f6a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Required named parameter 'field3' must be provided.
f6a(42); // error
^" in f6a{<inapplicable>}.(42);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:146:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f6a(42, 87); // error
^" in f6a{<inapplicable>}.(42, 87);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:147:8: Error: Too few positional arguments: 1 required, 0 given.
f6a(field1: 87, field2: 87); // error
^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
};
@@ -273,12 +281,20 @@
self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8b = #C10;
+ self::Class8b<dynamic> c8c = f8b<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8c is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8c is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8d = f8b<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8d is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8d is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8d is{ForNonNullableByDefault} self::Class8b<core::String>);
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
try {
f(){() → dynamic};
}
@@ -302,5 +318,6 @@
#C7 = static-tearoff self::Class6::_#new#tearOff
#C8 = static-tearoff self::Class7b::_#new#tearOff
#C9 = static-tearoff self::Class8b::_#new#tearOff
- #C10 = false
+ #C10 = static-tearoff self::Class8b::_#fact#tearOff
+ #C11 = false
}
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.outline.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.outline.expect
index e104583..a5fb580 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.outline.expect
@@ -97,13 +97,21 @@
;
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::fact::T%>
+ ;
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#fact#tearOff::T%>
+ return self::Class8a::fact<self::Class8a::_#fact#tearOff::T%>();
}
class Class8b<T extends core::Object? = dynamic> extends core::Object {
- static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•, self::Class8b::fact]/*isLegacy*/;
static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
return new self::Class8a::•<self::Class8b::•::T%>();
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::fact::T%>
+ return self::Class8a::fact<self::Class8b::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#fact#tearOff::T%>
+ return self::Class8a::fact<self::Class8b::_#fact#tearOff::T%>();
}
static final field core::bool inSoundMode;
static method main() → dynamic
diff --git a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.transformed.expect
index 6ee2990..46d6ccc 100644
--- a/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart.weak.transformed.expect
@@ -2,43 +2,43 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:101:8: Error: Too few positional arguments: 1 required, 0 given.
// f3a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:102:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f3a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:117:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f4a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:131:8: Error: Too few positional arguments: 1 required, 0 given.
// f5a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:132:8: Error: Too many positional arguments: 2 allowed, but 3 found.
// Try removing the extra positional arguments.
// f5a(42, 87, 123); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too few positional arguments: 1 required, 0 given.
// f6a(); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Required named parameter 'field3' must be provided.
// f6a(42); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:146:8: Error: Too many positional arguments: 1 allowed, but 2 found.
// Try removing the extra positional arguments.
// f6a(42, 87); // error
// ^
//
-// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+// pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:147:8: Error: Too few positional arguments: 1 required, 0 given.
// f6a(field1: 87, field2: 87); // error
// ^
//
@@ -148,13 +148,21 @@
;
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#new#tearOff::T%>
return new self::Class8a::•<self::Class8a::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::fact::T%>
+ return new self::Class8a::•<self::Class8a::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class8a<self::Class8a::_#fact#tearOff::T%>
+ return self::Class8a::fact<self::Class8a::_#fact#tearOff::T%>();
}
class Class8b<T extends core::Object? = dynamic> extends core::Object {
- static final field dynamic _redirecting# = <dynamic>[self::Class8b::•]/*isLegacy*/;
+ static final field dynamic _redirecting# = <dynamic>[self::Class8b::•, self::Class8b::fact]/*isLegacy*/;
static factory •<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::•::T%>
return new self::Class8a::•<self::Class8b::•::T%>();
static method _#new#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#new#tearOff::T%>
return new self::Class8a::•<self::Class8b::_#new#tearOff::T%>();
+ static factory fact<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::fact::T%>
+ return self::Class8a::fact<self::Class8b::fact::T%>();
+ static method _#fact#tearOff<T extends core::Object? = dynamic>() → self::Class8b<self::Class8b::_#fact#tearOff::T%>
+ return self::Class8a::fact<self::Class8b::_#fact#tearOff::T%>();
}
static final field core::bool inSoundMode = !(core::_GrowableList::•<core::int?>(0) is{ForNonNullableByDefault} core::List<core::int>);
static method main() → dynamic {
@@ -183,10 +191,10 @@
self::Class3 c3a = f3a(42){(core::int) → self::Class3};
self::expect(42, c3a.{self::Class3::field}{core::int});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:99:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:101:8: Error: Too few positional arguments: 1 required, 0 given.
f3a(); // error
^" in f3a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:100:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:102:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f3a(42, 87); // error
^" in f3a{<inapplicable>}.(42, 87);
@@ -202,7 +210,7 @@
self::Class4 c4b = f4a(42){([core::int?]) → self::Class4};
self::expect(42, c4b.{self::Class4::field}{core::int?});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:115:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:117:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f4a(42, 87); // error
^" in f4a{<inapplicable>}.(42, 87);
@@ -217,10 +225,10 @@
self::expect(87, c5b.{self::Class5::field1}{core::int});
self::expect(42, c5b.{self::Class5::field2}{core::int?});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:129:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:131:8: Error: Too few positional arguments: 1 required, 0 given.
f5a(); // error
^" in f5a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:130:8: Error: Too many positional arguments: 2 allowed, but 3 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:132:8: Error: Too many positional arguments: 2 allowed, but 3 found.
Try removing the extra positional arguments.
f5a(42, 87, 123); // error
^" in f5a{<inapplicable>}.(42, 87, 123);
@@ -234,17 +242,17 @@
self::expect(null, c6a.{self::Class6::field2}{core::int?});
self::expect(87, c6a.{self::Class6::field3}{core::int});
() → Null {
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:142:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too few positional arguments: 1 required, 0 given.
f6a(); // error
^" in f6a{<inapplicable>}.();
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:143:8: Error: Required named parameter 'field3' must be provided.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Required named parameter 'field3' must be provided.
f6a(42); // error
^" in f6a{<inapplicable>}.(42);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:144:8: Error: Too many positional arguments: 1 allowed, but 2 found.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:146:8: Error: Too many positional arguments: 1 allowed, but 2 found.
Try removing the extra positional arguments.
f6a(42, 87); // error
^" in f6a{<inapplicable>}.(42, 87);
- invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:145:8: Error: Too few positional arguments: 1 required, 0 given.
+ invalid-expression "pkg/front_end/testcases/constructor_tearoffs/lowering/redirecting_factory_tear_off.dart:147:8: Error: Too few positional arguments: 1 required, 0 given.
f6a(field1: 87, field2: 87); // error
^" in f6a{<inapplicable>}.(field1: 87, field2: 87);
};
@@ -273,12 +281,20 @@
self::expect(true, c8b is{ForNonNullableByDefault} self::Class8a<core::int>);
self::expect(true, c8b is{ForNonNullableByDefault} self::Class8b<core::int>);
self::expect(false, c8b is{ForNonNullableByDefault} self::Class8b<core::String>);
+ <T extends core::Object? = dynamic>() → self::Class8b<T%> f8b = #C10;
+ self::Class8b<dynamic> c8c = f8b<dynamic>(){() → self::Class8b<dynamic>};
+ self::expect(true, c8c is{ForNonNullableByDefault} self::Class8a<dynamic>);
+ self::expect(true, c8c is{ForNonNullableByDefault} self::Class8b<dynamic>);
+ self::Class8b<core::int> c8d = f8b<core::int>(){() → self::Class8b<core::int>};
+ self::expect(true, c8d is{ForNonNullableByDefault} self::Class8a<core::int>);
+ self::expect(true, c8d is{ForNonNullableByDefault} self::Class8b<core::int>);
+ self::expect(false, c8d is{ForNonNullableByDefault} self::Class8b<core::String>);
}
static method expect(dynamic expected, dynamic actual) → dynamic {
if(!(expected =={core::Object::==}{(core::Object) → core::bool} actual))
throw "Expected ${expected}, actual ${actual}";
}
-static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C10}) → dynamic {
+static method throws(() → dynamic f, {core::bool inSoundModeOnly = #C11}) → dynamic {
try {
f(){() → dynamic};
}
@@ -302,5 +318,6 @@
#C7 = static-tearoff self::Class6::_#new#tearOff
#C8 = static-tearoff self::Class7b::_#new#tearOff
#C9 = static-tearoff self::Class8b::_#new#tearOff
- #C10 = false
+ #C10 = static-tearoff self::Class8b::_#fact#tearOff
+ #C11 = false
}
diff --git a/pkg/front_end/testcases/general/bug33298.dart.weak.expect b/pkg/front_end/testcases/general/bug33298.dart.weak.expect
index 397db9f..bac28d2 100644
--- a/pkg/front_end/testcases/general/bug33298.dart.weak.expect
+++ b/pkg/front_end/testcases/general/bug33298.dart.weak.expect
@@ -65,7 +65,7 @@
core::List<core::String*>* list1 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(a.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
core::List<core::String*>* list2 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(let final self::A* #t1 = a in #t1 == null ?{(core::String*) →* core::String*} null : #t1.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
self::B<core::String*>* b = new self::B::•<core::String*>();
- core::List<core::String*>* list3 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(b.{self::B::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
+ core::List<core::String*>* list3 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(b.{self::B::call}{(core::String*) →* core::String*} as{TypeError,CovarianceCheck} (core::String*) →* core::String*){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
core::List<core::String*>* list4 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(let final self::B<core::String*>* #t2 = b in #t2 == null ?{(core::String*) →* core::String*} null : #t2.{self::B::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
self::C* c = new self::C::•();
core::List<core::String*>* list5 = <core::String*>["a", "b", "c"].{core::Iterable::map}<core::String*>(c.{self::C::call}{<T extends core::Object* = dynamic>(T*) →* T*}<core::String*>){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
diff --git a/pkg/front_end/testcases/general/bug33298.dart.weak.transformed.expect b/pkg/front_end/testcases/general/bug33298.dart.weak.transformed.expect
index 8f7030e..2fa1eb2 100644
--- a/pkg/front_end/testcases/general/bug33298.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33298.dart.weak.transformed.expect
@@ -65,7 +65,7 @@
core::List<core::String*>* list1 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(a.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
core::List<core::String*>* list2 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(let final self::A* #t1 = a in #t1 == null ?{(core::String*) →* core::String*} null : #t1.{self::A::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
self::B<core::String*>* b = new self::B::•<core::String*>();
- core::List<core::String*>* list3 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(b.{self::B::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
+ core::List<core::String*>* list3 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(b.{self::B::call}{(core::String*) →* core::String*} as{TypeError,CovarianceCheck} (core::String*) →* core::String*){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
core::List<core::String*>* list4 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(let final self::B<core::String*>* #t2 = b in #t2 == null ?{(core::String*) →* core::String*} null : #t2.{self::B::call}{(core::String*) →* core::String*}){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
self::C* c = new self::C::•();
core::List<core::String*>* list5 = core::_GrowableList::_literal3<core::String*>("a", "b", "c").{core::Iterable::map}<core::String*>(c.{self::C::call}{<T extends core::Object* = dynamic>(T*) →* T*}<core::String*>){((core::String*) →* core::String*) →* core::Iterable<core::String*>*}.{core::Iterable::toList}(){({growable: core::bool*}) →* core::List<core::String*>*};
diff --git a/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart
new file mode 100644
index 0000000..8d1ca89
--- /dev/null
+++ b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A<X extends num> {
+ void f<Y extends X>(Y y) {}
+}
+
+expectThrows(void Function() f) {
+ try {
+ f();
+ } catch (e) {
+ return;
+ }
+ throw "Expected an exception to be thrown!";
+}
+
+main() {
+ A<num> a = new A<int>();
+ expectThrows(() {
+ void Function<Y extends num>(Y) f = a.f;
+ });
+}
diff --git a/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.textual_outline.expect b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.textual_outline.expect
new file mode 100644
index 0000000..cf5cf7d
--- /dev/null
+++ b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+class A<X extends num> {
+ void f<Y extends X>(Y y) {}
+}
+
+expectThrows(void Function() f) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cf5cf7d
--- /dev/null
+++ b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+class A<X extends num> {
+ void f<Y extends X>(Y y) {}
+}
+
+expectThrows(void Function() f) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.weak.expect b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.weak.expect
new file mode 100644
index 0000000..b5abc6f
--- /dev/null
+++ b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.weak.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::num> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X>
+ : super core::Object::•()
+ ;
+ method f<generic-covariant-impl Y extends self::A::X>(self::A::f::Y y) → void {}
+}
+static method expectThrows(() → void f) → dynamic {
+ try {
+ f(){() → void};
+ }
+ on core::Object catch(final core::Object e) {
+ return;
+ }
+ throw "Expected an exception to be thrown!";
+}
+static method main() → dynamic {
+ self::A<core::num> a = new self::A::•<core::int>();
+ self::expectThrows(() → void {
+ <Y extends core::num>(Y) → void f = a.{self::A::f}{<generic-covariant-impl Y extends core::num>(Y) → void} as{TypeError,CovarianceCheck,ForNonNullableByDefault} <generic-covariant-impl Y extends core::num>(Y) → void;
+ });
+}
diff --git a/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.weak.outline.expect b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.weak.outline.expect
new file mode 100644
index 0000000..18ac6fe
--- /dev/null
+++ b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.weak.outline.expect
@@ -0,0 +1,14 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::num> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X>
+ ;
+ method f<generic-covariant-impl Y extends self::A::X>(self::A::f::Y y) → void
+ ;
+}
+static method expectThrows(() → void f) → dynamic
+ ;
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.weak.transformed.expect b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.weak.transformed.expect
new file mode 100644
index 0000000..b5abc6f
--- /dev/null
+++ b/pkg/front_end/testcases/general/method_tearoff_covariant_generic_type_check.dart.weak.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A<X extends core::num> extends core::Object {
+ synthetic constructor •() → self::A<self::A::X>
+ : super core::Object::•()
+ ;
+ method f<generic-covariant-impl Y extends self::A::X>(self::A::f::Y y) → void {}
+}
+static method expectThrows(() → void f) → dynamic {
+ try {
+ f(){() → void};
+ }
+ on core::Object catch(final core::Object e) {
+ return;
+ }
+ throw "Expected an exception to be thrown!";
+}
+static method main() → dynamic {
+ self::A<core::num> a = new self::A::•<core::int>();
+ self::expectThrows(() → void {
+ <Y extends core::num>(Y) → void f = a.{self::A::f}{<generic-covariant-impl Y extends core::num>(Y) → void} as{TypeError,CovarianceCheck,ForNonNullableByDefault} <generic-covariant-impl Y extends core::num>(Y) → void;
+ });
+}
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index a59e9fd..428a77b 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -3,6 +3,7 @@
# BSD-style license that can be found in the LICENSE.md file.
const_functions/const_functions_const_factory: VerificationError
+constructor_tearoffs/lowering/invalid_redirect: VerificationError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized
extension_types/simple_getter_resolution: ExpectationFileMismatchSerialized
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart
index 0d4dd96..11693a1 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart
+++ b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart
@@ -15,7 +15,7 @@
}
F<num> g1(C<num> c) {
- return c.f1;
+ return c. /*@ checkReturn=(num*) ->* void*/ f1;
}
void g2(C<int> c, Object x) {
@@ -24,7 +24,7 @@
}
G<List<num>, num> g3(C<num> c) {
- return c.f2;
+ return c. /*@ checkReturn=(List<num*>*) ->* num**/ f2;
}
void test() {
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.weak.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.weak.expect
index 05ac14b..5d38dc5 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.weak.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.weak.expect
@@ -23,14 +23,14 @@
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
static method g1(self::C<core::num*>* c) → (core::num*) →* void {
- return c.{self::C::f1}{(core::num*) →* void};
+ return c.{self::C::f1}{(core::num*) →* void} as{TypeError,CovarianceCheck} (core::num*) →* void;
}
static method g2(self::C<core::int*>* c, core::Object* x) → void {
(core::Object*) →* void f = self::g1(c) as (core::Object*) →* void;
f(x){(core::Object*) →* void};
}
static method g3(self::C<core::num*>* c) → (core::List<core::num*>*) →* core::num* {
- return c.{self::C::f2}{(core::List<core::num*>*) →* core::num*};
+ return c.{self::C::f2}{(core::List<core::num*>*) →* core::num*} as{TypeError,CovarianceCheck} (core::List<core::num*>*) →* core::num*;
}
static method test() → void {
(core::num*) →* void x = self::g1(new self::C::•<core::int*>());
diff --git a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.weak.transformed.expect b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.weak.transformed.expect
index 05ac14b..5d38dc5 100644
--- a/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/covariant_generic_parameter_tear_off.dart.weak.transformed.expect
@@ -23,14 +23,14 @@
abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
}
static method g1(self::C<core::num*>* c) → (core::num*) →* void {
- return c.{self::C::f1}{(core::num*) →* void};
+ return c.{self::C::f1}{(core::num*) →* void} as{TypeError,CovarianceCheck} (core::num*) →* void;
}
static method g2(self::C<core::int*>* c, core::Object* x) → void {
(core::Object*) →* void f = self::g1(c) as (core::Object*) →* void;
f(x){(core::Object*) →* void};
}
static method g3(self::C<core::num*>* c) → (core::List<core::num*>*) →* core::num* {
- return c.{self::C::f2}{(core::List<core::num*>*) →* core::num*};
+ return c.{self::C::f2}{(core::List<core::num*>*) →* core::num*} as{TypeError,CovarianceCheck} (core::List<core::num*>*) →* core::num*;
}
static method test() → void {
(core::num*) →* void x = self::g1(new self::C::•<core::int*>());
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 65e627a..5cd897f 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -10,6 +10,7 @@
constructor_tearoffs/call_instantiation: TypeCheckError
constructor_tearoffs/const_tear_off: RuntimeError
+constructor_tearoffs/lowering/invalid_redirect: VerificationError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 9803b19..dc2b0b7 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -8,6 +8,7 @@
constructor_tearoffs/call_instantiation: TypeCheckError
constructor_tearoffs/const_tear_off: RuntimeError
+constructor_tearoffs/lowering/invalid_redirect: VerificationError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index 60c84f44..0281cb6 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -13,6 +13,7 @@
constructor_tearoffs/call_instantiation: TypeCheckError
constructor_tearoffs/const_tear_off: RuntimeError
+constructor_tearoffs/lowering/invalid_redirect: VerificationError
extension_types/extension_on_nullable: ExpectationFileMismatchSerialized # Expected.
extension_types/issue45775: ExpectationFileMismatchSerialized # Expected.
extension_types/simple: ExpectationFileMismatchSerialized # Expected.
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index e598523..9581107 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -109,7 +109,9 @@
/// mapping to be used for replacing other types to use the new type parameters.
FreshTypeParameters getFreshTypeParameters(List<TypeParameter> typeParameters) {
List<TypeParameter> freshParameters = new List<TypeParameter>.generate(
- typeParameters.length, (i) => new TypeParameter(typeParameters[i].name),
+ typeParameters.length,
+ (i) => new TypeParameter(typeParameters[i].name)
+ ..flags = typeParameters[i].flags,
growable: true);
List<DartType> freshTypeArguments =
new List<DartType>.generate(typeParameters.length, (int i) {
@@ -138,8 +140,10 @@
class FreshTypeParameters {
/// The newly created type parameters.
final List<TypeParameter> freshTypeParameters;
+
/// List of [TypeParameterType]s for [TypeParameter].
final List<DartType> freshTypeArguments;
+
/// Substitution from the original type parameters to [freshTypeArguments].
final Substitution substitution;
@@ -389,7 +393,7 @@
}
TypeParameter freshTypeParameter(TypeParameter node) {
- TypeParameter fresh = new TypeParameter(node.name);
+ TypeParameter fresh = new TypeParameter(node.name)..flags = node.flags;
TypeParameterType typeParameterType = substitution[node] =
new TypeParameterType.forAlphaRenaming(node, fresh);
fresh.bound = visit(node.bound);
diff --git a/pkg/vm_service/test/cpu_samples_stream_test.dart b/pkg/vm_service/test/cpu_samples_stream_test.dart
index d6846ef..8ef6ff6 100644
--- a/pkg/vm_service/test/cpu_samples_stream_test.dart
+++ b/pkg/vm_service/test/cpu_samples_stream_test.dart
@@ -4,7 +4,8 @@
import 'dart:async';
-import 'package:test/test.dart';
+// TODO(bkonyi): re-import after sample streaming is fixed.
+// import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'common/service_test_common.dart';
@@ -31,7 +32,9 @@
var tests = <IsolateTest>[
(VmService service, IsolateRef isolate) async {
- final completer = Completer<void>();
+ // TODO(bkonyi): re-enable after sample streaming is fixed.
+ // See https://github.com/dart-lang/sdk/issues/46825
+ /*final completer = Completer<void>();
int count = 0;
int previousOrigin = 0;
sub = service.onProfilerEvent.listen((event) async {
@@ -56,6 +59,7 @@
await completer.future;
await service.streamCancel(EventStreams.kProfiler);
+ */
},
];
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 108fc91..a3fb4e1 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -127,19 +127,19 @@
hot_reload_rollback_test_mode_callback);
void Options::PrintVersion() {
- Syslog::PrintErr("Dart SDK version: %s\n", Dart_VersionString());
+ Syslog::Print("Dart SDK version: %s\n", Dart_VersionString());
}
// clang-format off
void Options::PrintUsage() {
- Syslog::PrintErr(
+ Syslog::Print(
"Usage: dart [<vm-flags>] <dart-script-file> [<script-arguments>]\n"
"\n"
"Executes the Dart script <dart-script-file> with "
"the given list of <script-arguments>.\n"
"\n");
if (!Options::verbose_option()) {
- Syslog::PrintErr(
+ Syslog::Print(
"Common VM flags:\n"
"--enable-asserts\n"
" Enable assert statements.\n"
@@ -176,7 +176,7 @@
"--version\n"
" Print the SDK version.\n");
} else {
- Syslog::PrintErr(
+ Syslog::Print(
"Supported options:\n"
"--enable-asserts\n"
" Enable assert statements.\n"
diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc
index 26ff8e2..49dadd2 100644
--- a/runtime/vm/flags.cc
+++ b/runtime/vm/flags.cc
@@ -113,30 +113,29 @@
}
switch (type_) {
case kBoolean: {
- OS::PrintErr("%s: %s (%s)\n", name_,
- *this->bool_ptr_ ? "true" : "false", comment_);
+ OS::Print("%s: %s (%s)\n", name_, *this->bool_ptr_ ? "true" : "false",
+ comment_);
break;
}
case kInteger: {
- OS::PrintErr("%s: %d (%s)\n", name_, *this->int_ptr_, comment_);
+ OS::Print("%s: %d (%s)\n", name_, *this->int_ptr_, comment_);
break;
}
case kUint64: {
- OS::PrintErr("%s: %" Pu64 " (%s)\n", name_, *this->uint64_ptr_,
- comment_);
+ OS::Print("%s: %" Pu64 " (%s)\n", name_, *this->uint64_ptr_, comment_);
break;
}
case kString: {
if (*this->charp_ptr_ != NULL) {
- OS::PrintErr("%s: '%s' (%s)\n", name_, *this->charp_ptr_, comment_);
+ OS::Print("%s: '%s' (%s)\n", name_, *this->charp_ptr_, comment_);
} else {
- OS::PrintErr("%s: (null) (%s)\n", name_, comment_);
+ OS::Print("%s: (null) (%s)\n", name_, comment_);
}
break;
}
case kOptionHandler:
case kFlagHandler: {
- OS::PrintErr("%s: (%s)\n", name_, comment_);
+ OS::Print("%s: (%s)\n", name_, comment_);
break;
}
default:
@@ -499,7 +498,7 @@
}
void Flags::PrintFlags() {
- OS::PrintErr("Flag settings:\n");
+ OS::Print("Flag settings:\n");
for (intptr_t i = 0; i < num_flags_; ++i) {
flags_[i]->Print();
}
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 2436574..fae638f 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -306,6 +306,12 @@
Sample* sample = nullptr;
if (block != nullptr) {
sample = block->ReserveSample();
+ if (sample != nullptr && block->is_full()) {
+ // TODO(bkonyi): remove once streaming is re-enabled.
+ // https://github.com/dart-lang/sdk/issues/46825
+ block->evictable_ = true;
+ FreeBlock(block);
+ }
}
if (sample != nullptr) {
return sample;
@@ -330,8 +336,11 @@
isolate->set_current_sample_block(next);
}
next->set_is_allocation_block(allocation_sample);
+
can_process_block_.store(true);
- isolate->mutator_thread()->ScheduleInterrupts(Thread::kVMInterrupt);
+ // TODO(bkonyi): re-enable after block streaming is fixed.
+ // See https://github.com/dart-lang/sdk/issues/46825
+ // isolate->mutator_thread()->ScheduleInterrupts(Thread::kVMInterrupt);
return ReserveSampleImpl(isolate, allocation_sample);
}
diff --git a/tests/language/closure/identity_equality_tearoff_test.dart b/tests/language/closure/identity_equality_tearoff_test.dart
index cdf7585..549f2d4 100644
--- a/tests/language/closure/identity_equality_tearoff_test.dart
+++ b/tests/language/closure/identity_equality_tearoff_test.dart
@@ -40,6 +40,26 @@
void instanceMethod() {}
X? genericInstanceMethod<X>() => null;
+
+ // Enable a mixed-in method in `M` that has a superinvocation.
+ int mixedInSuperMethod() => 0;
+}
+
+mixin M on A {
+ void mixedInMethod() {}
+ int mixedInSuperMethod() => super.mixedInSuperMethod() + 1;
+}
+
+class AM extends A with M {
+ int Function() get tearoffSuperMethod => super.mixedInSuperMethod;
+}
+
+class AMM extends AM with M {
+ // Tear off the second copy of M.mixedInSuperMethod
+ // (`tearoffSuperMethod` still tears off the first copy).
+ int Function() get tearoffSuperMethodSecond => super.mixedInSuperMethod;
+ // In this case, `super.` should not make a difference.
+ int Function() get tearoffSuperMethodSecondNoSuper => mixedInSuperMethod;
}
const cTopLevelFunction = topLevelFunction;
@@ -104,6 +124,7 @@
checkIdentical(cIntStaticMethod1, vIntStaticMethod2);
checkIdentical(vIntTopLevelFunction1, vIntTopLevelFunction2);
checkIdentical(vIntStaticMethod1, vIntStaticMethod2);
+ checkEqual(vIntInstanceMethod1, vIntInstanceMethod2);
const CheckIdentical(topLevelFunction, topLevelFunction);
const CheckIdentical(A.staticMethod, A.staticMethod);
@@ -268,6 +289,56 @@
const CheckNotIdentical(cIntTopLevelFunction1, cStringTopLevelFunction);
const CheckNotIdentical(cIntStaticMethod1, cStringStaticMethod);
+ {
+ var am = AM();
+ void Function() vMixedInMethod1 = am.mixedInMethod;
+ void Function() vMixedInMethod2 = am.mixedInMethod;
+ int Function() vMixedInSuperMethod1 = am.mixedInSuperMethod;
+ int Function() vMixedInSuperMethod2 = am.mixedInSuperMethod;
+
+ checkEqual(am.mixedInMethod, am.mixedInMethod);
+ checkEqual(vMixedInMethod1, vMixedInMethod2);
+ checkEqual(am.mixedInSuperMethod, am.mixedInSuperMethod);
+ checkEqual(vMixedInSuperMethod1, vMixedInSuperMethod2);
+ }
+ {
+ var amm = AMM();
+ void Function() vMixedInMethod1 = amm.mixedInMethod;
+ void Function() vMixedInMethod2 = amm.mixedInMethod;
+ int Function() vMixedInSuperMethod1 = amm.tearoffSuperMethod;
+ int Function() vMixedInSuperMethod2 = amm.tearoffSuperMethod;
+ int Function() vMixedInSuperMethodSecond1 = amm.tearoffSuperMethodSecond;
+ int Function() vMixedInSuperMethodSecond2 = amm.tearoffSuperMethodSecond;
+ int Function() vMixedInSuperMethodSecondNoSuper1 =
+ amm.tearoffSuperMethodSecondNoSuper;
+ int Function() vMixedInSuperMethodSecondNoSuper2 =
+ amm.tearoffSuperMethodSecondNoSuper;
+
+ checkEqual(amm.mixedInMethod, amm.mixedInMethod);
+ checkEqual(vMixedInMethod1, vMixedInMethod2);
+
+ checkEqual(amm.tearoffSuperMethod, amm.tearoffSuperMethod);
+ checkEqual(vMixedInSuperMethod1, vMixedInSuperMethod2);
+ checkEqual(amm.tearoffSuperMethodSecond, amm.tearoffSuperMethodSecond);
+ checkEqual(vMixedInSuperMethodSecond1, vMixedInSuperMethodSecond2);
+ checkUnequal(amm.tearoffSuperMethod, amm.tearoffSuperMethodSecond);
+ checkUnequal(vMixedInSuperMethod1, vMixedInSuperMethodSecond2);
+ checkUnequal(amm.tearoffSuperMethodSecond, amm.tearoffSuperMethod);
+ checkUnequal(vMixedInSuperMethodSecond1, vMixedInSuperMethod2);
+
+ checkEqual(amm.tearoffSuperMethodSecondNoSuper,
+ amm.tearoffSuperMethodSecondNoSuper);
+ checkEqual(
+ vMixedInSuperMethodSecondNoSuper1, vMixedInSuperMethodSecondNoSuper2);
+ checkUnequal(amm.tearoffSuperMethod, amm.tearoffSuperMethodSecondNoSuper);
+ checkUnequal(vMixedInSuperMethod1, vMixedInSuperMethodSecondNoSuper2);
+ checkUnequal(amm.tearoffSuperMethodSecondNoSuper, amm.tearoffSuperMethod);
+ checkUnequal(vMixedInSuperMethodSecondNoSuper1, vMixedInSuperMethod2);
+
+ checkEqual(
+ amm.tearoffSuperMethodSecond, amm.tearoffSuperMethodSecondNoSuper);
+ }
+
<X>() {
X? Function() vXTopLevelFunction1 = genericTopLevelFunction;
X? Function() vXStaticMethod1 = A.genericStaticMethod;
@@ -276,6 +347,14 @@
X? Function() vXInstanceMethod1 = a.genericInstanceMethod;
X? Function() vXInstanceMethod2 = a.genericInstanceMethod;
+ checkEqual(vXTopLevelFunction1, vXTopLevelFunction2);
+ checkEqual(vXStaticMethod1, vXStaticMethod2);
+ checkEqual(vXInstanceMethod1, vXInstanceMethod2);
+
+ checkEqual(vXTopLevelFunction1, vIntTopLevelFunction1);
+ checkEqual(vXStaticMethod1, vIntStaticMethod1);
+ checkEqual(vXInstanceMethod1, vIntInstanceMethod2);
+
checkUnequal(vXTopLevelFunction1, vXStaticMethod1);
checkUnequal(vXTopLevelFunction1, vXInstanceMethod1);
checkUnequal(vXStaticMethod1, vXInstanceMethod1);
diff --git a/tests/standalone/io/directory_fuzz_test.dart b/tests/standalone/io/directory_fuzz_test.dart
index 358bcff..0e3cbe6 100644
--- a/tests/standalone/io/directory_fuzz_test.dart
+++ b/tests/standalone/io/directory_fuzz_test.dart
@@ -12,68 +12,75 @@
import "package:expect/expect.dart";
import 'fuzz_support.dart';
+import 'file_write_only_test.dart' show withTempDir, withTempDirSync;
fuzzSyncMethods() {
- typeMapping.forEach((k, v) {
- doItSync(() {
- Directory.systemTemp.createTempSync(v as String?).deleteSync();
- });
- Directory? directory;
- doItSync(() => directory = new Directory(v as String));
- if (directory == null) return;
- final d = directory!;
- doItSync(d.existsSync);
- doItSync(d.createSync);
- doItSync(d.deleteSync);
- doItSync(d.listSync);
- doItSync(() {
- d.createTempSync('tempdir').deleteSync();
- });
- doItSync(() {
- // Let's be a little careful. If the directory exists we don't
- // want to delete it and all its contents.
- if (!d.existsSync()) d.deleteSync(recursive: true);
- });
- typeMapping.forEach((k2, v2) {
- doItSync(() => d.renameSync(v2 as String));
- doItSync(() => d.listSync(recursive: v2 as bool));
+ withTempDirSync('dart_directory_fuzz', (temp) {
+ typeMapping.forEach((k, v) {
+ doItSync(() {
+ Directory.systemTemp.createTempSync("${temp.path}/${v as String}")
+ .deleteSync();
+ });
+ Directory? directory;
+ doItSync(() => directory = new Directory("${temp.path}/${v as String}"));
+ if (directory == null) return;
+ final d = directory!;
+ doItSync(d.existsSync);
+ doItSync(d.createSync);
+ doItSync(d.deleteSync);
+ doItSync(d.listSync);
+ doItSync(() {
+ d.createTempSync('tempdir').deleteSync();
+ });
+ doItSync(() {
+ // Let's be a little careful. If the directory exists we don't
+ // want to delete it and all its contents.
+ if (!d.existsSync()) d.deleteSync(recursive: true);
+ });
+ typeMapping.forEach((k2, v2) {
+ doItSync(() => d.renameSync(v2 as String));
+ doItSync(() => d.listSync(recursive: v2 as bool));
+ });
});
});
}
-fuzzAsyncMethods() {
+fuzzAsyncMethods() async {
asyncStart();
- var futures = <Future>[];
- typeMapping.forEach((k, v) {
- futures.add(doItAsync(() {
- Directory.systemTemp.createTempSync(v as String?).deleteSync();
- }));
- if (v is! String) {
- return;
- }
- var d = new Directory(v);
- futures.add(doItAsync(d.exists));
- futures.add(doItAsync(d.create));
- futures.add(doItAsync(d.delete));
- futures.add(doItAsync(() {
- return d.createTemp('tempdir').then((temp) {
- return temp.delete();
- });
- }));
- futures.add(doItAsync(() {
- return d.exists().then((res) {
- if (!res) return d.delete(recursive: true);
- return new Future.value(true);
- });
- }));
- typeMapping.forEach((k2, v2) {
- futures.add(doItAsync(() => d.rename(v2 as String)));
+ await withTempDir('dart_directory_fuzz', (temp) async {
+ final futures = <Future>[];
+ typeMapping.forEach((k, v) {
futures.add(doItAsync(() {
- d.list(recursive: v2 as bool).listen((_) {}, onError: (e) => null);
+ Directory.systemTemp.createTempSync("${temp.path}/${v as String}")
+ .deleteSync();
}));
+ if (v is! String) {
+ return;
+ }
+ var d = new Directory("${temp.path}/$v");
+ futures.add(doItAsync(d.exists));
+ futures.add(doItAsync(d.create));
+ futures.add(doItAsync(d.delete));
+ futures.add(doItAsync(() {
+ return d.createTemp('tempdir').then((temp) {
+ return temp.delete();
+ });
+ }));
+ futures.add(doItAsync(() {
+ return d.exists().then((res) {
+ if (!res) return d.delete(recursive: true);
+ return new Future.value(true);
+ });
+ }));
+ typeMapping.forEach((k2, v2) {
+ futures.add(doItAsync(() => d.rename(v2 as String)));
+ futures.add(doItAsync(() {
+ d.list(recursive: v2 as bool).listen((_) {}, onError: (e) => null);
+ }));
+ });
});
+ await Future.wait(futures).then((_) => asyncEnd());
});
- Future.wait(futures).then((_) => asyncEnd());
}
main() {
diff --git a/tests/standalone_2/io/directory_fuzz_test.dart b/tests/standalone_2/io/directory_fuzz_test.dart
index 227058d6..c3a8e6a 100644
--- a/tests/standalone_2/io/directory_fuzz_test.dart
+++ b/tests/standalone_2/io/directory_fuzz_test.dart
@@ -14,69 +14,74 @@
import "package:expect/expect.dart";
import 'fuzz_support.dart';
+import 'file_write_only_test.dart' show withTempDir, withTempDirSync;
fuzzSyncMethods() {
- typeMapping.forEach((k, v) {
- doItSync(() {
- Directory.systemTemp.createTempSync(v).deleteSync();
- });
- Directory d;
- doItSync(() => d = new Directory(v));
- if (d == null) return;
- doItSync(d.existsSync);
- doItSync(d.createSync);
- doItSync(d.deleteSync);
- doItSync(d.listSync);
- doItSync(() {
- d.createTempSync('tempdir').deleteSync();
- });
- doItSync(() {
- // Let's be a little careful. If the directory exists we don't
- // want to delete it and all its contents.
- if (!d.existsSync()) d.deleteSync(recursive: true);
- });
- typeMapping.forEach((k2, v2) {
- doItSync(() => d.renameSync(v2));
- doItSync(() => d.listSync(recursive: v2));
+ withTempDirSync('dart_directory_fuzz', (temp) {
+ typeMapping.forEach((k, v) {
+ doItSync(() {
+ Directory.systemTemp.createTempSync("${temp.path}/$v").deleteSync();
+ });
+ Directory d;
+ doItSync(() => d = new Directory("${temp.path}/$v"));
+ if (d == null) return;
+ doItSync(d.existsSync);
+ doItSync(d.createSync);
+ doItSync(d.deleteSync);
+ doItSync(d.listSync);
+ doItSync(() {
+ d.createTempSync('tempdir').deleteSync();
+ });
+ doItSync(() {
+ // Let's be a little careful. If the directory exists we don't
+ // want to delete it and all its contents.
+ if (!d.existsSync()) d.deleteSync(recursive: true);
+ });
+ typeMapping.forEach((k2, v2) {
+ doItSync(() => d.renameSync(v2));
+ doItSync(() => d.listSync(recursive: v2));
+ });
});
});
}
-fuzzAsyncMethods() {
+fuzzAsyncMethods() async {
asyncStart();
- var futures = <Future>[];
- typeMapping.forEach((k, v) {
- futures.add(doItAsync(() {
- Directory.systemTemp.createTempSync(v).deleteSync();
- }));
- if (v is! String) {
- Expect.throws(() => new Directory(v),
- (e) => e is ArgumentError || e is TypeError);
- return;
- }
- var d = new Directory(v);
- futures.add(doItAsync(d.exists));
- futures.add(doItAsync(d.create));
- futures.add(doItAsync(d.delete));
- futures.add(doItAsync(() {
- return d.createTemp('tempdir').then((temp) {
- return temp.delete();
- });
- }));
- futures.add(doItAsync(() {
- return d.exists().then((res) {
- if (!res) return d.delete(recursive: true);
- return new Future.value(true);
- });
- }));
- typeMapping.forEach((k2, v2) {
- futures.add(doItAsync(() => d.rename(v2)));
+ await withTempDir('dart_directory_fuzz', (temp) async {
+ final futures = <Future>[];
+ typeMapping.forEach((k, v) {
futures.add(doItAsync(() {
- d.list(recursive: v2).listen((_) {}, onError: (e) => null);
+ Directory.systemTemp.createTempSync("${temp.path}/$v").deleteSync();
}));
+ if (v is! String) {
+ Expect.throws(() => new Directory(v),
+ (e) => e is ArgumentError || e is TypeError);
+ return;
+ }
+ var d = new Directory("${temp.path}/$v");
+ futures.add(doItAsync(d.exists));
+ futures.add(doItAsync(d.create));
+ futures.add(doItAsync(d.delete));
+ futures.add(doItAsync(() {
+ return d.createTemp('tempdir').then((temp) {
+ return temp.delete();
+ });
+ }));
+ futures.add(doItAsync(() {
+ return d.exists().then((res) {
+ if (!res) return d.delete(recursive: true);
+ return new Future.value(true);
+ });
+ }));
+ typeMapping.forEach((k2, v2) {
+ futures.add(doItAsync(() => d.rename(v2)));
+ futures.add(doItAsync(() {
+ d.list(recursive: v2).listen((_) {}, onError: (e) => null);
+ }));
+ });
});
+ await Future.wait(futures).then((_) => asyncEnd());
});
- Future.wait(futures).then((_) => asyncEnd());
}
main() {
diff --git a/tools/VERSION b/tools/VERSION
index c9d32db..5b78760 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 386
+PRERELEASE 387
PRERELEASE_PATCH 0
\ No newline at end of file