Version 3.6.0-106.0.dev Merge 7eef09cd6eccd60d66fc75a0435d2979385614d0 into dev
diff --git a/pkg/dart2wasm/lib/async.dart b/pkg/dart2wasm/lib/async.dart index deeca32..55e4020 100644 --- a/pkg/dart2wasm/lib/async.dart +++ b/pkg/dart2wasm/lib/async.dart
@@ -10,19 +10,78 @@ import 'code_generator.dart'; import 'state_machine.dart'; -class AsyncCodeGenerator extends StateMachineCodeGenerator { +class AsyncCodeGenerator extends StateMachineEntryCodeGenerator { AsyncCodeGenerator(super.translator, super.function, super.reference); late final ClassInfo asyncSuspendStateInfo = translator.classInfo[translator.asyncSuspendStateClass]!; - // Note: These locals are only available in "inner" functions. - w.Local get _suspendStateLocal => function.locals[0]; - w.Local get _awaitValueLocal => function.locals[1]; - w.Local get _pendingExceptionLocal => function.locals[2]; - w.Local get _pendingStackTraceLocal => function.locals[3]; + @override + void generateOuter( + FunctionNode functionNode, Context? context, Source functionSource) { + final resumeFun = _defineInnerBodyFunction(functionNode); - w.FunctionBuilder _defineBodyFunction(FunctionNode functionNode) => + // Outer (wrapper) function creates async state, calls the inner function + // (which runs until first suspension point, i.e. `await`), and returns the + // completer's future. + + // (1) Create async state. + + final asyncStateLocal = + b.addLocal(w.RefType(asyncSuspendStateInfo.struct, nullable: false)); + + // AsyncResumeFun _resume + b.global_get(translator.makeFunctionRef(resumeFun)); + + // WasmStructRef? _context + if (context != null) { + assert(!context.isEmpty); + b.local_get(context.currentLocal); + } else { + b.ref_null(w.HeapType.struct); + } + + // _AsyncCompleter _completer + types.makeType(this, functionNode.emittedValueType!); + call(translator.makeAsyncCompleter.reference); + + // Allocate `_AsyncSuspendState` + call(translator.newAsyncSuspendState.reference); + b.local_set(asyncStateLocal); + + // (2) Call inner function. + // + // Note: the inner function does not throw, so we don't need a `try` block + // here. + + b.local_get(asyncStateLocal); + b.ref_null(translator.topInfo.struct); // await value + b.ref_null(translator.topInfo.struct); // error value + b.ref_null(translator.stackTraceInfo.repr.struct); // stack trace + b.call(resumeFun); + b.drop(); // drop null + + // (3) Return the completer's future. + + b.local_get(asyncStateLocal); + final completerFutureGetterType = translator + .signatureForDirectCall(translator.completerFuture.getterReference); + b.struct_get( + asyncSuspendStateInfo.struct, FieldIndex.asyncSuspendStateCompleter); + translator.convertType( + b, + asyncSuspendStateInfo.struct.fields[5].type.unpacked, + completerFutureGetterType.inputs[0]); + call(translator.completerFuture.getterReference); + b.return_(); + b.end(); + + AsyncStateMachineCodeGenerator(translator, resumeFun, reference, + functionNode, functionSource, closures) + .generate(); + } + + w.FunctionBuilder _defineInnerBodyFunction(FunctionNode functionNode) => m.functions.define( m.types.defineFunction([ asyncSuspendStateInfo.nonNullableType, // _AsyncSuspendState @@ -37,6 +96,24 @@ translator.topInfo.nullableType ]), "${function.functionName} inner"); +} + +class AsyncStateMachineCodeGenerator extends StateMachineCodeGenerator { + AsyncStateMachineCodeGenerator( + super.translator, + super.function, + super.reference, + super.functionNode, + super.functionSource, + super.closures); + + late final ClassInfo asyncSuspendStateInfo = + translator.classInfo[translator.asyncSuspendStateClass]!; + + w.Local get _suspendStateLocal => function.locals[0]; + w.Local get _awaitValueLocal => function.locals[1]; + w.Local get _pendingExceptionLocal => function.locals[2]; + w.Local get _pendingStackTraceLocal => function.locals[3]; @override void setSuspendStateCurrentException(void Function() emitValue) { @@ -94,86 +171,9 @@ } @override - void generateFunctions(FunctionNode functionNode, Context? context) { - final resumeFun = _defineBodyFunction(functionNode); - - _generateOuter(functionNode, context, resumeFun); - - // Forget about the outer function locals containing the type arguments, - // so accesses to the type arguments in the inner function will fetch them - // from the context. - typeLocals.clear(); - - _generateInner(functionNode, context, resumeFun); - } - - void _generateOuter( - FunctionNode functionNode, Context? context, w.BaseFunction resumeFun) { - // Outer (wrapper) function creates async state, calls the inner function - // (which runs until first suspension point, i.e. `await`), and returns the - // completer's future. - - // (1) Create async state. - - final asyncStateLocal = - b.addLocal(w.RefType(asyncSuspendStateInfo.struct, nullable: false)); - - // AsyncResumeFun _resume - b.global_get(translator.makeFunctionRef(resumeFun)); - - // WasmStructRef? _context - if (context != null) { - assert(!context.isEmpty); - b.local_get(context.currentLocal); - } else { - b.ref_null(w.HeapType.struct); - } - - // _AsyncCompleter _completer - types.makeType(this, functionNode.emittedValueType!); - call(translator.makeAsyncCompleter.reference); - - // Allocate `_AsyncSuspendState` - call(translator.newAsyncSuspendState.reference); - b.local_set(asyncStateLocal); - - // (2) Call inner function. - // - // Note: the inner function does not throw, so we don't need a `try` block - // here. - - b.local_get(asyncStateLocal); - b.ref_null(translator.topInfo.struct); // await value - b.ref_null(translator.topInfo.struct); // error value - b.ref_null(translator.stackTraceInfo.repr.struct); // stack trace - b.call(resumeFun); - b.drop(); // drop null - - // (3) Return the completer's future. - - b.local_get(asyncStateLocal); - final completerFutureGetterType = translator - .signatureForDirectCall(translator.completerFuture.getterReference); - b.struct_get( - asyncSuspendStateInfo.struct, FieldIndex.asyncSuspendStateCompleter); - translator.convertType( - b, - asyncSuspendStateInfo.struct.fields[5].type.unpacked, - completerFutureGetterType.inputs[0]); - call(translator.completerFuture.getterReference); - b.end(); - } - - void _generateInner(FunctionNode functionNode, Context? context, - w.FunctionBuilder resumeFun) { + void generateInner(FunctionNode functionNode, Context? context) { // void Function(_AsyncSuspendState, Object?, Object?, StackTrace?) - // Set the current Wasm function for the code generator to the inner - // function of the `async`, which is to contain the body. - function = resumeFun; - b = resumeFun.body; - functionType = resumeFun.type; - // Set up locals for contexts and `this`. thisLocal = null; Context? localContext = context;
diff --git a/pkg/dart2wasm/lib/code_generator.dart b/pkg/dart2wasm/lib/code_generator.dart index 6d96df2..aa3bf24 100644 --- a/pkg/dart2wasm/lib/code_generator.dart +++ b/pkg/dart2wasm/lib/code_generator.dart
@@ -40,8 +40,8 @@ with ExpressionVisitor1DefaultMixin<w.ValueType, w.ValueType> implements InitializerVisitor<void>, StatementVisitor<void> { final Translator translator; - w.FunctionType functionType; - w.InstructionsBuilder b; + final w.FunctionType functionType; + final w.InstructionsBuilder b; final Reference reference; late final List<w.Local> paramLocals; final w.Label? returnLabel;
diff --git a/pkg/dart2wasm/lib/state_machine.dart b/pkg/dart2wasm/lib/state_machine.dart index cc0d292e..84b43af 100644 --- a/pkg/dart2wasm/lib/state_machine.dart +++ b/pkg/dart2wasm/lib/state_machine.dart
@@ -563,18 +563,74 @@ CatchVariables._(this.exception, this.stackTrace); } +abstract class StateMachineEntryCodeGenerator extends CodeGenerator { + final w.FunctionBuilder function; + + StateMachineEntryCodeGenerator( + Translator translator, this.function, Reference reference) + : super(translator, function.type, function.body, reference, + paramLocals: function.locals.toList()); + + @override + void generate() { + final source = member.enclosingComponent!.uriToSource[member.fileUri]!; + closures = Closures(translator, member); + setSourceMapSource(source); + setSourceMapFileOffset(member.fileOffset); + setupParametersAndContexts(member.reference); + _generateBody(member.function!, source); + } + + @override + void generateLambda(Lambda lambda, Closures closures) { + final source = lambda.functionNodeSource; + this.closures = closures; + setSourceMapSource(source); + setSourceMapFileOffset(lambda.functionNode.fileOffset); + setupLambdaParametersAndContexts(lambda); + _generateBody(lambda.functionNode, source); + } + + void _generateBody(FunctionNode functionNode, Source functionSource) { + Context? context = closures.contexts[functionNode]; + if (context != null && context.isEmpty) context = context.parent; + + generateOuter(functionNode, context, functionSource); + } + + /// Generate the outer function. + /// + /// - Outer function: the `async` or `sync*` function. + /// + /// In case of `async` this function should return a future. + /// + /// In case of `sync*`, this function should return an iterable. + /// + void generateOuter( + FunctionNode functionNode, Context? context, Source functionSource); +} + /// A [CodeGenerator] that compiles the function to a state machine based on /// the suspension points in the function (`await` expressions and `yield` /// statements). /// /// This is used to compile `async` and `sync*` functions. abstract class StateMachineCodeGenerator extends CodeGenerator { - w.FunctionBuilder function; + final w.FunctionBuilder function; + final FunctionNode functionNode; + final Source functionSource; StateMachineCodeGenerator( - Translator translator, this.function, Reference reference) + Translator translator, + this.function, + Reference reference, + this.functionNode, + this.functionSource, + Closures closures) : super(translator, function.type, function.body, reference, - paramLocals: function.locals.toList()); + paramLocals: function.locals.toList()) { + this.closures = closures; + } /// Targets of the CFG, indexed by target index. late final List<StateTarget> targets; @@ -612,23 +668,9 @@ @override void generate() { - final source = member.enclosingComponent!.uriToSource[member.fileUri]!; - setSourceMapSource(source); - setSourceMapFileOffset(member.fileOffset); - closures = Closures(translator, member); - setupParametersAndContexts(member.reference); - _generateBodies(member.function!); - } + setSourceMapSource(functionSource); + setSourceMapFileOffset(functionNode.fileOffset); - @override - void generateLambda(Lambda lambda, Closures closures) { - this.closures = closures; - setSourceMapSource(lambda.functionNodeSource); - setupLambdaParametersAndContexts(lambda); - _generateBodies(lambda.functionNode); - } - - void _generateBodies(FunctionNode functionNode) { // Number and categorize CFG targets. targets = _YieldFinder(translator.options.enableAsserts).find(functionNode); for (final target in targets) { @@ -647,7 +689,14 @@ Context? context = closures.contexts[functionNode]; if (context != null && context.isEmpty) context = context.parent; - generateFunctions(functionNode, context); + generateInner(functionNode, context); + } + + @override + void generateLambda(Lambda lambda, Closures closures) { + // This is only invoked for the actual async/async*/sync* code generator and + // not for the (inner) state machine code generator. + throw UnsupportedError('This should not be reachable'); } /// Store the exception value emitted by [emitValue] in suspension state. @@ -679,23 +728,10 @@ /// iteration by returning `false`. void emitReturn(void Function() emitValue); - /// Generate the outer and inner functions. - /// - /// - Outer function: the `async` or `sync*` function. - /// - /// In case of `async` this function should return a future. - /// - /// In case of `sync*`, this function should return an iterable. - /// - /// Note that when generating the outer function we can't use the - /// [StateMachineCodeGenerator] methods, as the outer functions are not the - /// state machines used to implement suspension and resumption. + /// Generate the inner functions. /// /// - Inner function: the function that will be called for resumption. - /// - /// [StateMachineCodeGenerator] methods (visitors etc.) are for generating - /// this function. - void generateFunctions(FunctionNode functionNode, Context? context); + void generateInner(FunctionNode functionNode, Context? context); void emitTargetLabel(StateTarget target) { currentTargetIndex++;
diff --git a/pkg/dart2wasm/lib/sync_star.dart b/pkg/dart2wasm/lib/sync_star.dart index 38ff310..9718a48 100644 --- a/pkg/dart2wasm/lib/sync_star.dart +++ b/pkg/dart2wasm/lib/sync_star.dart
@@ -10,6 +10,57 @@ import 'code_generator.dart'; import 'state_machine.dart'; +class SyncStarCodeGenerator extends StateMachineEntryCodeGenerator { + SyncStarCodeGenerator(super.translator, super.function, super.reference); + + late final ClassInfo suspendStateInfo = + translator.classInfo[translator.suspendStateClass]!; + + late final ClassInfo syncStarIterableInfo = + translator.classInfo[translator.syncStarIterableClass]!; + + @override + void generateOuter( + FunctionNode functionNode, Context? context, Source functionSource) { + final resumeFun = _defineInnerBodyFunction(functionNode); + + // Instantiate a [_SyncStarIterable] containing the context and resume + // function for this `sync*` function. + DartType elementType = functionNode.emittedValueType!; + translator.functions.recordClassAllocation(syncStarIterableInfo.classId); + b.i32_const(syncStarIterableInfo.classId); + b.i32_const(initialIdentityHash); + types.makeType(this, elementType); + if (context != null) { + assert(!context.isEmpty); + b.local_get(context.currentLocal); + } else { + b.ref_null(w.HeapType.struct); + } + b.global_get(translator.makeFunctionRef(resumeFun)); + b.struct_new(syncStarIterableInfo.struct); + b.return_(); + b.end(); + + SyncStarStateMachineCodeGenerator(translator, resumeFun, reference, + functionNode, functionSource, closures) + .generate(); + } + + w.FunctionBuilder _defineInnerBodyFunction(FunctionNode functionNode) => + m.functions.define( + m.types.defineFunction([ + suspendStateInfo.nonNullableType, // _SuspendState + translator.topInfo.nullableType, // Object?, error value + translator.stackTraceInfo.repr + .nullableType // StackTrace?, error stack trace + ], const [ + // bool for whether the generator has more to do + w.NumType.i32 + ]), + "${function.functionName} inner"); +} + /// A specialized code generator for generating code for `sync*` functions. /// /// This will create an "outer" function which is a small function that just @@ -25,8 +76,14 @@ /// Local state is preserved via the closure contexts, which will implicitly /// capture all local variables in a `sync*` function even if they are not /// captured by any lambdas. -class SyncStarCodeGenerator extends StateMachineCodeGenerator { - SyncStarCodeGenerator(super.translator, super.function, super.reference); +class SyncStarStateMachineCodeGenerator extends StateMachineCodeGenerator { + SyncStarStateMachineCodeGenerator( + super.translator, + super.function, + super.reference, + super.functionNode, + super.functionSource, + super.closures); late final ClassInfo suspendStateInfo = translator.classInfo[translator.suspendStateClass]!; @@ -42,19 +99,6 @@ w.Local get _pendingExceptionLocal => function.locals[1]; w.Local get _pendingStackTraceLocal => function.locals[2]; - w.FunctionBuilder _defineBodyFunction(FunctionNode functionNode) => - m.functions.define( - m.types.defineFunction([ - suspendStateInfo.nonNullableType, // _SuspendState - translator.topInfo.nullableType, // Object?, error value - translator.stackTraceInfo.repr - .nullableType // StackTrace?, error stack trace - ], const [ - // bool for whether the generator has more to do - w.NumType.i32 - ]), - "${function.functionName} inner"); - @override void setSuspendStateCurrentException(void Function() emitValue) { b.local_get(_suspendStateLocal); @@ -104,47 +148,7 @@ } @override - void generateFunctions(FunctionNode functionNode, Context? context) { - final resumeFun = _defineBodyFunction(functionNode); - - _generateOuter(functionNode, context, resumeFun); - - // Forget about the outer function locals containing the type arguments, - // so accesses to the type arguments in the inner function will fetch them - // from the context. - typeLocals.clear(); - - _generateInner(functionNode, context, resumeFun); - } - - void _generateOuter( - FunctionNode functionNode, Context? context, w.BaseFunction resumeFun) { - // Instantiate a [_SyncStarIterable] containing the context and resume - // function for this `sync*` function. - DartType elementType = functionNode.emittedValueType!; - translator.functions.recordClassAllocation(syncStarIterableInfo.classId); - b.i32_const(syncStarIterableInfo.classId); - b.i32_const(initialIdentityHash); - types.makeType(this, elementType); - if (context != null) { - assert(!context.isEmpty); - b.local_get(context.currentLocal); - } else { - b.ref_null(w.HeapType.struct); - } - b.global_get(translator.makeFunctionRef(resumeFun)); - b.struct_new(syncStarIterableInfo.struct); - b.end(); - } - - void _generateInner(FunctionNode functionNode, Context? context, - w.FunctionBuilder resumeFun) { - // Set the current Wasm function for the code generator to the inner - // function of the `sync*`, which is to contain the body. - function = resumeFun; - b = resumeFun.body; - functionType = resumeFun.type; - + void generateInner(FunctionNode functionNode, Context? context) { // Set up locals for contexts and `this`. thisLocal = null; Context? localContext = context; @@ -197,6 +201,7 @@ emitReturn(() {}); b.end(); // masterLoop + b.return_(); b.end(); // inner function }
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md index 499429d..cd0d884 100644 --- a/pkg/dds/CHANGELOG.md +++ b/pkg/dds/CHANGELOG.md
@@ -1,6 +1,7 @@ # 4.2.5 - Fixed DevTools URI not including a trailing '/' before the query parameters, which could prevent DevTools from loading properly. - [DAP] Fixed an issue where format specifiers and `format.hex` in `variablesRequest` would not apply to values from lists such as `Uint8List` from `dart:typed_data`. +- Added `package:dds/dds_launcher.dart`, a library which can be used to launch DDS instances using `dart development-service`. # 4.2.4+1 - Added missing type to `Event` in `postEvent`.
diff --git a/pkg/dds/lib/dds.dart b/pkg/dds/lib/dds.dart index 8b22313..7a6ed14 100644 --- a/pkg/dds/lib/dds.dart +++ b/pkg/dds/lib/dds.dart
@@ -169,6 +169,8 @@ static const String protocolVersion = '2.0'; } +/// Thrown by DDS during initialization failures, unexpected connection issues, +/// and when attempting to spawn DDS when an existing DDS instance exists. class DartDevelopmentServiceException implements Exception { /// Set when `DartDeveloperService.startDartDevelopmentService` is called and /// the target VM service already has a Dart Developer Service instance @@ -182,6 +184,33 @@ /// Set when a connection error has occurred after startup. static const int connectionError = 3; + factory DartDevelopmentServiceException.fromJson(Map<String, Object?> json) { + if (json + case { + 'error_code': final int errorCode, + 'message': final String message, + 'uri': final String? uri + }) { + return switch (errorCode) { + existingDdsInstanceError => + DartDevelopmentServiceException.existingDdsInstance( + message, + ddsUri: Uri.parse(uri!), + ), + failedToStartError => DartDevelopmentServiceException.failedToStart(), + connectionError => + DartDevelopmentServiceException.connectionIssue(message), + _ => throw StateError( + 'Invalid DartDevelopmentServiceException error_code: $errorCode', + ), + }; + } + throw StateError('Invalid DartDevelopmentServiceException JSON: $json'); + } + + /// Thrown when `DartDeveloperService.startDartDevelopmentService` is called + /// and the target VM service already has a Dart Developer Service instance + /// connected. factory DartDevelopmentServiceException.existingDdsInstance( String message, { Uri? ddsUri, @@ -192,11 +221,14 @@ ); } + /// Thrown when the connection to the remote VM service terminates unexpectedly + /// during Dart Development Service startup. factory DartDevelopmentServiceException.failedToStart() { return DartDevelopmentServiceException._( failedToStartError, 'Failed to start Dart Development Service'); } + /// Thrown when a connection error has occurred after startup. factory DartDevelopmentServiceException.connectionIssue(String message) { return DartDevelopmentServiceException._(connectionError, message); } @@ -215,6 +247,7 @@ final String message; } +/// Thrown when attempting to start a new DDS instance when one already exists. class ExistingDartDevelopmentServiceException extends DartDevelopmentServiceException { ExistingDartDevelopmentServiceException._(
diff --git a/pkg/dds/lib/dds_launcher.dart b/pkg/dds/lib/dds_launcher.dart new file mode 100644 index 0000000..2e8ad80 --- /dev/null +++ b/pkg/dds/lib/dds_launcher.dart
@@ -0,0 +1,198 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'dds.dart' hide DartDevelopmentService; +import 'src/arg_parser.dart'; +import 'src/dds_impl.dart'; + +/// Spawns a Dart Development Service instance which will communicate with a +/// VM service. Requires the target VM service to have no other connected +/// clients. +/// +/// [remoteVmServiceUri] is the address of the VM service that this +/// development service will communicate with. +/// +/// If provided, [serviceUri] will determine the address and port of the +/// spawned Dart Development Service. +/// +/// [enableAuthCodes] controls whether or not an authentication code must +/// be provided by clients when communicating with this instance of +/// DDS. Authentication codes take the form of a base64 +/// encoded string provided as the first element of the DDS path and is meant +/// to make it more difficult for unintended clients to connect to this +/// service. Authentication codes are enabled by default. +/// +/// If [serveDevTools] is enabled, DDS will serve a DevTools instance and act +/// as a DevTools Server. If not specified, [devToolsServerAddress] is ignored. +/// +/// If provided, DDS will redirect DevTools requests to an existing DevTools +/// server hosted at [devToolsServerAddress]. Ignored if [serveDevTools] is not +/// true. +/// +/// If [enableServicePortFallback] is enabled, DDS will attempt to bind to any +/// available port if the specified port is unavailable. +/// +/// If set, the set of [cachedUserTags] will be used to determine which CPU +/// samples should be cached by DDS. +/// +/// If provided, [dartExecutable] is the path to the 'dart' executable that +/// should be used to spawn the DDS instance. By default, `Platform.executable` +/// is used. +class DartDevelopmentServiceLauncher { + static Future<DartDevelopmentServiceLauncher> start({ + required Uri remoteVmServiceUri, + Uri? serviceUri, + bool enableAuthCodes = true, + bool serveDevTools = false, + Uri? devToolsServerAddress, + bool enableServicePortFallback = false, + List<String> cachedUserTags = const <String>[], + String? dartExecutable, + }) async { + final process = await Process.start( + dartExecutable ?? Platform.executable, + <String>[ + 'development-service', + '--${DartDevelopmentServiceOptions.vmServiceUriOption}=$remoteVmServiceUri', + if (serviceUri != null) ...<String>[ + '--${DartDevelopmentServiceOptions.bindAddressOption}=${serviceUri.host}', + '--${DartDevelopmentServiceOptions.bindPortOption}=${serviceUri.port}', + ], + if (!enableAuthCodes) + '--${DartDevelopmentServiceOptions.disableServiceAuthCodesFlag}', + if (serveDevTools) + '--${DartDevelopmentServiceOptions.serveDevToolsFlag}', + if (devToolsServerAddress != null) + '--${DartDevelopmentServiceOptions.devToolsServerAddressOption}=$devToolsServerAddress', + if (enableServicePortFallback) + '--${DartDevelopmentServiceOptions.enableServicePortFallbackFlag}', + for (final String tag in cachedUserTags) + '--${DartDevelopmentServiceOptions.cachedUserTagsOption}=$tag', + ], + ); + final completer = Completer<DartDevelopmentServiceLauncher>(); + late StreamSubscription<Object?> stderrSub; + stderrSub = process.stderr + .transform(utf8.decoder) + .transform(json.decoder) + .listen((Object? result) { + if (result + case { + 'state': 'started', + 'ddsUri': final String ddsUriStr, + }) { + final ddsUri = Uri.parse(ddsUriStr); + final devToolsUriStr = result['devToolsUri'] as String?; + final devToolsUri = + devToolsUriStr == null ? null : Uri.parse(devToolsUriStr); + final dtdUriStr = + (result['dtd'] as Map<String, Object?>?)?['uri'] as String?; + final dtdUri = dtdUriStr == null ? null : Uri.parse(dtdUriStr); + + completer.complete( + DartDevelopmentServiceLauncher._( + process: process, + uri: ddsUri, + devToolsUri: devToolsUri, + dtdUri: dtdUri, + ), + ); + } else if (result + case { + 'state': 'error', + 'error': final String error, + }) { + final Map<String, Object?>? exceptionDetails = + result['ddsExceptionDetails'] as Map<String, Object?>?; + completer.completeError( + exceptionDetails != null + ? DartDevelopmentServiceException.fromJson(exceptionDetails) + : StateError(error), + ); + } else { + throw StateError('Unexpected result from DDS: $result'); + } + stderrSub.cancel(); + }); + return completer.future; + } + + DartDevelopmentServiceLauncher._({ + required Process process, + required this.uri, + required this.devToolsUri, + required this.dtdUri, + }) : _ddsInstance = process; + + final Process _ddsInstance; + + /// The [Uri] VM service clients can use to communicate with this + /// DDS instance via HTTP. + final Uri uri; + + /// The HTTP [Uri] of the hosted DevTools instance. + /// + /// Returns `null` if DevTools is not running. + final Uri? devToolsUri; + + /// The [Uri] of the Dart Tooling Daemon instance that is hosted by DevTools. + /// + /// This will be null if DTD was not started by the DevTools server. For + /// example, it may have been started by an IDE. + final Uri? dtdUri; + + /// The [Uri] VM service clients can use to communicate with this + /// DDS instance via server-sent events (SSE). + Uri get sseUri => _toSse(uri)!; + + /// The [Uri] VM service clients can use to communicate with this + /// DDS instance via a [WebSocket]. + Uri get wsUri => _toWebSocket(uri)!; + + List<String> _cleanupPathSegments(Uri uri) { + final pathSegments = <String>[]; + if (uri.pathSegments.isNotEmpty) { + pathSegments.addAll( + uri.pathSegments.where( + // Strip out the empty string that appears at the end of path segments. + // Empty string elements will result in an extra '/' being added to the + // URI. + (s) => s.isNotEmpty, + ), + ); + } + return pathSegments; + } + + Uri? _toWebSocket(Uri? uri) { + if (uri == null) { + return null; + } + final pathSegments = _cleanupPathSegments(uri); + pathSegments.add('ws'); + return uri.replace(scheme: 'ws', pathSegments: pathSegments); + } + + Uri? _toSse(Uri? uri) { + if (uri == null) { + return null; + } + final pathSegments = _cleanupPathSegments(uri); + pathSegments.add(DartDevelopmentServiceImpl.kSseHandlerPath); + return uri.replace(scheme: 'sse', pathSegments: pathSegments); + } + + /// Completes when the DDS instance has shutdown. + Future<void> get done => _ddsInstance.exitCode; + + /// Shutdown the DDS instance. + Future<void> shutdown() { + _ddsInstance.kill(); + return _ddsInstance.exitCode; + } +}
diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart index 376855e..69dcfd4 100644 --- a/pkg/dds/lib/src/dds_impl.dart +++ b/pkg/dds/lib/src/dds_impl.dart
@@ -347,8 +347,8 @@ Handler _sseHandler() { final handler = SseHandler( authCodesEnabled - ? Uri.parse('/$authCode/$_kSseHandlerPath') - : Uri.parse('/$_kSseHandlerPath'), + ? Uri.parse('/$authCode/$kSseHandlerPath') + : Uri.parse('/$kSseHandlerPath'), keepAlive: sseKeepAlive, ); @@ -441,7 +441,7 @@ return null; } final pathSegments = _cleanupPathSegments(uri); - pathSegments.add(_kSseHandlerPath); + pathSegments.add(kSseHandlerPath); return uri.replace(scheme: 'sse', pathSegments: pathSegments); } @@ -552,7 +552,7 @@ StreamManager get streamManager => _streamManager; late StreamManager _streamManager; - static const _kSseHandlerPath = '\$debugHandler'; + static const kSseHandlerPath = '\$debugHandler'; late json_rpc.Peer vmServiceClient; late WebSocketChannel _vmServiceSocket;
diff --git a/pkg/dds/test/launcher_smoke_test.dart b/pkg/dds/test/launcher_smoke_test.dart new file mode 100644 index 0000000..80fc54b --- /dev/null +++ b/pkg/dds/test/launcher_smoke_test.dart
@@ -0,0 +1,72 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:convert'; +import 'dart:io'; + +import 'package:dds/dds_launcher.dart'; +import 'package:test/test.dart'; +import 'package:vm_service/vm_service_io.dart'; + +import 'common/test_helper.dart'; + +void main() { + group('DDS', () { + late Process process; + late DartDevelopmentServiceLauncher dds; + + setUp(() async { + process = await spawnDartProcess('smoke.dart'); + }); + + tearDown(() async { + await dds.shutdown(); + process.kill(); + }); + + void createSmokeTest(bool useAuthCodes) { + test( + 'Launcher Smoke Test with ${useAuthCodes ? "" : "no"} authentication codes', + () async { + dds = await DartDevelopmentServiceLauncher.start( + remoteVmServiceUri: remoteVmServiceUri, + enableAuthCodes: useAuthCodes, + ); + + // Ensure basic websocket requests are forwarded correctly to the VM service. + final service = await vmServiceConnectUri(dds.wsUri.toString()); + final version = await service.getVersion(); + expect(version.major! > 0, true); + expect(version.minor! >= 0, true); + + expect( + dds.uri.pathSegments, + useAuthCodes ? isNotEmpty : isEmpty, + ); + + // Ensure we can still make requests of the VM service via HTTP. + HttpClient client = HttpClient(); + final request = await client.getUrl(remoteVmServiceUri.replace( + pathSegments: [ + if (remoteVmServiceUri.pathSegments.isNotEmpty) + remoteVmServiceUri.pathSegments.first, + 'getVersion', + ], + )); + final response = await request.close(); + final Map<String, dynamic> jsonResponse = (await response + .transform(utf8.decoder) + .transform(json.decoder) + .single) as Map<String, dynamic>; + expect(jsonResponse['result']['type'], 'Version'); + expect(jsonResponse['result']['major'] > 0, true); + expect(jsonResponse['result']['minor'] >= 0, true); + }, + ); + } + + createSmokeTest(true); + createSmokeTest(false); + }); +}
diff --git a/pkg/front_end/lib/src/base/scope.dart b/pkg/front_end/lib/src/base/scope.dart index bb726bd..1aabf30 100644 --- a/pkg/front_end/lib/src/base/scope.dart +++ b/pkg/front_end/lib/src/base/scope.dart
@@ -26,7 +26,6 @@ import '../source/source_function_builder.dart'; import '../source/source_library_builder.dart'; import '../source/source_member_builder.dart'; -import '../util/helpers.dart' show DelayedActionPerformer; import 'messages.dart'; import 'name_space.dart'; import 'uri_offset.dart'; @@ -773,9 +772,7 @@ ProcedureKind? get kind => null; @override - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { throw new UnsupportedError('$runtimeType.buildOutlineExpressions'); }
diff --git a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart index 8128c30..9f7c620 100644 --- a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart +++ b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
@@ -23,7 +23,6 @@ import '../source/source_field_builder.dart'; import '../source/source_library_builder.dart'; import '../source/type_parameter_scope_builder.dart'; -import '../util/helpers.dart' show DelayedActionPerformer; import 'builder.dart'; import 'constructor_builder.dart'; import 'declaration_builders.dart'; @@ -273,8 +272,7 @@ /// Builds the default value from this [initializerToken] if this is a /// formal parameter on a const constructor or instance method. - void buildOutlineExpressions(SourceLibraryBuilder libraryBuilder, - List<DelayedActionPerformer> delayedActionPerformers) { + void buildOutlineExpressions(SourceLibraryBuilder libraryBuilder) { if (needsDefaultValuesBuiltAsOutlineExpressions) { if (initializerToken != null) { final DeclarationBuilder declarationBuilder = @@ -296,9 +294,7 @@ bodyBuilder, initializer, variable!.type, hasDeclaredInitializer); variable!.initializer = initializer..parent = variable; initializerWasInferred = true; - bodyBuilder.performBacklogComputations( - delayedActionPerformers: delayedActionPerformers, - allowFurtherDelays: false); + bodyBuilder.performBacklogComputations(); } else if (kind.isOptional) { // As done by BodyBuilder.endFormalParameter. variable!.initializer = new NullLiteral()..parent = variable;
diff --git a/pkg/front_end/lib/src/builder/metadata_builder.dart b/pkg/front_end/lib/src/builder/metadata_builder.dart index 2e7c2da..315e768 100644 --- a/pkg/front_end/lib/src/builder/metadata_builder.dart +++ b/pkg/front_end/lib/src/builder/metadata_builder.dart
@@ -107,7 +107,7 @@ // TODO(johnniwinther): Avoid potentially inferring annotations multiple // times. bodyBuilder.inferAnnotations(parent, parent.annotations); - bodyBuilder.performBacklogComputations(allowFurtherDelays: false); + bodyBuilder.performBacklogComputations(); for (MapEntry<MetadataBuilder, int> entry in parsedAnnotationBuilders.entries) { MetadataBuilder annotationBuilder = entry.key;
diff --git a/pkg/front_end/lib/src/builder/type_variable_builder.dart b/pkg/front_end/lib/src/builder/type_variable_builder.dart index 6c56ff7..65dc82c 100644 --- a/pkg/front_end/lib/src/builder/type_variable_builder.dart +++ b/pkg/front_end/lib/src/builder/type_variable_builder.dart
@@ -401,7 +401,6 @@ SourceLibraryBuilder libraryBuilder, BodyBuilderContext bodyBuilderContext, ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, LookupScope scope) { MetadataBuilder.buildAnnotations(parameter, metadata, bodyBuilderContext, libraryBuilder, fileUri!, scope);
diff --git a/pkg/front_end/lib/src/kernel/benchmarker.dart b/pkg/front_end/lib/src/kernel/benchmarker.dart index 8f7af23..c1164de 100644 --- a/pkg/front_end/lib/src/kernel/benchmarker.dart +++ b/pkg/front_end/lib/src/kernel/benchmarker.dart
@@ -189,6 +189,7 @@ outline_buildClassHierarchyMembers, outline_computeHierarchy, outline_installTypedefTearOffs, + outline_performRedirectingFactoryInference, outline_performTopLevelInference, outline_checkOverrides, outline_checkAbstractMembers, @@ -279,7 +280,6 @@ inferRedirectingFactoryTypeArguments, buildOutlineExpressions, - delayedActionPerformer, computeMacroApplications_macroExecutorProvider, macroApplications_macroExecutorLoadMacro,
diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart index 81a3d1e..356a7a5 100644 --- a/pkg/front_end/lib/src/kernel/body_builder.dart +++ b/pkg/front_end/lib/src/kernel/body_builder.dart
@@ -100,8 +100,8 @@ import '../type_inference/type_inferrer.dart' show TypeInferrer, InferredFunctionBody; import '../type_inference/type_schema.dart' show UnknownType; -import '../util/local_stack.dart'; import '../util/helpers.dart'; +import '../util/local_stack.dart'; import 'benchmarker.dart' show Benchmarker; import 'body_builder_context.dart'; import 'collections.dart'; @@ -126,7 +126,7 @@ } class BodyBuilder extends StackListenerImpl - implements ExpressionGeneratorHelper, DelayedActionPerformer { + implements ExpressionGeneratorHelper { @override final Forest forest; @@ -246,89 +246,6 @@ /// nominal correspondingly. bool _insideOfFormalParameterType = false; - /// True if the currently built part of the body is inside of a default value - /// of a formal parameter. - /// - /// Being inside of a default value is treated with regards to possible - /// nestedness of the default values. See the documentation on - /// [_defaultValueNestingLevel] for details. - bool get _insideOfFormalParameterDefaultValue { - return _defaultValueNestingLevel > 0; - } - - /// True if the parser is between [beginMetadata] and [endMetadata]. - bool _insideMetadataParsing = false; - - /// Numeric nestedness of formal parameter default values. - /// - /// The value of 0 means that the currently built part is not within a default - /// value. Consider the following clarifying examples. - /// - /// // `const Bar()` isn't within a default value. - /// foo() => const Bar(); - /// - /// // `const Bar()` is at [_defaultValueNestingLevel] = 1. - /// foo([dynamic x = const Bar()]) {} - /// - /// // `const Bar()` is at [_defaultValueNestingLevel] = 2. - /// // `const Baz()` is at [_defaultValueNestingLevel] = 1. - /// foo([dynamic x = ([dynamic y = const Bar()]) => const Baz()]) {} - /// - /// Since function expressions aren't const values, currently it's not - /// possible to write a program with [_defaultValueNestingLevel] > 1 that - /// doesn't contain a compile-time error. However, it's still necessary to - /// track the nestedness level to avoid bad compiler states and compiler - /// crashes. - int _defaultValueNestingLevel = 0; - - /// Returns true if newly created aliased or redirecting invocations need - /// post-processing such as resolution or unaliasing. - /// - /// The need for the condition computed by the getter is due to some parts of - /// the AST being built twice. The first time they are built is during - /// outline expressions building. The second time they are built during the - /// function body building. However, they are fully processed only the first - /// time they are built, and the second time around they are discarded. - /// Additional complication arises due to some nodes, such as annotations, - /// being built only once. So we only need to add the nodes created for the - /// first time into the lists of nodes for post-processing. - /// - /// The invocations inside default values that need resolution or unaliasing - /// were already added to the post-processing lists during outline expression - /// building. Only those invocations that are built outside of the default - /// values or inside the default values that aren't built as outline - /// expressions need to be added during the second pass. - bool get _createdStaticInvocationsNeedPostProcessing { - return - // All invocations in outline building phase will be type-inferred, and - // they all should be added to the post-processing. - _context.inOutlineBuildingPhase || - - // Here we aren't in the outline mode, but rather in the - // body-building mode. If the current context has formal parameters - // and is a constructor context, their default values should be - // skipped because in the body-building mode they aren't passed - // through type inference. - (!_context.hasFormalParameters || - !_insideOfFormalParameterDefaultValue || - !_context.isConstructor) && - - // The invocations in the metadata should also be skipped in the - // body-building phase, since they aren't type-inferred. An - // exception here are the annotations within method bodies, - // field initializers, and on formal parameters. - !(_context.inMetadata || - _insideMetadataParsing && - !_inBody && - !inFormals && - !inFieldInitializer) && - - // Finally, the const fields in body-building phase aren't - // inferred and the invocations in them should be skipped during - // post-processing. - !_context.inConstFields; - } - bool get inFunctionType => _structuralParameterDepthLevel > 0 || _insideOfFormalParameterType; @@ -346,10 +263,6 @@ int functionNestingLevel = 0; - int _inBodyCount = 0; - - bool get _inBody => _inBodyCount > 0; - Statement? problemInLoopOrSwitch; LocalStack<LabelScope> _labelScopes; @@ -371,41 +284,6 @@ /// and where that was. Map<String, int>? initializedFields; - /// List of built redirecting factory invocations. The targets of the - /// invocations are to be resolved in a separate step. - final List<FactoryConstructorInvocation> redirectingFactoryInvocations = []; - - /// List of redirecting factory invocations delayed for resolution. - /// - /// A resolution of a redirecting factory invocation can be delayed because - /// the inference in the declaration of the redirecting factory isn't done - /// yet. - final List<FactoryConstructorInvocation> - delayedRedirectingFactoryInvocations = []; - - /// List of built type aliased generative constructor invocations that - /// require unaliasing. - final List<TypeAliasedConstructorInvocation> - typeAliasedConstructorInvocations = []; - - /// List of built type aliased factory constructor invocations that require - /// unaliasing. - final List<TypeAliasedFactoryInvocation> typeAliasedFactoryInvocations = []; - - /// List of type aliased factory invocations delayed for resolution. - /// - /// A resolution of a type aliased factory invocation can be delayed because - /// the inference in the declaration of the target isn't done yet. - final List<TypeAliasedFactoryInvocation> - delayedTypeAliasedFactoryInvocations = []; - - /// List of type aliased constructor invocations delayed for resolution. - /// - /// A resolution of a type aliased constructor invocation can be delayed - /// because the inference in the declaration of the target isn't done yet. - final List<TypeAliasedConstructorInvocation> - delayedTypeAliasedConstructorInvocations = []; - /// Variables with metadata. Their types need to be inferred late, for /// example, in [finishFunction]. List<VariableDeclaration>? variablesWithMetadata; @@ -538,9 +416,6 @@ void enterLocalScope(LocalScope localScope) { _localScopes.push(localScope); _labelScopes.push(new LabelScopeImpl(_labelScope)); - if (_localScope.kind == ScopeKind.functionBody) { - _inBodyCount++; - } } void createAndEnterLocalScope( @@ -548,9 +423,6 @@ _localScopes .push(_localScope.createNestedScope(debugName: debugName, kind: kind)); _labelScopes.push(new LabelScopeImpl(_labelScope)); - if (kind == ScopeKind.functionBody) { - _inBodyCount++; - } } void exitLocalScope({List<ScopeKind>? expectedScopeKinds}) { @@ -571,9 +443,6 @@ declaredInCurrentGuard = null; } } - if (_localScope.kind == ScopeKind.functionBody) { - _inBodyCount--; - } _labelScopes.pop(); _localScopes.pop(); } @@ -939,7 +808,6 @@ super.push(constantContext); constantContext = ConstantContext.inferred; assert(checkState(token, [ValueKinds.ConstantContext])); - _insideMetadataParsing = true; } @override @@ -1017,7 +885,6 @@ } constantContext = savedConstantContext; } - _insideMetadataParsing = false; assert(checkState(beginToken, [ValueKinds.Expression])); } @@ -1101,21 +968,7 @@ continue; } if (initializer != null) { - if (fieldBuilder.hasBodyBeenBuilt) { - // The initializer was already compiled (e.g., if it appear in the - // outline, like constant field initializers) so we do not need to - // perform type inference or transformations. - - // If the body is already built and it's a type aliased constructor or - // factory invocation, they shouldn't be checked or resolved the - // second time, so they are removed from the corresponding lists. - if (initializer is TypeAliasedConstructorInvocation) { - typeAliasedConstructorInvocations.remove(initializer); - } - if (initializer is TypeAliasedFactoryInvocation) { - typeAliasedFactoryInvocations.remove(initializer); - } - } else { + if (!fieldBuilder.hasBodyBeenBuilt) { initializer = typeInferrer .inferFieldInitializer(this, fieldBuilder.builtType, initializer) .expression; @@ -1143,7 +996,7 @@ } pop(); // Annotations. - performBacklogComputations(allowFurtherDelays: false); + performBacklogComputations(); assert(stack.length == 0); } @@ -1152,40 +1005,13 @@ /// /// Back logged computations include resolution of redirecting factory /// invocations and checking of typedef types. - /// - /// If the parameter [allowFurtherDelays] is set to `true`, the backlog - /// computations are allowed to be delayed one more time if they can't be - /// completed in the current invocation of [performBacklogComputations] and - /// have a chance to be completed during the next invocation. If - /// [allowFurtherDelays] is set to `false`, the backlog computations are - /// assumed to be final and the function throws an internal exception in case - /// if any of the computations can't be completed. - void performBacklogComputations( - {List<DelayedActionPerformer>? delayedActionPerformers, - required bool allowFurtherDelays}) { + void performBacklogComputations() { _finishVariableMetadata(); - _unaliasTypeAliasedConstructorInvocations( - typeAliasedConstructorInvocations); - _unaliasTypeAliasedFactoryInvocations(typeAliasedFactoryInvocations); - _resolveRedirectingFactoryTargets(redirectingFactoryInvocations, - allowFurtherDelays: allowFurtherDelays); libraryBuilder.checkPendingBoundsChecks(typeEnvironment); - if (hasDelayedActions) { - assert( - delayedActionPerformers != null, - // Coverage-ignore(suite): Not run. - "Body builder has delayed actions that cannot be performed: " - "${[ - ...delayedRedirectingFactoryInvocations, - ...delayedTypeAliasedFactoryInvocations, - ...delayedTypeAliasedConstructorInvocations, - ]}"); - delayedActionPerformers?.add(this); - } } void finishRedirectingFactoryBody() { - performBacklogComputations(allowFurtherDelays: false); + performBacklogComputations(); } @override @@ -1497,7 +1323,7 @@ _context.setBody(body); } - performBacklogComputations(allowFurtherDelays: false); + performBacklogComputations(); } void checkAsyncReturnType(AsyncMarker asyncModifier, DartType returnType, @@ -1615,7 +1441,8 @@ /// [target], `.arguments` is [arguments], `.fileOffset` is [fileOffset], /// and `.isConst` is [isConst]. /// Returns null if the invocation can't be resolved. - Expression? _resolveRedirectingFactoryTarget( + @override + Expression? resolveRedirectingFactoryTarget( Procedure target, Arguments arguments, int fileOffset, bool isConst) { Procedure initialTarget = target; Expression replacementNode; @@ -1662,195 +1489,49 @@ return replacementNode; } - /// If the parameter [allowFurtherDelays] is set to `true`, the resolution of - /// redirecting factories is allowed to be delayed one more time if it can't - /// be completed in the current invocation of - /// [_resolveRedirectingFactoryTargets] and has a chance to be completed - /// during the next invocation. If [allowFurtherDelays] is set to `false`, - /// the resolution of redirecting factories is assumed to be final and the - /// function throws an internal exception in case if any of the resolutions - /// can't be completed. - void _resolveRedirectingFactoryTargets( - List<FactoryConstructorInvocation> redirectingFactoryInvocations, - {required bool allowFurtherDelays}) { - List<FactoryConstructorInvocation> invocations = - redirectingFactoryInvocations.toList(); - redirectingFactoryInvocations.clear(); - for (FactoryConstructorInvocation invocation in invocations) { - // If the invocation was invalid, it or its parent has already been - // desugared into an exception throwing expression. There is nothing to - // resolve anymore. Note that in the case where the invocation's parent - // was invalid, type inference won't reach the invocation node and won't - // set its inferredType field. If type inference is disabled, reach to - // the outermost parent to check if the node is a dead code. - if (invocation.parent == null) continue; - if (!invocation.hasBeenInferred) { - if (allowFurtherDelays) { - delayedRedirectingFactoryInvocations.add(invocation); - } - continue; - } - Expression? replacement = _resolveRedirectingFactoryTarget( - invocation.target, - invocation.arguments, - invocation.fileOffset, - invocation.isConst); - if (replacement == null) { - delayedRedirectingFactoryInvocations.add(invocation); - } else { - invocation.parent?.replaceChild(invocation, replacement); - } - } - } - - void _unaliasTypeAliasedConstructorInvocations( - List<TypeAliasedConstructorInvocation> - typeAliasedConstructorInvocations) { - List<TypeAliasedConstructorInvocation> invocations = [ - ...typeAliasedConstructorInvocations - ]; - typeAliasedConstructorInvocations.clear(); - for (TypeAliasedConstructorInvocation invocation in invocations) { - assert( - invocation.hasBeenInferred || isOrphaned(invocation), - // Coverage-ignore(suite): Not run. - "Node $invocation has not been inferred."); - - Expression? replacement; - if (invocation.hasBeenInferred) { - bool inferred = !hasExplicitTypeArguments(invocation.arguments); - DartType aliasedType = new TypedefType( - invocation.typeAliasBuilder.typedef, - Nullability.nonNullable, - invocation.arguments.types); - libraryBuilder.checkBoundsInType( - aliasedType, typeEnvironment, uri, invocation.fileOffset, - allowSuperBounded: false, inferred: inferred); - DartType unaliasedType = aliasedType.unalias; - List<DartType>? invocationTypeArguments = null; - if (unaliasedType is InterfaceType) { - invocationTypeArguments = unaliasedType.typeArguments; - } - Arguments invocationArguments = forest.createArguments( - noLocation, invocation.arguments.positional, - types: invocationTypeArguments, named: invocation.arguments.named); - replacement = new ConstructorInvocation( - invocation.target, invocationArguments, - isConst: invocation.isConst); - } - if (replacement == null) { - delayedTypeAliasedConstructorInvocations.add(invocation); - } else { - invocation.parent?.replaceChild(invocation, replacement); - } - } - typeAliasedConstructorInvocations.clear(); - } - - void _unaliasTypeAliasedFactoryInvocations( - List<TypeAliasedFactoryInvocation> typeAliasedFactoryInvocations) { - List<TypeAliasedFactoryInvocation> invocations = - typeAliasedFactoryInvocations.toList(); - typeAliasedFactoryInvocations.clear(); - for (TypeAliasedFactoryInvocation invocation in invocations) { - assert( - invocation.hasBeenInferred || isOrphaned(invocation), - // Coverage-ignore(suite): Not run. - "Node $invocation has not been inferred."); - - Expression? replacement; - if (invocation.hasBeenInferred) { - bool inferred = !hasExplicitTypeArguments(invocation.arguments); - DartType aliasedType = new TypedefType( - invocation.typeAliasBuilder.typedef, - Nullability.nonNullable, - invocation.arguments.types); - libraryBuilder.checkBoundsInType( - aliasedType, typeEnvironment, uri, invocation.fileOffset, - allowSuperBounded: false, inferred: inferred); - DartType unaliasedType = aliasedType.unalias; - List<DartType>? invocationTypeArguments = null; - if (unaliasedType is TypeDeclarationType) { - invocationTypeArguments = unaliasedType.typeArguments; - } - Arguments invocationArguments = forest.createArguments( - noLocation, invocation.arguments.positional, - types: invocationTypeArguments, - named: invocation.arguments.named, - hasExplicitTypeArguments: - hasExplicitTypeArguments(invocation.arguments)); - replacement = _resolveRedirectingFactoryTarget(invocation.target, - invocationArguments, invocation.fileOffset, invocation.isConst); - } - - if (replacement == null) { - delayedTypeAliasedFactoryInvocations.add(invocation); - } else { - invocation.parent?.replaceChild(invocation, replacement); - } - } - typeAliasedFactoryInvocations.clear(); - } - - /// Perform actions that were delayed - /// - /// An action can be delayed, for instance, because it depends on some - /// calculations in another library. For example, a resolution of a - /// redirecting factory invocation depends on the type inference in the - /// redirecting factory. @override - void performDelayedActions({required bool allowFurtherDelays}) { - if (delayedRedirectingFactoryInvocations.isNotEmpty) { - _resolveRedirectingFactoryTargets(delayedRedirectingFactoryInvocations, - allowFurtherDelays: allowFurtherDelays); - if (delayedRedirectingFactoryInvocations.isNotEmpty) { - // Coverage-ignore-block(suite): Not run. - for (StaticInvocation invocation - in delayedRedirectingFactoryInvocations) { - internalProblem( - fasta.templateInternalProblemUnhandled.withArguments( - invocation.target.name.text, 'performDelayedActions'), - invocation.fileOffset, - uri); - } - } + Expression unaliasSingleTypeAliasedConstructorInvocation( + TypeAliasedConstructorInvocation invocation) { + bool inferred = !hasExplicitTypeArguments(invocation.arguments); + DartType aliasedType = new TypedefType(invocation.typeAliasBuilder.typedef, + Nullability.nonNullable, invocation.arguments.types); + libraryBuilder.checkBoundsInType( + aliasedType, typeEnvironment, uri, invocation.fileOffset, + allowSuperBounded: false, inferred: inferred); + DartType unaliasedType = aliasedType.unalias; + List<DartType>? invocationTypeArguments = null; + if (unaliasedType is InterfaceType) { + invocationTypeArguments = unaliasedType.typeArguments; } - if (delayedTypeAliasedFactoryInvocations.isNotEmpty) { - _unaliasTypeAliasedFactoryInvocations( - delayedTypeAliasedFactoryInvocations); - if (delayedTypeAliasedFactoryInvocations.isNotEmpty) { - // Coverage-ignore-block(suite): Not run. - for (StaticInvocation invocation - in delayedTypeAliasedFactoryInvocations) { - internalProblem( - fasta.templateInternalProblemUnhandled.withArguments( - invocation.target.name.text, 'performDelayedActions'), - invocation.fileOffset, - uri); - } - } - } - if (delayedTypeAliasedConstructorInvocations.isNotEmpty) { - _unaliasTypeAliasedConstructorInvocations( - delayedTypeAliasedConstructorInvocations); - if (delayedTypeAliasedConstructorInvocations.isNotEmpty) { - // Coverage-ignore-block(suite): Not run. - for (ConstructorInvocation invocation - in delayedTypeAliasedConstructorInvocations) { - internalProblem( - fasta.templateInternalProblemUnhandled.withArguments( - invocation.target.name.text, 'performDelayedActions'), - invocation.fileOffset, - uri); - } - } - } + Arguments invocationArguments = forest.createArguments( + noLocation, invocation.arguments.positional, + types: invocationTypeArguments, named: invocation.arguments.named); + return new ConstructorInvocation(invocation.target, invocationArguments, + isConst: invocation.isConst); } - bool get hasDelayedActions { - return delayedRedirectingFactoryInvocations.isNotEmpty || - delayedTypeAliasedFactoryInvocations.isNotEmpty || - delayedTypeAliasedConstructorInvocations.isNotEmpty; + @override + Expression? unaliasSingleTypeAliasedFactoryInvocation( + TypeAliasedFactoryInvocation invocation) { + bool inferred = !hasExplicitTypeArguments(invocation.arguments); + DartType aliasedType = new TypedefType(invocation.typeAliasBuilder.typedef, + Nullability.nonNullable, invocation.arguments.types); + libraryBuilder.checkBoundsInType( + aliasedType, typeEnvironment, uri, invocation.fileOffset, + allowSuperBounded: false, inferred: inferred); + DartType unaliasedType = aliasedType.unalias; + List<DartType>? invocationTypeArguments = null; + if (unaliasedType is TypeDeclarationType) { + invocationTypeArguments = unaliasedType.typeArguments; + } + Arguments invocationArguments = forest.createArguments( + noLocation, invocation.arguments.positional, + types: invocationTypeArguments, + named: invocation.arguments.named, + hasExplicitTypeArguments: + hasExplicitTypeArguments(invocation.arguments)); + return resolveRedirectingFactoryTarget(invocation.target, + invocationArguments, invocation.fileOffset, invocation.isConst); } void _finishVariableMetadata() { @@ -1902,15 +1583,14 @@ // Coverage-ignore-block(suite): Not run. temporaryParent = new ListLiteral(expressions); } - performBacklogComputations(allowFurtherDelays: false); // Coverage-ignore(suite): Not run. + performBacklogComputations(); return temporaryParent != null ? temporaryParent.expressions : expressions; } // Coverage-ignore(suite): Not run. Expression parseSingleExpression( Parser parser, Token token, FunctionNode parameters) { - assert(redirectingFactoryInvocations.isEmpty); int fileOffset = offsetForToken(token); List<NominalVariableBuilder>? typeParameterBuilders; for (TypeParameter typeParameter in parameters.typeParameters) { @@ -1988,7 +1668,7 @@ "Previously implicit assumption about inferFunctionBody " "not returning anything different."); - performBacklogComputations(allowFurtherDelays: false); + performBacklogComputations(); return fakeReturn.expression!; } @@ -5764,7 +5444,6 @@ super.push(constantContext); _insideOfFormalParameterType = false; constantContext = ConstantContext.required; - _defaultValueNestingLevel++; } @override @@ -5773,7 +5452,6 @@ Object? defaultValueExpression = pop(); constantContext = pop() as ConstantContext; push(defaultValueExpression); - _defaultValueNestingLevel--; } @override @@ -6253,17 +5931,12 @@ libraryBuilder.checkBoundsInConstructorInvocation( node, typeEnvironment, uri); } else { - TypeAliasedConstructorInvocation typeAliasedConstructorInvocation = - node = new TypeAliasedConstructorInvocation( - typeAliasBuilder, target, arguments, - isConst: isConst) - ..fileOffset = charOffset; + node = new TypeAliasedConstructorInvocation( + typeAliasBuilder, target, arguments, + isConst: isConst) + ..fileOffset = charOffset; // No type arguments were passed, so we need not check bounds. assert(arguments.types.isEmpty); - if (_createdStaticInvocationsNeedPostProcessing) { - typeAliasedConstructorInvocations - .add(typeAliasedConstructorInvocation); - } } return node; } else { @@ -6295,9 +5968,6 @@ libraryBuilder.checkBoundsInFactoryInvocation( factoryConstructorInvocation, typeEnvironment, uri, inferred: !hasExplicitTypeArguments(arguments)); - if (_createdStaticInvocationsNeedPostProcessing) { - redirectingFactoryInvocations.add(factoryConstructorInvocation); - } node = factoryConstructorInvocation; } else { TypeAliasedFactoryInvocation typeAliasedFactoryInvocation = @@ -6307,9 +5977,6 @@ ..fileOffset = charOffset; // No type arguments were passed, so we need not check bounds. assert(arguments.types.isEmpty); - if (_createdStaticInvocationsNeedPostProcessing) { - typeAliasedFactoryInvocations.add(typeAliasedFactoryInvocation); - } node = typeAliasedFactoryInvocation; } return node; @@ -10525,7 +10192,6 @@ node.target, clone(node.arguments), isConst: node.isConst) ..hasBeenInferred = node.hasBeenInferred; - bodyBuilder.redirectingFactoryInvocations.add(result); return result; } // Coverage-ignore(suite): Not run. @@ -10534,7 +10200,6 @@ node.typeAliasBuilder, node.target, clone(node.arguments), isConst: node.isConst) ..hasBeenInferred = node.hasBeenInferred; - bodyBuilder.typeAliasedFactoryInvocations.add(result); return result; } // Coverage-ignore(suite): Not run. @@ -10550,7 +10215,6 @@ node.typeAliasBuilder, node.target, clone(node.arguments), isConst: node.isConst) ..hasBeenInferred = node.hasBeenInferred; - bodyBuilder.typeAliasedConstructorInvocations.add(result); return result; } return super.visitConstructorInvocation(node);
diff --git a/pkg/front_end/lib/src/kernel/kernel_target.dart b/pkg/front_end/lib/src/kernel/kernel_target.dart index 747d9f1..526a03b 100644 --- a/pkg/front_end/lib/src/kernel/kernel_target.dart +++ b/pkg/front_end/lib/src/kernel/kernel_target.dart
@@ -616,6 +616,15 @@ benchmarker // Coverage-ignore(suite): Not run. + ?.enterPhase( + BenchmarkPhases.outline_performRedirectingFactoryInference); + // TODO(johnniwinther): Add an interface for registering delayed actions. + List<DelayedDefaultValueCloner> delayedDefaultValueCloners = []; + loader.inferRedirectingFactories( + loader.hierarchy, delayedDefaultValueCloners); + + benchmarker + // Coverage-ignore(suite): Not run. ?.enterPhase(BenchmarkPhases.outline_performTopLevelInference); loader.performTopLevelInference(sortedSourceClassBuilders); @@ -637,8 +646,6 @@ benchmarker // Coverage-ignore(suite): Not run. ?.enterPhase(BenchmarkPhases.outline_buildOutlineExpressions); - // TODO(johnniwinther): Add an interface for registering delayed actions. - List<DelayedDefaultValueCloner> delayedDefaultValueCloners = []; loader.buildOutlineExpressions( loader.hierarchy, delayedDefaultValueCloners); delayedDefaultValueCloners.forEach(registerDelayedDefaultValueCloner);
diff --git a/pkg/front_end/lib/src/source/source_builder_factory.dart b/pkg/front_end/lib/src/source/source_builder_factory.dart index d02d5ad..0ca16da 100644 --- a/pkg/front_end/lib/src/source/source_builder_factory.dart +++ b/pkg/front_end/lib/src/source/source_builder_factory.dart
@@ -1519,6 +1519,8 @@ procedureNameScheme, nativeMethodName, redirectionTarget); + (_parent.redirectingFactoryBuilders ??= []) + .add(procedureBuilder as RedirectingFactoryBuilder); } else { procedureBuilder = new SourceFactoryBuilder( metadata,
diff --git a/pkg/front_end/lib/src/source/source_builder_mixins.dart b/pkg/front_end/lib/src/source/source_builder_mixins.dart index defa998..8201a79 100644 --- a/pkg/front_end/lib/src/source/source_builder_mixins.dart +++ b/pkg/front_end/lib/src/source/source_builder_mixins.dart
@@ -20,7 +20,6 @@ import '../builder/type_builder.dart'; import '../kernel/body_builder_context.dart'; import '../kernel/kernel_helper.dart'; -import '../util/helpers.dart'; import 'source_constructor_builder.dart'; import 'source_field_builder.dart'; import 'source_library_builder.dart'; @@ -159,9 +158,7 @@ required bool inMetadata, required bool inConstFields}); - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { MetadataBuilder.buildAnnotations( annotatable, @@ -182,7 +179,6 @@ inMetadata: true, inConstFields: false), classHierarchy, - delayedActionPerformers, typeParameterScope); } } @@ -190,8 +186,8 @@ Iterator<SourceMemberBuilder> iterator = nameSpace.filteredIterator( parent: this, includeDuplicates: false, includeAugmentations: true); while (iterator.moveNext()) { - iterator.current.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + iterator.current + .buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners); } }
diff --git a/pkg/front_end/lib/src/source/source_class_builder.dart b/pkg/front_end/lib/src/source/source_class_builder.dart index f6598d5..d2b4cf6 100644 --- a/pkg/front_end/lib/src/source/source_class_builder.dart +++ b/pkg/front_end/lib/src/source/source_class_builder.dart
@@ -44,7 +44,6 @@ import '../kernel/kernel_helper.dart'; import '../kernel/type_algorithms.dart' show computeTypeVariableBuilderVariance; import '../kernel/utils.dart' show compareProcedures; -import '../util/helpers.dart'; import 'class_declaration.dart'; import 'source_builder_mixins.dart'; import 'source_constructor_builder.dart'; @@ -383,14 +382,12 @@ inConstFields: inConstFields); } - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { void build(Builder declaration) { SourceMemberBuilder member = declaration as SourceMemberBuilder; member.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + classHierarchy, delayedDefaultValueCloners); } MetadataBuilder.buildAnnotations( @@ -413,7 +410,6 @@ inMetadata: true, inConstFields: false), classHierarchy, - delayedActionPerformers, typeParameterScope); } }
diff --git a/pkg/front_end/lib/src/source/source_constructor_builder.dart b/pkg/front_end/lib/src/source/source_constructor_builder.dart index 4f5fd9d..2572203 100644 --- a/pkg/front_end/lib/src/source/source_constructor_builder.dart +++ b/pkg/front_end/lib/src/source/source_constructor_builder.dart
@@ -45,7 +45,6 @@ finishProcedureAugmentation; import '../type_inference/inference_results.dart'; import '../type_inference/type_schema.dart'; -import '../util/helpers.dart' show DelayedActionPerformer; import 'constructor_declaration.dart'; import 'name_scheme.dart'; import 'source_class_builder.dart'; @@ -302,9 +301,7 @@ } void _buildConstructorForOutline( - Token? beginInitializers, - List<DelayedActionPerformer> delayedActionPerformers, - LookupScope declarationScope) { + Token? beginInitializers, LookupScope declarationScope) { if (beginInitializers != null) { final LocalScope? formalParameterScope; if (isConst) { @@ -328,11 +325,10 @@ if (isConst) { bodyBuilder.constantContext = ConstantContext.required; } + inferFormalTypes(bodyBuilder.hierarchy); bodyBuilder.parseInitializers(beginInitializers, doFinishConstructor: isConst); - bodyBuilder.performBacklogComputations( - delayedActionPerformers: delayedActionPerformers, - allowFurtherDelays: false); + bodyBuilder.performBacklogComputations(); } } @@ -842,24 +838,20 @@ bool _hasBuiltOutlines = false; @override - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { if (_hasBuiltOutlines) return; if (isConst && isAugmenting) { origin.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + classHierarchy, delayedDefaultValueCloners); } - super.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners); // For modular compilation purposes we need to include initializers // for const constructors into the outline. We also need to parse // initializers to infer types of the super-initializing parameters. if (isConst || _hasSuperInitializingFormals) { - _buildConstructorForOutline( - beginInitializers, delayedActionPerformers, classBuilder.scope); + _buildConstructorForOutline(beginInitializers, classBuilder.scope); } addSuperParameterDefaultValueCloners(delayedDefaultValueCloners); if (isConst && isAugmenting) { @@ -1104,9 +1096,7 @@ } @override - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { if (_immediatelyDefiningConstructor != null) { // Ensure that default value expressions have been created for [_origin]. @@ -1114,8 +1104,8 @@ // values and initializers first. MemberBuilder origin = _immediatelyDefiningConstructor!; if (origin is SourceConstructorBuilder) { - origin.buildOutlineExpressions(classHierarchy, delayedActionPerformers, - delayedDefaultValueCloners); + origin.buildOutlineExpressions( + classHierarchy, delayedDefaultValueCloners); } addSuperParameterDefaultValueCloners(delayedDefaultValueCloners); _immediatelyDefiningConstructor = null; @@ -1265,20 +1255,16 @@ } @override - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { - super.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners); if (isConst) { // For modular compilation purposes we need to include initializers // for const constructors into the outline. LookupScope typeParameterScope = computeTypeParameterScope(extensionTypeDeclarationBuilder.scope); - _buildConstructorForOutline( - beginInitializers, delayedActionPerformers, typeParameterScope); + _buildConstructorForOutline(beginInitializers, typeParameterScope); _buildBody(); } beginInitializers = null;
diff --git a/pkg/front_end/lib/src/source/source_enum_builder.dart b/pkg/front_end/lib/src/source/source_enum_builder.dart index 4540be2..2abf5d9 100644 --- a/pkg/front_end/lib/src/source/source_enum_builder.dart +++ b/pkg/front_end/lib/src/source/source_enum_builder.dart
@@ -51,7 +51,6 @@ import '../kernel/kernel_helper.dart'; import '../type_inference/inference_results.dart'; import '../type_inference/type_schema.dart'; -import '../util/helpers.dart'; import 'name_scheme.dart'; import 'source_class_builder.dart' show SourceClassBuilder; import 'source_constructor_builder.dart'; @@ -83,8 +82,6 @@ final Set<SourceFieldBuilder> _builtElements = new Set<SourceFieldBuilder>.identity(); - final List<DelayedActionPerformer> _delayedActionPerformers = []; - SourceEnumBuilder.internal( List<MetadataBuilder>? metadata, String name, @@ -702,9 +699,7 @@ // redirecting factories can't be completed at this moment and // therefore should be delayed to another invocation of // [BodyBuilder.performBacklogComputations]. - bodyBuilder.performBacklogComputations( - delayedActionPerformers: _delayedActionPerformers, - allowFurtherDelays: true); + bodyBuilder.performBacklogComputations(); arguments.positional.insertAll(0, enumSyntheticArguments); arguments.argumentsOriginalOrder?.insertAll(0, enumSyntheticArguments); @@ -778,9 +773,7 @@ } @override - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { List<Expression> values = <Expression>[]; if (enumConstantInfos != null) { @@ -807,8 +800,6 @@ elementBuilder.type.registerInferredType( buildElement(elementBuilder, classHierarchy.coreTypes)); } - delayedActionPerformers.addAll(_delayedActionPerformers); - _delayedActionPerformers.clear(); SourceProcedureBuilder toStringBuilder = firstMemberNamed("_enumToString") as SourceProcedureBuilder; @@ -846,8 +837,7 @@ ])); } - super.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners); } }
diff --git a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart index 29dcd03..d892e59 100644 --- a/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart +++ b/pkg/front_end/lib/src/source/source_extension_type_declaration_builder.dart
@@ -29,7 +29,6 @@ import '../kernel/kernel_helper.dart'; import '../kernel/type_algorithms.dart'; import '../type_inference/type_inference_engine.dart'; -import '../util/helpers.dart'; import 'class_declaration.dart'; import 'source_builder_mixins.dart'; import 'source_constructor_builder.dart'; @@ -594,18 +593,15 @@ } @override - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { - super.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners); Iterator<SourceMemberBuilder> iterator = constructorScope.filteredIterator( parent: this, includeDuplicates: false, includeAugmentations: true); while (iterator.moveNext()) { - iterator.current.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + iterator.current + .buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners); } }
diff --git a/pkg/front_end/lib/src/source/source_factory_builder.dart b/pkg/front_end/lib/src/source/source_factory_builder.dart index ff84d96..07f7370 100644 --- a/pkg/front_end/lib/src/source/source_factory_builder.dart +++ b/pkg/front_end/lib/src/source/source_factory_builder.dart
@@ -24,6 +24,7 @@ import '../builder/formal_parameter_builder.dart'; import '../builder/function_builder.dart'; import '../builder/metadata_builder.dart'; +import '../builder/omitted_type_builder.dart'; import '../builder/type_builder.dart'; import '../codes/cfe_codes.dart'; import '../dill/dill_extension_type_member_builder.dart'; @@ -35,7 +36,6 @@ import '../type_inference/inference_helper.dart'; import '../type_inference/type_inferrer.dart'; import '../type_inference/type_schema.dart'; -import '../util/helpers.dart'; import 'name_scheme.dart'; import 'redirecting_factory_body.dart'; import 'source_class_builder.dart'; @@ -202,16 +202,13 @@ bool _hasBuiltOutlines = false; @override - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { if (_hasBuiltOutlines) return; if (_delayedDefaultValueCloner != null) { delayedDefaultValueCloners.add(_delayedDefaultValueCloner!); } - super.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners); _hasBuiltOutlines = true; } @@ -487,20 +484,21 @@ bool _hasBuiltOutlines = false; @override - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { if (_hasBuiltOutlines) return; if (isConst && isAugmenting) { origin.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + classHierarchy, delayedDefaultValueCloners); } - super.buildOutlineExpressions( - classHierarchy, delayedActionPerformers, delayedDefaultValueCloners); + super.buildOutlineExpressions(classHierarchy, delayedDefaultValueCloners); - RedirectingFactoryTarget redirectingFactoryTarget = - _procedureInternal.function.redirectingFactoryTarget!; + RedirectingFactoryTarget? redirectingFactoryTarget = + _procedureInternal.function.redirectingFactoryTarget; + if (redirectingFactoryTarget == null) { + // The error is reported elsewhere. + return; + } List<DartType>? typeArguments = redirectingFactoryTarget.typeArguments; Member? target = redirectingFactoryTarget.target; if (typeArguments != null && typeArguments.any((t) => t is UnknownType)) { @@ -519,8 +517,8 @@ Builder? targetBuilder = redirectionTarget.target; if (targetBuilder is SourceMemberBuilder) { // Ensure that target has been built. - targetBuilder.buildOutlineExpressions(classHierarchy, - delayedActionPerformers, delayedDefaultValueCloners); + targetBuilder.buildOutlineExpressions( + classHierarchy, delayedDefaultValueCloners); } if (targetBuilder is FunctionBuilder) { target = targetBuilder.member; @@ -532,6 +530,23 @@ unhandled("${targetBuilder.runtimeType}", "buildOutlineExpressions", charOffset, fileUri); } + + // Type arguments for the targets of redirecting factories can only be + // inferred if the formal parameters of the targets are inferred too. + // That may not be the case when the target's parameters are initializing + // parameters referring to fields with types that are to be inferred. + if (targetBuilder is SourceFunctionBuilderImpl) { + List<FormalParameterBuilder>? formals = targetBuilder.formals; + if (formals != null) { + for (FormalParameterBuilder formal in formals) { + TypeBuilder formalType = formal.type; + if (formalType is InferableTypeBuilder) { + formalType.inferType(classHierarchy); + } + } + } + } + typeArguments = inferrer.inferRedirectingFactoryTypeArguments( helper, _procedureInternal.function.returnType,
diff --git a/pkg/front_end/lib/src/source/source_field_builder.dart b/pkg/front_end/lib/src/source/source_field_builder.dart index 443b41e..d60b640 100644 --- a/pkg/front_end/lib/src/source/source_field_builder.dart +++ b/pkg/front_end/lib/src/source/source_field_builder.dart
@@ -37,7 +37,6 @@ import '../source/source_library_builder.dart' show SourceLibraryBuilder; import '../type_inference/type_inference_engine.dart' show IncludesTypeParametersNonCovariantly; -import '../util/helpers.dart' show DelayedActionPerformer; import 'source_class_builder.dart'; import 'source_extension_type_declaration_builder.dart'; import 'source_member_builder.dart'; @@ -452,9 +451,7 @@ Iterable<Annotatable> get annotatables => _fieldEncoding.annotatables; @override - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { for (Annotatable annotatable in annotatables) { MetadataBuilder.buildAnnotations( @@ -495,9 +492,7 @@ bodyBuilder.parseFieldInitializer(_constInitializerToken!)) .expression; buildBody(classHierarchy.coreTypes, initializer); - bodyBuilder.performBacklogComputations( - delayedActionPerformers: delayedActionPerformers, - allowFurtherDelays: false); + bodyBuilder.performBacklogComputations(); } _constInitializerToken = null; }
diff --git a/pkg/front_end/lib/src/source/source_function_builder.dart b/pkg/front_end/lib/src/source/source_function_builder.dart index dac0725..3e5f9de 100644 --- a/pkg/front_end/lib/src/source/source_function_builder.dart +++ b/pkg/front_end/lib/src/source/source_function_builder.dart
@@ -34,7 +34,6 @@ import 'source_loader.dart' show SourceLoader; import '../type_inference/type_inference_engine.dart' show IncludesTypeParametersNonCovariantly; -import '../util/helpers.dart' show DelayedActionPerformer; import 'source_builder_mixins.dart'; import 'source_extension_type_declaration_builder.dart'; import 'source_member_builder.dart'; @@ -482,9 +481,7 @@ } @override - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { if (!hasBuiltOutlineExpressions) { DeclarationBuilder? classOrExtensionBuilder = @@ -515,7 +512,6 @@ inMetadata: true, inConstFields: false), classHierarchy, - delayedActionPerformers, computeTypeParameterScope(parentScope)); } } @@ -526,8 +522,7 @@ // buildOutlineExpressions to clear initializerToken to prevent // consuming too much memory. for (FormalParameterBuilder formal in formals!) { - formal.buildOutlineExpressions( - libraryBuilder, delayedActionPerformers); + formal.buildOutlineExpressions(libraryBuilder); } } hasBuiltOutlineExpressions = true;
diff --git a/pkg/front_end/lib/src/source/source_library_builder.dart b/pkg/front_end/lib/src/source/source_library_builder.dart index 58258b1..068f780 100644 --- a/pkg/front_end/lib/src/source/source_library_builder.dart +++ b/pkg/front_end/lib/src/source/source_library_builder.dart
@@ -71,7 +71,6 @@ exportNeverSentinel, toKernelCombinators, unserializableExportName; -import '../util/helpers.dart'; import 'builder_factory.dart'; import 'class_declaration.dart'; import 'name_scheme.dart'; @@ -189,6 +188,13 @@ /// if [SourceLoader.computeFieldPromotability] hasn't been called. FieldNonPromotabilityInfo? fieldNonPromotabilityInfo; + /// Redirecting factory builders defined in the library. They should be + /// collected as they are built, so that we can build the outline expressions + /// in the right order. + /// + /// See [SourceLoader.buildOutlineExpressions] for details. + List<RedirectingFactoryBuilder>? redirectingFactoryBuilders; + // TODO(johnniwinther): Remove this. final Map<String, List<Builder>>? augmentations; @@ -1142,16 +1148,14 @@ inConstFields: inConstFields); } - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedDefaultValueCloner> delayedDefaultValueCloners, - List<DelayedActionPerformer> delayedActionPerformers) { + void buildOutlineExpressions(ClassHierarchy classHierarchy, + List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { Iterable<SourceLibraryBuilder>? augmentationLibraries = this.augmentationLibraries; if (augmentationLibraries != null) { for (SourceLibraryBuilder augmentationLibrary in augmentationLibraries) { - augmentationLibrary.buildOutlineExpressions(classHierarchy, - delayedDefaultValueCloners, delayedActionPerformers); + augmentationLibrary.buildOutlineExpressions( + classHierarchy, delayedDefaultValueCloners); } } @@ -1171,20 +1175,20 @@ while (iterator.moveNext()) { Builder declaration = iterator.current; if (declaration is SourceClassBuilder) { - declaration.buildOutlineExpressions(classHierarchy, - delayedActionPerformers, delayedDefaultValueCloners); + declaration.buildOutlineExpressions( + classHierarchy, delayedDefaultValueCloners); } else if (declaration is SourceExtensionBuilder) { - declaration.buildOutlineExpressions(classHierarchy, - delayedActionPerformers, delayedDefaultValueCloners); + declaration.buildOutlineExpressions( + classHierarchy, delayedDefaultValueCloners); } else if (declaration is SourceExtensionTypeDeclarationBuilder) { - declaration.buildOutlineExpressions(classHierarchy, - delayedActionPerformers, delayedDefaultValueCloners); + declaration.buildOutlineExpressions( + classHierarchy, delayedDefaultValueCloners); } else if (declaration is SourceMemberBuilder) { - declaration.buildOutlineExpressions(classHierarchy, - delayedActionPerformers, delayedDefaultValueCloners); + declaration.buildOutlineExpressions( + classHierarchy, delayedDefaultValueCloners); } else if (declaration is SourceTypeAliasBuilder) { - declaration.buildOutlineExpressions(classHierarchy, - delayedActionPerformers, delayedDefaultValueCloners); + declaration.buildOutlineExpressions( + classHierarchy, delayedDefaultValueCloners); } else { assert( declaration is PrefixBuilder ||
diff --git a/pkg/front_end/lib/src/source/source_loader.dart b/pkg/front_end/lib/src/source/source_loader.dart index 897c3e9..48d8dd8 100644 --- a/pkg/front_end/lib/src/source/source_loader.dart +++ b/pkg/front_end/lib/src/source/source_loader.dart
@@ -78,7 +78,6 @@ import '../macros/macro_injected_impl.dart' as injected; import '../type_inference/type_inference_engine.dart'; import '../type_inference/type_inferrer.dart'; -import '../util/helpers.dart'; import 'diet_listener.dart' show DietListener; import 'diet_parser.dart' show DietParser, useImplicitCreationExpressionInCfe; import 'name_scheme.dart'; @@ -88,6 +87,7 @@ import 'source_constructor_builder.dart'; import 'source_enum_builder.dart'; import 'source_extension_type_declaration_builder.dart'; +import 'source_factory_builder.dart'; import 'source_library_builder.dart' show ImplicitLanguageVersion, @@ -2898,24 +2898,10 @@ void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { - List<DelayedActionPerformer> delayedActionPerformers = - <DelayedActionPerformer>[]; for (SourceLibraryBuilder library in sourceLibraryBuilders) { library.buildOutlineExpressions( - classHierarchy, delayedDefaultValueCloners, delayedActionPerformers); + classHierarchy, delayedDefaultValueCloners); } - - target.benchmarker - // Coverage-ignore(suite): Not run. - ?.beginSubdivide(BenchmarkSubdivides.delayedActionPerformer); - for (DelayedActionPerformer delayedActionPerformer - in delayedActionPerformers) { - delayedActionPerformer.performDelayedActions(allowFurtherDelays: false); - } - target.benchmarker - // Coverage-ignore(suite): Not run. - ?.endSubdivide(); - ticker.logMs("Build outline expressions"); } void buildClassHierarchy( @@ -2943,15 +2929,47 @@ new TypeInferenceEngineImpl(instrumentation, target.benchmarker); } - void performTopLevelInference(List<SourceClassBuilder> sourceClasses) { + void inferRedirectingFactories(ClassHierarchy classHierarchy, + List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { + /// Inferring redirecting factories partially overlaps with top-level + /// inference, since the formal parameters of the redirection targets should + /// be inferred, and they can be formal initializing parameters requiring + /// inference. [RedirectingFactoryBuilder.buildOutlineExpressions] can + /// invoke inference on those formal parameters. Therefore, the top-level + /// inference should be prepared before we can infer redirecting factories. + /// The first phase of top level initializer inference, which consists of /// creating kernel objects for all fields and top level variables that /// might be subject to type inference, and records dependencies between /// them. typeInferenceEngine.prepareTopLevel(coreTypes, hierarchy); membersBuilder.computeTypes(); - inferableTypes.inferTypes(typeInferenceEngine.hierarchyBuilder); + // TODO(cstefantsova): Put the redirecting factory inference into a separate + // step. + + // Redirecting factory invocations can occur in outline expressions and + // should be processed before them. The outline expressions within + // redirecting factory invocations themselves are minimal, containing only + // the target and possibly some type arguments, and don't depend on other + // kinds of outline expressions themselves. + for (SourceLibraryBuilder library in sourceLibraryBuilders) { + List<RedirectingFactoryBuilder>? redirectingFactoryBuilders = + library.redirectingFactoryBuilders; + if (redirectingFactoryBuilders != null) { + for (RedirectingFactoryBuilder redirectingFactoryBuilder + in redirectingFactoryBuilders) { + redirectingFactoryBuilder.buildOutlineExpressions( + classHierarchy, delayedDefaultValueCloners); + } + } + } + + ticker.logMs("Performed redirecting factory inference"); + } + + void performTopLevelInference(List<SourceClassBuilder> sourceClasses) { + inferableTypes.inferTypes(typeInferenceEngine.hierarchyBuilder); typeInferenceEngine.isTypeInferencePrepared = true; ticker.logMs("Performed top level inference");
diff --git a/pkg/front_end/lib/src/source/source_member_builder.dart b/pkg/front_end/lib/src/source/source_member_builder.dart index 35ce7d3..136c2fb 100644 --- a/pkg/front_end/lib/src/source/source_member_builder.dart +++ b/pkg/front_end/lib/src/source/source_member_builder.dart
@@ -18,7 +18,6 @@ import '../kernel/kernel_helper.dart'; import '../type_inference/type_inference_engine.dart' show InferenceDataForTesting; -import '../util/helpers.dart' show DelayedActionPerformer; import 'source_class_builder.dart'; import 'source_library_builder.dart'; @@ -34,9 +33,7 @@ /// Builds the core AST structures for this member as needed for the outline. void buildOutlineNodes(BuildNodesCallback f); - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners); /// Builds the AST nodes for this member as needed for the full compilation. @@ -171,9 +168,7 @@ @override // Coverage-ignore(suite): Not run. - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) {} @override
diff --git a/pkg/front_end/lib/src/source/source_type_alias_builder.dart b/pkg/front_end/lib/src/source/source_type_alias_builder.dart index 8db6d9b..4325d2c 100644 --- a/pkg/front_end/lib/src/source/source_type_alias_builder.dart +++ b/pkg/front_end/lib/src/source/source_type_alias_builder.dart
@@ -25,7 +25,6 @@ import '../kernel/constructor_tearoff_lowering.dart'; import '../kernel/expression_generator_helper.dart'; import '../kernel/kernel_helper.dart'; -import '../util/helpers.dart'; import 'source_library_builder.dart' show SourceLibraryBuilder; import 'source_loader.dart'; @@ -335,9 +334,7 @@ inConstFields: inConstFields); } - void buildOutlineExpressions( - ClassHierarchy classHierarchy, - List<DelayedActionPerformer> delayedActionPerformers, + void buildOutlineExpressions(ClassHierarchy classHierarchy, List<DelayedDefaultValueCloner> delayedDefaultValueCloners) { MetadataBuilder.buildAnnotations( typedef, @@ -358,7 +355,6 @@ inMetadata: true, inConstFields: false), classHierarchy, - delayedActionPerformers, computeTypeParameterScope(libraryBuilder.scope)); } }
diff --git a/pkg/front_end/lib/src/type_inference/inference_helper.dart b/pkg/front_end/lib/src/type_inference/inference_helper.dart index 8899b9f..71089c2 100644 --- a/pkg/front_end/lib/src/type_inference/inference_helper.dart +++ b/pkg/front_end/lib/src/type_inference/inference_helper.dart
@@ -5,6 +5,7 @@ import 'package:kernel/ast.dart'; import '../codes/cfe_codes.dart' show LocatedMessage, Message; +import '../kernel/internal_ast.dart'; abstract class InferenceHelper { Uri get uri; @@ -28,4 +29,13 @@ String superConstructorNameForDiagnostics(String name); String constructorNameForDiagnostics(String name, {String? className}); + + Expression unaliasSingleTypeAliasedConstructorInvocation( + TypeAliasedConstructorInvocation invocation); + + Expression? resolveRedirectingFactoryTarget( + Procedure target, Arguments arguments, int fileOffset, bool isConst); + + Expression? unaliasSingleTypeAliasedFactoryInvocation( + TypeAliasedFactoryInvocation invocation); }
diff --git a/pkg/front_end/lib/src/type_inference/inference_visitor.dart b/pkg/front_end/lib/src/type_inference/inference_visitor.dart index 20a1c62..1dab4ce 100644 --- a/pkg/front_end/lib/src/type_inference/inference_visitor.dart +++ b/pkg/front_end/lib/src/type_inference/inference_visitor.dart
@@ -1415,15 +1415,17 @@ isConst: node.isConst, staticTarget: node.target); node.hasBeenInferred = true; - Expression resultNode = node; SourceLibraryBuilder library = libraryBuilder; if (!hadExplicitTypeArguments) { library.checkBoundsInFactoryInvocation( node, typeSchemaEnvironment, helper.uri, inferred: true); } - return new ExpressionInferenceResult( - result.inferredType, result.applyResult(resultNode)); + Expression resolvedExpression = helper.resolveRedirectingFactoryTarget( + node.target, node.arguments, node.fileOffset, node.isConst)!; + Expression resultExpression = result.applyResult(resolvedExpression); + + return new ExpressionInferenceResult(result.inferredType, resultExpression); } /// Returns the function type of [constructor] when called through [typedef]. @@ -1481,10 +1483,13 @@ isConst: node.isConst, staticTarget: node.target); node.hasBeenInferred = true; - Expression resultNode = node; + + Expression resolvedExpression = + helper.unaliasSingleTypeAliasedConstructorInvocation(node); + Expression resultingExpression = result.applyResult(resolvedExpression); return new ExpressionInferenceResult( - result.inferredType, result.applyResult(resultNode)); + result.inferredType, resultingExpression); } /// Returns the function type of [factory] when called through [typedef]. @@ -1547,10 +1552,13 @@ node.arguments as ArgumentsImpl, isConst: node.isConst, staticTarget: node.target); + + Expression resolvedExpression = + helper.unaliasSingleTypeAliasedFactoryInvocation(node)!; + Expression resultExpression = result.applyResult(resolvedExpression); + node.hasBeenInferred = true; - Expression resultNode = node; - return new ExpressionInferenceResult( - result.inferredType, result.applyResult(resultNode)); + return new ExpressionInferenceResult(result.inferredType, resultExpression); } @override
diff --git a/pkg/front_end/lib/src/util/helpers.dart b/pkg/front_end/lib/src/util/helpers.dart index b3eb4d5..07ce19c 100644 --- a/pkg/front_end/lib/src/util/helpers.dart +++ b/pkg/front_end/lib/src/util/helpers.dart
@@ -7,10 +7,6 @@ import '../api_prototype/experimental_flags.dart'; import '../source/source_library_builder.dart'; -abstract class DelayedActionPerformer { - void performDelayedActions({required bool allowFurtherDelays}); -} - /// Returns `true` if access to `Record` from `dart:core` is allowed. bool isRecordAccessAllowed(SourceLibraryBuilder library) { return library
diff --git a/pkg/front_end/test/coverage_suite_expected.dart b/pkg/front_end/test/coverage_suite_expected.dart index f714809..9e7a7a3 100644 --- a/pkg/front_end/test/coverage_suite_expected.dart +++ b/pkg/front_end/test/coverage_suite_expected.dart
@@ -285,7 +285,7 @@ ), // 100.0%. "package:front_end/src/builder/formal_parameter_builder.dart": ( - hitCount: 188, + hitCount: 186, missCount: 0, ), // 100.0%. @@ -478,15 +478,15 @@ hitCount: 0, missCount: 0, ), - // 99.34556835965287%. + // 99.14393499709809%. "package:front_end/src/kernel/body_builder.dart": ( - hitCount: 6983, - missCount: 46, + hitCount: 6833, + missCount: 59, ), - // 100.0%. + // 98.26086956521739%. "package:front_end/src/kernel/body_builder_context.dart": ( - hitCount: 345, - missCount: 0, + hitCount: 339, + missCount: 6, ), // 81.57894736842105%. "package:front_end/src/kernel/collections.dart": ( @@ -598,10 +598,10 @@ hitCount: 1, missCount: 0, ), - // 100.0%. + // 99.12126537785588%. "package:front_end/src/kernel/internal_ast.dart": ( - hitCount: 569, - missCount: 0, + hitCount: 564, + missCount: 5, ), // 100.0%. "package:front_end/src/kernel/invalid_type.dart": ( @@ -618,9 +618,9 @@ hitCount: 285, missCount: 0, ), - // 99.90521327014218%. + // 99.90566037735849%. "package:front_end/src/kernel/kernel_target.dart": ( - hitCount: 1054, + hitCount: 1059, missCount: 1, ), // 100.0%. @@ -790,7 +790,7 @@ ), // 100.0%. "package:front_end/src/source/source_builder_factory.dart": ( - hitCount: 1163, + hitCount: 1167, missCount: 0, ), // 98.13664596273291%. @@ -808,14 +808,14 @@ hitCount: 741, missCount: 4, ), - // 98.31271091113611%. + // 98.31649831649831%. "package:front_end/src/source/source_constructor_builder.dart": ( - hitCount: 874, + hitCount: 876, missCount: 15, ), - // 99.81203007518798%. + // 99.81024667931689%. "package:front_end/src/source/source_enum_builder.dart": ( - hitCount: 531, + hitCount: 526, missCount: 1, ), // 100.0%. @@ -831,7 +831,7 @@ ), // 100.0%. "package:front_end/src/source/source_factory_builder.dart": ( - hitCount: 576, + hitCount: 583, missCount: 0, ), // 100.0%. @@ -849,9 +849,9 @@ hitCount: 1419, missCount: 2, ), - // 99.89258861439313%. + // 99.89253089736701%. "package:front_end/src/source/source_loader.dart": ( - hitCount: 1860, + hitCount: 1859, missCount: 2, ), // 100.0%. @@ -874,9 +874,9 @@ hitCount: 20, missCount: 0, ), - // 99.09909909909909%. + // 99.00497512437812%. "package:front_end/src/source/type_parameter_scope_builder.dart": ( - hitCount: 220, + hitCount: 199, missCount: 2, ), // 100.0%. @@ -909,9 +909,9 @@ hitCount: 166, missCount: 0, ), - // 99.51504600845561%. + // 99.51564828614009%. "package:front_end/src/type_inference/inference_visitor.dart": ( - hitCount: 8003, + hitCount: 8013, missCount: 39, ), // 99.875%. @@ -961,7 +961,7 @@ ), // 100.0%. "package:front_end/src/type_inference/type_inferrer.dart": ( - hitCount: 88, + hitCount: 96, missCount: 0, ), // 100.0%.
diff --git a/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.expect b/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.expect index 3d66491..f365b95 100644 --- a/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.expect +++ b/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.expect
@@ -16,6 +16,11 @@ // const newConst1 = new ExtensionType1(0); /* Error */ // ^^^ // +// pkg/front_end/testcases/extension_types/const_constructor_access.dart:9:23: Error: Cannot invoke a non-'const' constructor where a const expression is expected. +// Try using a constructor or factory that is 'const'. +// const newConst1 = new ExtensionType1(0); /* Error */ +// ^ +// // pkg/front_end/testcases/extension_types/const_constructor_access.dart:13:31: Error: Cannot invoke a non-'const' constructor where a const expression is expected. // Try using a constructor or factory that is 'const'. // const implicitConstAliased1 = Typedef1(0); /* Error */ @@ -30,6 +35,11 @@ // const newConstAliased1 = new Typedef1(0); /* Error */ // ^^^ // +// pkg/front_end/testcases/extension_types/const_constructor_access.dart:15:30: Error: Cannot invoke a non-'const' constructor where a const expression is expected. +// Try using a constructor or factory that is 'const'. +// const newConstAliased1 = new Typedef1(0); /* Error */ +// ^ +// // pkg/front_end/testcases/extension_types/const_constructor_access.dart:21:19: Error: New expression is not a constant expression. // const newConst2 = new ExtensionType2(0); /* Error */ // ^^^ @@ -38,16 +48,6 @@ // const newConstAliased2 = new Typedef2(0); /* Error */ // ^^^ // -// pkg/front_end/testcases/extension_types/const_constructor_access.dart:9:23: Error: Cannot invoke a non-'const' constructor where a const expression is expected. -// Try using a constructor or factory that is 'const'. -// const newConst1 = new ExtensionType1(0); /* Error */ -// ^ -// -// pkg/front_end/testcases/extension_types/const_constructor_access.dart:15:30: Error: Cannot invoke a non-'const' constructor where a const expression is expected. -// Try using a constructor or factory that is 'const'. -// const newConstAliased1 = new Typedef1(0); /* Error */ -// ^ -// import self as self; import "dart:core" as core;
diff --git a/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.modular.expect b/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.modular.expect index 3d66491..f365b95 100644 --- a/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.modular.expect +++ b/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.modular.expect
@@ -16,6 +16,11 @@ // const newConst1 = new ExtensionType1(0); /* Error */ // ^^^ // +// pkg/front_end/testcases/extension_types/const_constructor_access.dart:9:23: Error: Cannot invoke a non-'const' constructor where a const expression is expected. +// Try using a constructor or factory that is 'const'. +// const newConst1 = new ExtensionType1(0); /* Error */ +// ^ +// // pkg/front_end/testcases/extension_types/const_constructor_access.dart:13:31: Error: Cannot invoke a non-'const' constructor where a const expression is expected. // Try using a constructor or factory that is 'const'. // const implicitConstAliased1 = Typedef1(0); /* Error */ @@ -30,6 +35,11 @@ // const newConstAliased1 = new Typedef1(0); /* Error */ // ^^^ // +// pkg/front_end/testcases/extension_types/const_constructor_access.dart:15:30: Error: Cannot invoke a non-'const' constructor where a const expression is expected. +// Try using a constructor or factory that is 'const'. +// const newConstAliased1 = new Typedef1(0); /* Error */ +// ^ +// // pkg/front_end/testcases/extension_types/const_constructor_access.dart:21:19: Error: New expression is not a constant expression. // const newConst2 = new ExtensionType2(0); /* Error */ // ^^^ @@ -38,16 +48,6 @@ // const newConstAliased2 = new Typedef2(0); /* Error */ // ^^^ // -// pkg/front_end/testcases/extension_types/const_constructor_access.dart:9:23: Error: Cannot invoke a non-'const' constructor where a const expression is expected. -// Try using a constructor or factory that is 'const'. -// const newConst1 = new ExtensionType1(0); /* Error */ -// ^ -// -// pkg/front_end/testcases/extension_types/const_constructor_access.dart:15:30: Error: Cannot invoke a non-'const' constructor where a const expression is expected. -// Try using a constructor or factory that is 'const'. -// const newConstAliased1 = new Typedef1(0); /* Error */ -// ^ -// import self as self; import "dart:core" as core;
diff --git a/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.outline.expect b/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.outline.expect index a0f936d..d17b68f 100644 --- a/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.outline.expect +++ b/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.outline.expect
@@ -16,6 +16,11 @@ // const newConst1 = new ExtensionType1(0); /* Error */ // ^^^ // +// pkg/front_end/testcases/extension_types/const_constructor_access.dart:9:23: Error: Cannot invoke a non-'const' constructor where a const expression is expected. +// Try using a constructor or factory that is 'const'. +// const newConst1 = new ExtensionType1(0); /* Error */ +// ^ +// // pkg/front_end/testcases/extension_types/const_constructor_access.dart:13:31: Error: Cannot invoke a non-'const' constructor where a const expression is expected. // Try using a constructor or factory that is 'const'. // const implicitConstAliased1 = Typedef1(0); /* Error */ @@ -30,6 +35,11 @@ // const newConstAliased1 = new Typedef1(0); /* Error */ // ^^^ // +// pkg/front_end/testcases/extension_types/const_constructor_access.dart:15:30: Error: Cannot invoke a non-'const' constructor where a const expression is expected. +// Try using a constructor or factory that is 'const'. +// const newConstAliased1 = new Typedef1(0); /* Error */ +// ^ +// // pkg/front_end/testcases/extension_types/const_constructor_access.dart:21:19: Error: New expression is not a constant expression. // const newConst2 = new ExtensionType2(0); /* Error */ // ^^^ @@ -38,16 +48,6 @@ // const newConstAliased2 = new Typedef2(0); /* Error */ // ^^^ // -// pkg/front_end/testcases/extension_types/const_constructor_access.dart:9:23: Error: Cannot invoke a non-'const' constructor where a const expression is expected. -// Try using a constructor or factory that is 'const'. -// const newConst1 = new ExtensionType1(0); /* Error */ -// ^ -// -// pkg/front_end/testcases/extension_types/const_constructor_access.dart:15:30: Error: Cannot invoke a non-'const' constructor where a const expression is expected. -// Try using a constructor or factory that is 'const'. -// const newConstAliased1 = new Typedef1(0); /* Error */ -// ^ -// import self as self; import "dart:core" as core;
diff --git a/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.transformed.expect index 3d66491..f365b95 100644 --- a/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/extension_types/const_constructor_access.dart.strong.transformed.expect
@@ -16,6 +16,11 @@ // const newConst1 = new ExtensionType1(0); /* Error */ // ^^^ // +// pkg/front_end/testcases/extension_types/const_constructor_access.dart:9:23: Error: Cannot invoke a non-'const' constructor where a const expression is expected. +// Try using a constructor or factory that is 'const'. +// const newConst1 = new ExtensionType1(0); /* Error */ +// ^ +// // pkg/front_end/testcases/extension_types/const_constructor_access.dart:13:31: Error: Cannot invoke a non-'const' constructor where a const expression is expected. // Try using a constructor or factory that is 'const'. // const implicitConstAliased1 = Typedef1(0); /* Error */ @@ -30,6 +35,11 @@ // const newConstAliased1 = new Typedef1(0); /* Error */ // ^^^ // +// pkg/front_end/testcases/extension_types/const_constructor_access.dart:15:30: Error: Cannot invoke a non-'const' constructor where a const expression is expected. +// Try using a constructor or factory that is 'const'. +// const newConstAliased1 = new Typedef1(0); /* Error */ +// ^ +// // pkg/front_end/testcases/extension_types/const_constructor_access.dart:21:19: Error: New expression is not a constant expression. // const newConst2 = new ExtensionType2(0); /* Error */ // ^^^ @@ -38,16 +48,6 @@ // const newConstAliased2 = new Typedef2(0); /* Error */ // ^^^ // -// pkg/front_end/testcases/extension_types/const_constructor_access.dart:9:23: Error: Cannot invoke a non-'const' constructor where a const expression is expected. -// Try using a constructor or factory that is 'const'. -// const newConst1 = new ExtensionType1(0); /* Error */ -// ^ -// -// pkg/front_end/testcases/extension_types/const_constructor_access.dart:15:30: Error: Cannot invoke a non-'const' constructor where a const expression is expected. -// Try using a constructor or factory that is 'const'. -// const newConstAliased1 = new Typedef1(0); /* Error */ -// ^ -// import self as self; import "dart:core" as core;
diff --git a/pkg/front_end/testcases/general/bounds_instances.dart.strong.expect b/pkg/front_end/testcases/general/bounds_instances.dart.strong.expect index 10849bb..0e07d33a 100644 --- a/pkg/front_end/testcases/general/bounds_instances.dart.strong.expect +++ b/pkg/front_end/testcases/general/bounds_instances.dart.strong.expect
@@ -94,6 +94,16 @@ // class G<X extends Class<X>> {} // ^ // +// pkg/front_end/testcases/general/bounds_instances.dart:16:7: Error: Inferred type argument 'Class<Object?>' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'F'. +// - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// new F(); // Error +// ^ +// pkg/front_end/testcases/general/bounds_instances.dart:9:11: Context: This is the type variable whose bound isn't conformed to. +// typedef F<X extends Class<X>> = Class1; +// ^ +// // pkg/front_end/testcases/general/bounds_instances.dart:24:7: Error: Inferred type argument 'Class<Object?>' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'G'. // - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'. // - 'Object' is from 'dart:core'. @@ -140,16 +150,6 @@ // G<int>.new; // Error // ^ // -// pkg/front_end/testcases/general/bounds_instances.dart:16:7: Error: Inferred type argument 'Class<Object?>' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'F'. -// - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// new F(); // Error -// ^ -// pkg/front_end/testcases/general/bounds_instances.dart:9:11: Context: This is the type variable whose bound isn't conformed to. -// typedef F<X extends Class<X>> = Class1; -// ^ -// // pkg/front_end/testcases/general/bounds_instances.dart:39:3: Error: Type argument 'Object' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'F'. // - 'Object' is from 'dart:core'. // - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'.
diff --git a/pkg/front_end/testcases/general/bounds_instances.dart.strong.modular.expect b/pkg/front_end/testcases/general/bounds_instances.dart.strong.modular.expect index 10849bb..0e07d33a 100644 --- a/pkg/front_end/testcases/general/bounds_instances.dart.strong.modular.expect +++ b/pkg/front_end/testcases/general/bounds_instances.dart.strong.modular.expect
@@ -94,6 +94,16 @@ // class G<X extends Class<X>> {} // ^ // +// pkg/front_end/testcases/general/bounds_instances.dart:16:7: Error: Inferred type argument 'Class<Object?>' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'F'. +// - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// new F(); // Error +// ^ +// pkg/front_end/testcases/general/bounds_instances.dart:9:11: Context: This is the type variable whose bound isn't conformed to. +// typedef F<X extends Class<X>> = Class1; +// ^ +// // pkg/front_end/testcases/general/bounds_instances.dart:24:7: Error: Inferred type argument 'Class<Object?>' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'G'. // - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'. // - 'Object' is from 'dart:core'. @@ -140,16 +150,6 @@ // G<int>.new; // Error // ^ // -// pkg/front_end/testcases/general/bounds_instances.dart:16:7: Error: Inferred type argument 'Class<Object?>' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'F'. -// - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// new F(); // Error -// ^ -// pkg/front_end/testcases/general/bounds_instances.dart:9:11: Context: This is the type variable whose bound isn't conformed to. -// typedef F<X extends Class<X>> = Class1; -// ^ -// // pkg/front_end/testcases/general/bounds_instances.dart:39:3: Error: Type argument 'Object' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'F'. // - 'Object' is from 'dart:core'. // - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'.
diff --git a/pkg/front_end/testcases/general/bounds_instances.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bounds_instances.dart.strong.transformed.expect index 10849bb..0e07d33a 100644 --- a/pkg/front_end/testcases/general/bounds_instances.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/general/bounds_instances.dart.strong.transformed.expect
@@ -94,6 +94,16 @@ // class G<X extends Class<X>> {} // ^ // +// pkg/front_end/testcases/general/bounds_instances.dart:16:7: Error: Inferred type argument 'Class<Object?>' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'F'. +// - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// new F(); // Error +// ^ +// pkg/front_end/testcases/general/bounds_instances.dart:9:11: Context: This is the type variable whose bound isn't conformed to. +// typedef F<X extends Class<X>> = Class1; +// ^ +// // pkg/front_end/testcases/general/bounds_instances.dart:24:7: Error: Inferred type argument 'Class<Object?>' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'G'. // - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'. // - 'Object' is from 'dart:core'. @@ -140,16 +150,6 @@ // G<int>.new; // Error // ^ // -// pkg/front_end/testcases/general/bounds_instances.dart:16:7: Error: Inferred type argument 'Class<Object?>' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'F'. -// - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// new F(); // Error -// ^ -// pkg/front_end/testcases/general/bounds_instances.dart:9:11: Context: This is the type variable whose bound isn't conformed to. -// typedef F<X extends Class<X>> = Class1; -// ^ -// // pkg/front_end/testcases/general/bounds_instances.dart:39:3: Error: Type argument 'Object' doesn't conform to the bound 'Class<X>' of the type variable 'X' on 'F'. // - 'Object' is from 'dart:core'. // - 'Class' is from 'pkg/front_end/testcases/general/bounds_instances.dart'.
diff --git a/pkg/front_end/testcases/general/constructor_inference_interdependence.dart b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart new file mode 100644 index 0000000..cd9eabd --- /dev/null +++ b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart
@@ -0,0 +1,22 @@ +// Copyright (c) 2024, 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 C {} + +sealed class B<X> { + final C? Function()? foo; + const B({required this.foo}); + + const factory B.redir({C? Function()? foo}) = A; +} + +mixin M {} + +final class A<X> extends B<X> with M { + const A({super.foo = null}) : super(); +} + +main() { + print(new A()); +}
diff --git a/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.expect b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.expect new file mode 100644 index 0000000..0db728b --- /dev/null +++ b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.expect
@@ -0,0 +1,36 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + synthetic constructor •() → self::C + : super core::Object::•() + ; +} +abstract sealed class B<X extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ { + final field () →? self::C? foo; + const constructor •({required () →? self::C? foo}) → self::B<self::B::X%> + : self::B::foo = foo, super core::Object::•() + ; + static factory redir<X extends core::Object? = dynamic>({() →? self::C? foo = #C1}) → self::B<self::B::redir::X%> /* redirection-target: self::A::•<self::B::redir::X%>*/ + return new self::A::•<self::B::redir::X%>(foo: foo); +} +abstract class M extends core::Object /*isMixinDeclaration*/ { +} +abstract sealed class _A&B&M<X extends core::Object? = dynamic> = self::B<self::_A&B&M::X%> with self::M /*isAnonymousMixin,hasConstConstructor*/ { + const synthetic constructor •({required () →? self::C? foo}) → self::_A&B&M<self::_A&B&M::X%> + : super self::B::•(foo: foo) + ; +} +final class A<X extends core::Object? = dynamic> extends self::_A&B&M<self::A::X%> /*hasConstConstructor*/ { + const constructor •({has-declared-initializer () →? self::C? foo = #C1}) → self::A<self::A::X%> + : super self::_A&B&M::•(foo: foo) + ; +} +static method main() → dynamic { + core::print(new self::A::•<dynamic>()); +} + +constants { + #C1 = null +}
diff --git a/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.modular.expect b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.modular.expect new file mode 100644 index 0000000..0db728b --- /dev/null +++ b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.modular.expect
@@ -0,0 +1,36 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + synthetic constructor •() → self::C + : super core::Object::•() + ; +} +abstract sealed class B<X extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ { + final field () →? self::C? foo; + const constructor •({required () →? self::C? foo}) → self::B<self::B::X%> + : self::B::foo = foo, super core::Object::•() + ; + static factory redir<X extends core::Object? = dynamic>({() →? self::C? foo = #C1}) → self::B<self::B::redir::X%> /* redirection-target: self::A::•<self::B::redir::X%>*/ + return new self::A::•<self::B::redir::X%>(foo: foo); +} +abstract class M extends core::Object /*isMixinDeclaration*/ { +} +abstract sealed class _A&B&M<X extends core::Object? = dynamic> = self::B<self::_A&B&M::X%> with self::M /*isAnonymousMixin,hasConstConstructor*/ { + const synthetic constructor •({required () →? self::C? foo}) → self::_A&B&M<self::_A&B&M::X%> + : super self::B::•(foo: foo) + ; +} +final class A<X extends core::Object? = dynamic> extends self::_A&B&M<self::A::X%> /*hasConstConstructor*/ { + const constructor •({has-declared-initializer () →? self::C? foo = #C1}) → self::A<self::A::X%> + : super self::_A&B&M::•(foo: foo) + ; +} +static method main() → dynamic { + core::print(new self::A::•<dynamic>()); +} + +constants { + #C1 = null +}
diff --git a/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.outline.expect b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.outline.expect new file mode 100644 index 0000000..af6da57 --- /dev/null +++ b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.outline.expect
@@ -0,0 +1,30 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + synthetic constructor •() → self::C + ; +} +abstract sealed class B<X extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ { + final field () →? self::C? foo; + const constructor •({required () →? self::C? foo}) → self::B<self::B::X%> + : self::B::foo = foo, super core::Object::•() + ; + static factory redir<X extends core::Object? = dynamic>({() →? self::C? foo = null}) → self::B<self::B::redir::X%> /* redirection-target: self::A::•<self::B::redir::X%>*/ + return new self::A::•<self::B::redir::X%>(foo: foo); +} +abstract class M extends core::Object /*isMixinDeclaration*/ { +} +abstract sealed class _A&B&M<X extends core::Object? = dynamic> = self::B<self::_A&B&M::X%> with self::M /*isAnonymousMixin,hasConstConstructor*/ { + const synthetic constructor •({required () →? self::C? foo}) → self::_A&B&M<self::_A&B&M::X%> + : super self::B::•(foo: foo) + ; +} +final class A<X extends core::Object? = dynamic> extends self::_A&B&M<self::A::X%> /*hasConstConstructor*/ { + const constructor •({has-declared-initializer () →? self::C? foo = null}) → self::A<self::A::X%> + : super self::_A&B&M::•(foo: foo) + ; +} +static method main() → dynamic + ;
diff --git a/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.transformed.expect new file mode 100644 index 0000000..b0993ad --- /dev/null +++ b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.strong.transformed.expect
@@ -0,0 +1,36 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + synthetic constructor •() → self::C + : super core::Object::•() + ; +} +abstract sealed class B<X extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/ { + final field () →? self::C? foo; + const constructor •({required () →? self::C? foo}) → self::B<self::B::X%> + : self::B::foo = foo, super core::Object::•() + ; + static factory redir<X extends core::Object? = dynamic>({() →? self::C? foo = #C1}) → self::B<self::B::redir::X%> /* redirection-target: self::A::•<self::B::redir::X%>*/ + return new self::A::•<self::B::redir::X%>(foo: foo); +} +abstract class M extends core::Object /*isMixinDeclaration*/ { +} +abstract sealed class _A&B&M<X extends core::Object? = dynamic> extends self::B<self::_A&B&M::X%> implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/ { + const synthetic constructor •({required () →? self::C? foo}) → self::_A&B&M<self::_A&B&M::X%> + : super self::B::•(foo: foo) + ; +} +final class A<X extends core::Object? = dynamic> extends self::_A&B&M<self::A::X%> /*hasConstConstructor*/ { + const constructor •({has-declared-initializer () →? self::C? foo = #C1}) → self::A<self::A::X%> + : super self::_A&B&M::•(foo: foo) + ; +} +static method main() → dynamic { + core::print(new self::A::•<dynamic>()); +} + +constants { + #C1 = null +}
diff --git a/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.textual_outline.expect b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.textual_outline.expect new file mode 100644 index 0000000..dc73668 --- /dev/null +++ b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.textual_outline.expect
@@ -0,0 +1,15 @@ +class C {} + +sealed class B<X> { + final C? Function()? foo; + const B({required this.foo}); + const factory B.redir({C? Function()? foo}) = A; +} + +mixin M {} + +final class A<X> extends B<X> with M { + const A({super.foo = null}) : super(); +} + +main() {}
diff --git a/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.textual_outline_modelled.expect new file mode 100644 index 0000000..8c1259b --- /dev/null +++ b/pkg/front_end/testcases/general/constructor_inference_interdependence.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@ +class C {} + +final class A<X> extends B<X> with M { + const A({super.foo = null}) : super(); +} + +main() {} + +mixin M {} + +sealed class B<X> { + const B({required this.foo}); + const factory B.redir({C? Function()? foo}) = A; + final C? Function()? foo; +}
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart new file mode 100644 index 0000000..cad4e75 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart
@@ -0,0 +1,16 @@ +// Copyright (c) 2024, 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 C { + List<A> field; + C({this.field = const [A.redir()]}); +} + +abstract class A { + const factory A.redir() = B; +} + +class B<X> implements A { + const B(); +}
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.expect new file mode 100644 index 0000000..2d6194a --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.expect
@@ -0,0 +1,30 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A> field; + constructor •({core::List<self::A> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; +} +abstract class A extends core::Object { + static factory redir() → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(); +} +class B<X extends core::Object? = dynamic> extends core::Object implements self::A /*hasConstConstructor*/ { + const constructor •() → self::B<self::B::X%> + : super core::Object::•() + ; +} + +constants { + #C1 = self::B<dynamic> {} + #C2 = <self::A>[#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///redirecting_constructors_declaration_order.dart: +- B. (from org-dartlang-testcase:///redirecting_constructors_declaration_order.dart:15:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.modular.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.modular.expect new file mode 100644 index 0000000..2d6194a --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.modular.expect
@@ -0,0 +1,30 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A> field; + constructor •({core::List<self::A> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; +} +abstract class A extends core::Object { + static factory redir() → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(); +} +class B<X extends core::Object? = dynamic> extends core::Object implements self::A /*hasConstConstructor*/ { + const constructor •() → self::B<self::B::X%> + : super core::Object::•() + ; +} + +constants { + #C1 = self::B<dynamic> {} + #C2 = <self::A>[#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///redirecting_constructors_declaration_order.dart: +- B. (from org-dartlang-testcase:///redirecting_constructors_declaration_order.dart:15:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.outline.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.outline.expect new file mode 100644 index 0000000..b288ecc --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.outline.expect
@@ -0,0 +1,23 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A> field; + constructor •({core::List<self::A> field = const <self::A>[const self::B::•<dynamic>()]}) → self::C + ; +} +abstract class A extends core::Object { + static factory redir() → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(); +} +class B<X extends core::Object? = dynamic> extends core::Object implements self::A /*hasConstConstructor*/ { + const constructor •() → self::B<self::B::X%> + : super core::Object::•() + ; +} + + +Extra constant evaluation status: +Evaluated: ListLiteral @ org-dartlang-testcase:///redirecting_constructors_declaration_order.dart:7:19 -> ListConstant(const <A>[const B<dynamic>{}]) +Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.transformed.expect new file mode 100644 index 0000000..2d6194a --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.strong.transformed.expect
@@ -0,0 +1,30 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A> field; + constructor •({core::List<self::A> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; +} +abstract class A extends core::Object { + static factory redir() → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(); +} +class B<X extends core::Object? = dynamic> extends core::Object implements self::A /*hasConstConstructor*/ { + const constructor •() → self::B<self::B::X%> + : super core::Object::•() + ; +} + +constants { + #C1 = self::B<dynamic> {} + #C2 = <self::A>[#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///redirecting_constructors_declaration_order.dart: +- B. (from org-dartlang-testcase:///redirecting_constructors_declaration_order.dart:15:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.textual_outline.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.textual_outline.expect new file mode 100644 index 0000000..3ce5bdc --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.textual_outline.expect
@@ -0,0 +1,12 @@ +class C { + List<A> field; + C({this.field = const [A.redir()]}); +} + +abstract class A { + const factory A.redir() = B; +} + +class B<X> implements A { + const B(); +}
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.textual_outline_modelled.expect new file mode 100644 index 0000000..0d599f9 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@ +abstract class A { + const factory A.redir() = B; +} + +class B<X> implements A { + const B(); +} + +class C { + C({this.field = const [A.redir()]}); + List<A> field; +}
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart new file mode 100644 index 0000000..4d57560 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart
@@ -0,0 +1,23 @@ +// Copyright (c) 2024, 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 C { + List<A> field; + C.named1({this.field = const [A.redir1(0, s: "")]}); + C.named2({this.field = const [A.redir1(s: "", 0)]}); +} + +abstract class A { + const factory A.redir1(int x, {required String s}) = B; + const factory A.redir2(int x, {required String s}) = B; +} + +class B<X> implements A { + const B(int x, {required String s}); +} + +test() { + new A.redir2(0, s: ""); + new A.redir2(s: "", 0); +}
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.expect new file mode 100644 index 0000000..8db2dcf --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.expect
@@ -0,0 +1,39 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A> field; + constructor named1({core::List<self::A> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; + constructor named2({core::List<self::A> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; +} +abstract class A extends core::Object { + static factory redir1(core::int x, {required core::String s}) → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(x, s: s); + static factory redir2(core::int x, {required core::String s}) → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(x, s: s); +} +class B<X extends core::Object? = dynamic> extends core::Object implements self::A /*hasConstConstructor*/ { + const constructor •(core::int x, {required core::String s}) → self::B<self::B::X%> + : super core::Object::•() + ; +} +static method test() → dynamic { + new self::B::•<dynamic>(0, s: ""); + let final core::String #t1 = "" in new self::B::•<dynamic>(0, s: #t1); +} + +constants { + #C1 = self::B<dynamic> {} + #C2 = <self::A>[#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///redirecting_constructors_declaration_order_2.dart: +- B. (from org-dartlang-testcase:///redirecting_constructors_declaration_order_2.dart:17:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.modular.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.modular.expect new file mode 100644 index 0000000..8db2dcf --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.modular.expect
@@ -0,0 +1,39 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A> field; + constructor named1({core::List<self::A> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; + constructor named2({core::List<self::A> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; +} +abstract class A extends core::Object { + static factory redir1(core::int x, {required core::String s}) → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(x, s: s); + static factory redir2(core::int x, {required core::String s}) → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(x, s: s); +} +class B<X extends core::Object? = dynamic> extends core::Object implements self::A /*hasConstConstructor*/ { + const constructor •(core::int x, {required core::String s}) → self::B<self::B::X%> + : super core::Object::•() + ; +} +static method test() → dynamic { + new self::B::•<dynamic>(0, s: ""); + let final core::String #t1 = "" in new self::B::•<dynamic>(0, s: #t1); +} + +constants { + #C1 = self::B<dynamic> {} + #C2 = <self::A>[#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///redirecting_constructors_declaration_order_2.dart: +- B. (from org-dartlang-testcase:///redirecting_constructors_declaration_order_2.dart:17:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.outline.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.outline.expect new file mode 100644 index 0000000..f58b613 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.outline.expect
@@ -0,0 +1,30 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A> field; + constructor named1({core::List<self::A> field = const <self::A>[const self::B::•<dynamic>(0, s: "")]}) → self::C + ; + constructor named2({core::List<self::A> field = const <self::A>[const self::B::•<dynamic>(0, s: "")]}) → self::C + ; +} +abstract class A extends core::Object { + static factory redir1(core::int x, {required core::String s}) → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(x, s: s); + static factory redir2(core::int x, {required core::String s}) → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(x, s: s); +} +class B<X extends core::Object? = dynamic> extends core::Object implements self::A /*hasConstConstructor*/ { + const constructor •(core::int x, {required core::String s}) → self::B<self::B::X%> + : super core::Object::•() + ; +} +static method test() → dynamic + ; + + +Extra constant evaluation status: +Evaluated: ListLiteral @ org-dartlang-testcase:///redirecting_constructors_declaration_order_2.dart:7:26 -> ListConstant(const <A>[const B<dynamic>{}]) +Evaluated: ListLiteral @ org-dartlang-testcase:///redirecting_constructors_declaration_order_2.dart:8:26 -> ListConstant(const <A>[const B<dynamic>{}]) +Extra constant evaluation: evaluated: 8, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.transformed.expect new file mode 100644 index 0000000..105c064 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.strong.transformed.expect
@@ -0,0 +1,43 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A> field; + constructor named1({core::List<self::A> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; + constructor named2({core::List<self::A> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; +} +abstract class A extends core::Object { + static factory redir1(core::int x, {required core::String s}) → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(x, s: s); + static factory redir2(core::int x, {required core::String s}) → self::A /* redirection-target: self::B::•<dynamic>*/ + return new self::B::•<dynamic>(x, s: s); +} +class B<X extends core::Object? = dynamic> extends core::Object implements self::A /*hasConstConstructor*/ { + const constructor •(core::int x, {required core::String s}) → self::B<self::B::X%> + : super core::Object::•() + ; +} +static method test() → dynamic { + new self::B::•<dynamic>(0, s: ""); + let final core::String #t1 = "" in new self::B::•<dynamic>(0, s: #t1); +} + +constants { + #C1 = self::B<dynamic> {} + #C2 = <self::A>[#C1] +} + +Extra constant evaluation status: +Evaluated: VariableGet @ org-dartlang-testcase:///redirecting_constructors_declaration_order_2.dart:22:19 -> StringConstant("") +Extra constant evaluation: evaluated: 12, effectively constant: 1 + + +Constructor coverage from constants: +org-dartlang-testcase:///redirecting_constructors_declaration_order_2.dart: +- B. (from org-dartlang-testcase:///redirecting_constructors_declaration_order_2.dart:17:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.textual_outline.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.textual_outline.expect new file mode 100644 index 0000000..c262d64 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.textual_outline.expect
@@ -0,0 +1,16 @@ +class C { + List<A> field; + C.named1({this.field = const [A.redir1(0, s: "")]}); + C.named2({this.field = const [A.redir1(s: "", 0)]}); +} + +abstract class A { + const factory A.redir1(int x, {required String s}) = B; + const factory A.redir2(int x, {required String s}) = B; +} + +class B<X> implements A { + const B(int x, {required String s}); +} + +test() {}
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.textual_outline_modelled.expect new file mode 100644 index 0000000..606c5ac --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_2.dart.textual_outline_modelled.expect
@@ -0,0 +1,16 @@ +abstract class A { + const factory A.redir1(int x, {required String s}) = B; + const factory A.redir2(int x, {required String s}) = B; +} + +class B<X> implements A { + const B(int x, {required String s}); +} + +class C { + C.named1({this.field = const [A.redir1(0, s: "")]}); + C.named2({this.field = const [A.redir1(s: "", 0)]}); + List<A> field; +} + +test() {}
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart new file mode 100644 index 0000000..757e8d6 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart
@@ -0,0 +1,23 @@ +// Copyright (c) 2024, 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 C { + List<A<bool>> field; + C.named1({this.field = const [A.redir1(0, s: "")]}); + C.named2({this.field = const [A.redir1(s: "", 0)]}); +} + +abstract class A<X> { + const factory A.redir1(int x, {required String s}) = B; + const factory A.redir2(int x, {required String s}) = B; +} + +class B<Y> implements A<Y> { + const B(int x, {required String s}); +} + +test() { + A<String> foo1 = new A.redir2(0, s: ""); + A<num> foo2 = new A.redir2(s: "", 0); +}
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.expect new file mode 100644 index 0000000..61b3f85 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.expect
@@ -0,0 +1,39 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A<core::bool>> field; + constructor named1({core::List<self::A<core::bool>> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; + constructor named2({core::List<self::A<core::bool>> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; +} +abstract class A<X extends core::Object? = dynamic> extends core::Object { + static factory redir1<X extends core::Object? = dynamic>(core::int x, {required core::String s}) → self::A<self::A::redir1::X%> /* redirection-target: self::B::•<self::A::redir1::X%>*/ + return new self::B::•<self::A::redir1::X%>(x, s: s); + static factory redir2<X extends core::Object? = dynamic>(core::int x, {required core::String s}) → self::A<self::A::redir2::X%> /* redirection-target: self::B::•<self::A::redir2::X%>*/ + return new self::B::•<self::A::redir2::X%>(x, s: s); +} +class B<Y extends core::Object? = dynamic> extends core::Object implements self::A<self::B::Y%> /*hasConstConstructor*/ { + const constructor •(core::int x, {required core::String s}) → self::B<self::B::Y%> + : super core::Object::•() + ; +} +static method test() → dynamic { + self::A<core::String> foo1 = new self::B::•<core::String>(0, s: ""); + self::A<core::num> foo2 = let final core::String #t1 = "" in new self::B::•<core::num>(0, s: #t1); +} + +constants { + #C1 = self::B<core::bool> {} + #C2 = <self::A<core::bool>>[#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///redirecting_constructors_declaration_order_3.dart: +- B. (from org-dartlang-testcase:///redirecting_constructors_declaration_order_3.dart:17:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.modular.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.modular.expect new file mode 100644 index 0000000..61b3f85 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.modular.expect
@@ -0,0 +1,39 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A<core::bool>> field; + constructor named1({core::List<self::A<core::bool>> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; + constructor named2({core::List<self::A<core::bool>> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; +} +abstract class A<X extends core::Object? = dynamic> extends core::Object { + static factory redir1<X extends core::Object? = dynamic>(core::int x, {required core::String s}) → self::A<self::A::redir1::X%> /* redirection-target: self::B::•<self::A::redir1::X%>*/ + return new self::B::•<self::A::redir1::X%>(x, s: s); + static factory redir2<X extends core::Object? = dynamic>(core::int x, {required core::String s}) → self::A<self::A::redir2::X%> /* redirection-target: self::B::•<self::A::redir2::X%>*/ + return new self::B::•<self::A::redir2::X%>(x, s: s); +} +class B<Y extends core::Object? = dynamic> extends core::Object implements self::A<self::B::Y%> /*hasConstConstructor*/ { + const constructor •(core::int x, {required core::String s}) → self::B<self::B::Y%> + : super core::Object::•() + ; +} +static method test() → dynamic { + self::A<core::String> foo1 = new self::B::•<core::String>(0, s: ""); + self::A<core::num> foo2 = let final core::String #t1 = "" in new self::B::•<core::num>(0, s: #t1); +} + +constants { + #C1 = self::B<core::bool> {} + #C2 = <self::A<core::bool>>[#C1] +} + + +Constructor coverage from constants: +org-dartlang-testcase:///redirecting_constructors_declaration_order_3.dart: +- B. (from org-dartlang-testcase:///redirecting_constructors_declaration_order_3.dart:17:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.outline.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.outline.expect new file mode 100644 index 0000000..51200e0 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.outline.expect
@@ -0,0 +1,30 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A<core::bool>> field; + constructor named1({core::List<self::A<core::bool>> field = const <self::A<core::bool>>[const self::B::•<core::bool>(0, s: "")]}) → self::C + ; + constructor named2({core::List<self::A<core::bool>> field = const <self::A<core::bool>>[const self::B::•<core::bool>(0, s: "")]}) → self::C + ; +} +abstract class A<X extends core::Object? = dynamic> extends core::Object { + static factory redir1<X extends core::Object? = dynamic>(core::int x, {required core::String s}) → self::A<self::A::redir1::X%> /* redirection-target: self::B::•<self::A::redir1::X%>*/ + return new self::B::•<self::A::redir1::X%>(x, s: s); + static factory redir2<X extends core::Object? = dynamic>(core::int x, {required core::String s}) → self::A<self::A::redir2::X%> /* redirection-target: self::B::•<self::A::redir2::X%>*/ + return new self::B::•<self::A::redir2::X%>(x, s: s); +} +class B<Y extends core::Object? = dynamic> extends core::Object implements self::A<self::B::Y%> /*hasConstConstructor*/ { + const constructor •(core::int x, {required core::String s}) → self::B<self::B::Y%> + : super core::Object::•() + ; +} +static method test() → dynamic + ; + + +Extra constant evaluation status: +Evaluated: ListLiteral @ org-dartlang-testcase:///redirecting_constructors_declaration_order_3.dart:7:26 -> ListConstant(const <A<bool>>[const B<bool>{}]) +Evaluated: ListLiteral @ org-dartlang-testcase:///redirecting_constructors_declaration_order_3.dart:8:26 -> ListConstant(const <A<bool>>[const B<bool>{}]) +Extra constant evaluation: evaluated: 8, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.transformed.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.transformed.expect new file mode 100644 index 0000000..c1da56f --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.strong.transformed.expect
@@ -0,0 +1,43 @@ +library; +import self as self; +import "dart:core" as core; + +class C extends core::Object { + field core::List<self::A<core::bool>> field; + constructor named1({core::List<self::A<core::bool>> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; + constructor named2({core::List<self::A<core::bool>> field = #C2}) → self::C + : self::C::field = field, super core::Object::•() + ; +} +abstract class A<X extends core::Object? = dynamic> extends core::Object { + static factory redir1<X extends core::Object? = dynamic>(core::int x, {required core::String s}) → self::A<self::A::redir1::X%> /* redirection-target: self::B::•<self::A::redir1::X%>*/ + return new self::B::•<self::A::redir1::X%>(x, s: s); + static factory redir2<X extends core::Object? = dynamic>(core::int x, {required core::String s}) → self::A<self::A::redir2::X%> /* redirection-target: self::B::•<self::A::redir2::X%>*/ + return new self::B::•<self::A::redir2::X%>(x, s: s); +} +class B<Y extends core::Object? = dynamic> extends core::Object implements self::A<self::B::Y%> /*hasConstConstructor*/ { + const constructor •(core::int x, {required core::String s}) → self::B<self::B::Y%> + : super core::Object::•() + ; +} +static method test() → dynamic { + self::A<core::String> foo1 = new self::B::•<core::String>(0, s: ""); + self::A<core::num> foo2 = let final core::String #t1 = "" in new self::B::•<core::num>(0, s: #t1); +} + +constants { + #C1 = self::B<core::bool> {} + #C2 = <self::A<core::bool>>[#C1] +} + +Extra constant evaluation status: +Evaluated: VariableGet @ org-dartlang-testcase:///redirecting_constructors_declaration_order_3.dart:22:33 -> StringConstant("") +Extra constant evaluation: evaluated: 12, effectively constant: 1 + + +Constructor coverage from constants: +org-dartlang-testcase:///redirecting_constructors_declaration_order_3.dart: +- B. (from org-dartlang-testcase:///redirecting_constructors_declaration_order_3.dart:17:9) +- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart)
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.textual_outline.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.textual_outline.expect new file mode 100644 index 0000000..61ae9b7 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.textual_outline.expect
@@ -0,0 +1,16 @@ +class C { + List<A<bool>> field; + C.named1({this.field = const [A.redir1(0, s: "")]}); + C.named2({this.field = const [A.redir1(s: "", 0)]}); +} + +abstract class A<X> { + const factory A.redir1(int x, {required String s}) = B; + const factory A.redir2(int x, {required String s}) = B; +} + +class B<Y> implements A<Y> { + const B(int x, {required String s}); +} + +test() {}
diff --git a/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.textual_outline_modelled.expect new file mode 100644 index 0000000..63f11e2 --- /dev/null +++ b/pkg/front_end/testcases/general/redirecting_constructors_declaration_order_3.dart.textual_outline_modelled.expect
@@ -0,0 +1,16 @@ +abstract class A<X> { + const factory A.redir1(int x, {required String s}) = B; + const factory A.redir2(int x, {required String s}) = B; +} + +class B<Y> implements A<Y> { + const B(int x, {required String s}); +} + +class C { + C.named1({this.field = const [A.redir1(0, s: "")]}); + C.named2({this.field = const [A.redir1(s: "", 0)]}); + List<A<bool>> field; +} + +test() {}
diff --git a/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.expect index fb03960..adc5810 100644 --- a/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.expect +++ b/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.expect
@@ -163,16 +163,16 @@ // new T7(0); // Error // ^ // -// pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:63:10: Error: The argument type 'int' can't be assigned to the parameter type 'List<void Function<T>(T)>'. -// - 'List' is from 'dart:core'. -// new T7(0); // Error -// ^ -// // pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:59:7: Error: Generic function type 'void Function<T>(T)' inferred as a type argument. // Try providing a non-generic function type explicitly. // new T4(); // Error // ^ // +// pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:63:10: Error: The argument type 'int' can't be assigned to the parameter type 'List<void Function<T>(T)>'. +// - 'List' is from 'dart:core'. +// new T7(0); // Error +// ^ +// // pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:60:4: Error: Generic function type 'void Function<T>(T)' inferred as a type argument. // Try providing a non-generic function type explicitly. // <T4>[]; // Error
diff --git a/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.modular.expect b/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.modular.expect index fb03960..adc5810 100644 --- a/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.modular.expect +++ b/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.modular.expect
@@ -163,16 +163,16 @@ // new T7(0); // Error // ^ // -// pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:63:10: Error: The argument type 'int' can't be assigned to the parameter type 'List<void Function<T>(T)>'. -// - 'List' is from 'dart:core'. -// new T7(0); // Error -// ^ -// // pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:59:7: Error: Generic function type 'void Function<T>(T)' inferred as a type argument. // Try providing a non-generic function type explicitly. // new T4(); // Error // ^ // +// pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:63:10: Error: The argument type 'int' can't be assigned to the parameter type 'List<void Function<T>(T)>'. +// - 'List' is from 'dart:core'. +// new T7(0); // Error +// ^ +// // pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:60:4: Error: Generic function type 'void Function<T>(T)' inferred as a type argument. // Try providing a non-generic function type explicitly. // <T4>[]; // Error
diff --git a/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.transformed.expect index 6fe631c..9d18dd9 100644 --- a/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart.strong.transformed.expect
@@ -163,16 +163,16 @@ // new T7(0); // Error // ^ // -// pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:63:10: Error: The argument type 'int' can't be assigned to the parameter type 'List<void Function<T>(T)>'. -// - 'List' is from 'dart:core'. -// new T7(0); // Error -// ^ -// // pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:59:7: Error: Generic function type 'void Function<T>(T)' inferred as a type argument. // Try providing a non-generic function type explicitly. // new T4(); // Error // ^ // +// pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:63:10: Error: The argument type 'int' can't be assigned to the parameter type 'List<void Function<T>(T)>'. +// - 'List' is from 'dart:core'. +// new T7(0); // Error +// ^ +// // pkg/front_end/testcases/generic_metadata/alias_from_opt_in.dart:60:4: Error: Generic function type 'void Function<T>(T)' inferred as a type argument. // Try providing a non-generic function type explicitly. // <T4>[]; // Error
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.expect b/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.expect index 5dd8435..417b6fd 100644 --- a/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.expect +++ b/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.expect
@@ -2,26 +2,6 @@ // // Problems in library: // -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:15:3: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'A'. -// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:5:9: Context: This is the type variable whose bound isn't conformed to. -// class A<X extends A<X>> {} -// ^ -// -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:17:3: Error: Inferred type argument 'A2<Object?>' doesn't conform to the bound 'A2<X>' of the type variable 'X' on 'A2'. -// - 'A2' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A2(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:8:10: Context: This is the type variable whose bound isn't conformed to. -// class A2<X extends A2<X>> { -// ^ -// // pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:14:3: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'. // - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. // - 'Object' is from 'dart:core'. @@ -32,6 +12,16 @@ // typedef B<X extends A<X>> = A<X>; // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:15:3: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'A'. +// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:5:9: Context: This is the type variable whose bound isn't conformed to. +// class A<X extends A<X>> {} +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:16:3: Error: Inferred type argument 'A2<Object?>' doesn't conform to the bound 'A2<X>' of the type variable 'X' on 'B2'. // - 'A2' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. // - 'Object' is from 'dart:core'. @@ -52,6 +42,16 @@ // class A2<X extends A2<X>> { // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:17:3: Error: Inferred type argument 'A2<Object?>' doesn't conform to the bound 'A2<X>' of the type variable 'X' on 'A2'. +// - 'A2' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A2(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:8:10: Context: This is the type variable whose bound isn't conformed to. +// class A2<X extends A2<X>> { +// ^ +// import self as self; import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.modular.expect b/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.modular.expect index 5dd8435..417b6fd 100644 --- a/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.modular.expect +++ b/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.modular.expect
@@ -2,26 +2,6 @@ // // Problems in library: // -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:15:3: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'A'. -// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:5:9: Context: This is the type variable whose bound isn't conformed to. -// class A<X extends A<X>> {} -// ^ -// -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:17:3: Error: Inferred type argument 'A2<Object?>' doesn't conform to the bound 'A2<X>' of the type variable 'X' on 'A2'. -// - 'A2' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A2(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:8:10: Context: This is the type variable whose bound isn't conformed to. -// class A2<X extends A2<X>> { -// ^ -// // pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:14:3: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'. // - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. // - 'Object' is from 'dart:core'. @@ -32,6 +12,16 @@ // typedef B<X extends A<X>> = A<X>; // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:15:3: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'A'. +// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:5:9: Context: This is the type variable whose bound isn't conformed to. +// class A<X extends A<X>> {} +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:16:3: Error: Inferred type argument 'A2<Object?>' doesn't conform to the bound 'A2<X>' of the type variable 'X' on 'B2'. // - 'A2' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. // - 'Object' is from 'dart:core'. @@ -52,6 +42,16 @@ // class A2<X extends A2<X>> { // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:17:3: Error: Inferred type argument 'A2<Object?>' doesn't conform to the bound 'A2<X>' of the type variable 'X' on 'A2'. +// - 'A2' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A2(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:8:10: Context: This is the type variable whose bound isn't conformed to. +// class A2<X extends A2<X>> { +// ^ +// import self as self; import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.transformed.expect index 5dd8435..417b6fd 100644 --- a/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart.strong.transformed.expect
@@ -2,26 +2,6 @@ // // Problems in library: // -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:15:3: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'A'. -// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:5:9: Context: This is the type variable whose bound isn't conformed to. -// class A<X extends A<X>> {} -// ^ -// -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:17:3: Error: Inferred type argument 'A2<Object?>' doesn't conform to the bound 'A2<X>' of the type variable 'X' on 'A2'. -// - 'A2' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A2(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:8:10: Context: This is the type variable whose bound isn't conformed to. -// class A2<X extends A2<X>> { -// ^ -// // pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:14:3: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'. // - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. // - 'Object' is from 'dart:core'. @@ -32,6 +12,16 @@ // typedef B<X extends A<X>> = A<X>; // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:15:3: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'A'. +// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:5:9: Context: This is the type variable whose bound isn't conformed to. +// class A<X extends A<X>> {} +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:16:3: Error: Inferred type argument 'A2<Object?>' doesn't conform to the bound 'A2<X>' of the type variable 'X' on 'B2'. // - 'A2' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. // - 'Object' is from 'dart:core'. @@ -52,6 +42,16 @@ // class A2<X extends A2<X>> { // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:17:3: Error: Inferred type argument 'A2<Object?>' doesn't conform to the bound 'A2<X>' of the type variable 'X' on 'A2'. +// - 'A2' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A2(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue42446.dart:8:10: Context: This is the type variable whose bound isn't conformed to. +// class A2<X extends A2<X>> { +// ^ +// import self as self; import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.expect b/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.expect index 0f569e6..d001566 100644 --- a/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.expect +++ b/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.expect
@@ -12,6 +12,16 @@ // class A<X extends A<X>> {} // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:33:9: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'C'. +// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// new C(); +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:14:11: Context: This is the type variable whose bound isn't conformed to. +// typedef C<X extends A<X>> = A<X>; +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:34:7: Error: Inferred type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'call'. // - 'Object' is from 'dart:core'. // - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'. @@ -76,16 +86,6 @@ // instance2(() => captureTypeArgument()); // ^ // -// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:33:9: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'C'. -// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// new C(); -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:14:11: Context: This is the type variable whose bound isn't conformed to. -// typedef C<X extends A<X>> = A<X>; -// ^ -// // pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:47:11: Error: Inferred type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'Subclass.instance1'. // - 'Object' is from 'dart:core'. // - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'.
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.modular.expect b/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.modular.expect index 0f569e6..d001566 100644 --- a/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.modular.expect +++ b/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.modular.expect
@@ -12,6 +12,16 @@ // class A<X extends A<X>> {} // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:33:9: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'C'. +// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// new C(); +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:14:11: Context: This is the type variable whose bound isn't conformed to. +// typedef C<X extends A<X>> = A<X>; +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:34:7: Error: Inferred type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'call'. // - 'Object' is from 'dart:core'. // - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'. @@ -76,16 +86,6 @@ // instance2(() => captureTypeArgument()); // ^ // -// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:33:9: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'C'. -// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// new C(); -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:14:11: Context: This is the type variable whose bound isn't conformed to. -// typedef C<X extends A<X>> = A<X>; -// ^ -// // pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:47:11: Error: Inferred type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'Subclass.instance1'. // - 'Object' is from 'dart:core'. // - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'.
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.transformed.expect index 0f569e6..d001566 100644 --- a/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart.strong.transformed.expect
@@ -12,6 +12,16 @@ // class A<X extends A<X>> {} // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:33:9: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'C'. +// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// new C(); +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:14:11: Context: This is the type variable whose bound isn't conformed to. +// typedef C<X extends A<X>> = A<X>; +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:34:7: Error: Inferred type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'call'. // - 'Object' is from 'dart:core'. // - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'. @@ -76,16 +86,6 @@ // instance2(() => captureTypeArgument()); // ^ // -// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:33:9: Error: Inferred type argument 'A<Object?>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'C'. -// - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// new C(); -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:14:11: Context: This is the type variable whose bound isn't conformed to. -// typedef C<X extends A<X>> = A<X>; -// ^ -// // pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart:47:11: Error: Inferred type argument 'Object?' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'Subclass.instance1'. // - 'Object' is from 'dart:core'. // - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45464.dart'.
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.expect b/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.expect index 47a40ba..849cda5 100644 --- a/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.expect +++ b/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.expect
@@ -2,6 +2,16 @@ // // Problems in library: // +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:20:3: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. +// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. +// typedef A<X extends G<C<X>>> = C<X>; +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:21:5: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. // - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. // - 'Object' is from 'dart:core'. @@ -12,6 +22,16 @@ // typedef A<X extends G<C<X>>> = C<X>; // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:22:5: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. +// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A.bar(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. +// typedef A<X extends G<C<X>>> = C<X>; +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:23:3: Error: Inferred type argument 'D<Object?> Function(D<Never>)' doesn't conform to the bound 'D<X> Function(D<X>)' of the type variable 'X' on 'B'. // - 'D' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. // - 'Object' is from 'dart:core'. @@ -22,26 +42,6 @@ // typedef B<X extends G<D<X>>> = D<X>; // ^ // -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:20:3: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. -// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. -// typedef A<X extends G<C<X>>> = C<X>; -// ^ -// -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:22:5: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. -// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A.bar(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. -// typedef A<X extends G<C<X>>> = C<X>; -// ^ -// // pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:24:5: Error: Inferred type argument 'D<Object?> Function(D<Never>)' doesn't conform to the bound 'D<X> Function(D<X>)' of the type variable 'X' on 'B'. // - 'D' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. // - 'Object' is from 'dart:core'.
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.modular.expect b/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.modular.expect index 47a40ba..849cda5 100644 --- a/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.modular.expect +++ b/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.modular.expect
@@ -2,6 +2,16 @@ // // Problems in library: // +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:20:3: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. +// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. +// typedef A<X extends G<C<X>>> = C<X>; +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:21:5: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. // - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. // - 'Object' is from 'dart:core'. @@ -12,6 +22,16 @@ // typedef A<X extends G<C<X>>> = C<X>; // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:22:5: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. +// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A.bar(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. +// typedef A<X extends G<C<X>>> = C<X>; +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:23:3: Error: Inferred type argument 'D<Object?> Function(D<Never>)' doesn't conform to the bound 'D<X> Function(D<X>)' of the type variable 'X' on 'B'. // - 'D' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. // - 'Object' is from 'dart:core'. @@ -22,26 +42,6 @@ // typedef B<X extends G<D<X>>> = D<X>; // ^ // -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:20:3: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. -// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. -// typedef A<X extends G<C<X>>> = C<X>; -// ^ -// -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:22:5: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. -// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A.bar(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. -// typedef A<X extends G<C<X>>> = C<X>; -// ^ -// // pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:24:5: Error: Inferred type argument 'D<Object?> Function(D<Never>)' doesn't conform to the bound 'D<X> Function(D<X>)' of the type variable 'X' on 'B'. // - 'D' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. // - 'Object' is from 'dart:core'.
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.transformed.expect index 47a40ba..849cda5 100644 --- a/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.transformed.expect +++ b/pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart.strong.transformed.expect
@@ -2,6 +2,16 @@ // // Problems in library: // +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:20:3: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. +// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. +// typedef A<X extends G<C<X>>> = C<X>; +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:21:5: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. // - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. // - 'Object' is from 'dart:core'. @@ -12,6 +22,16 @@ // typedef A<X extends G<C<X>>> = C<X>; // ^ // +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:22:5: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. +// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. +// - 'Object' is from 'dart:core'. +// Try specifying type arguments explicitly so that they conform to the bounds. +// A.bar(); // Error. +// ^ +// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. +// typedef A<X extends G<C<X>>> = C<X>; +// ^ +// // pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:23:3: Error: Inferred type argument 'D<Object?> Function(D<Never>)' doesn't conform to the bound 'D<X> Function(D<X>)' of the type variable 'X' on 'B'. // - 'D' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. // - 'Object' is from 'dart:core'. @@ -22,26 +42,6 @@ // typedef B<X extends G<D<X>>> = D<X>; // ^ // -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:20:3: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. -// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. -// typedef A<X extends G<C<X>>> = C<X>; -// ^ -// -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:22:5: Error: Inferred type argument 'C<Object?> Function(C<Never>)' doesn't conform to the bound 'C<X> Function(C<X>)' of the type variable 'X' on 'A'. -// - 'C' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. -// - 'Object' is from 'dart:core'. -// Try specifying type arguments explicitly so that they conform to the bounds. -// A.bar(); // Error. -// ^ -// pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:16:11: Context: This is the type variable whose bound isn't conformed to. -// typedef A<X extends G<C<X>>> = C<X>; -// ^ -// // pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart:24:5: Error: Inferred type argument 'D<Object?> Function(D<Never>)' doesn't conform to the bound 'D<X> Function(D<X>)' of the type variable 'X' on 'B'. // - 'D' is from 'pkg/front_end/testcases/nonfunction_type_aliases/issue45519_2.dart'. // - 'Object' is from 'dart:core'.
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status index be6a69d..a1234c6 100644 --- a/pkg/front_end/testcases/strong.status +++ b/pkg/front_end/testcases/strong.status
@@ -79,6 +79,7 @@ regress/issue_39682: semiFuzzFailureOnForceRebuildBodies # has private method dart2wasm/inference_update_2/issue52452: semiFuzzFailureOnForceRebuildBodies # private fields in class. records/nullable_access_extension: semiFuzzFailureOnForceRebuildBodies # unnamed extension +general/constructor_inference_interdependence: semiFuzzFailureOnForceRebuildBodies # sealed class ending up in another library. # FUZZ FRAMEWORK FAILURES general/script_tag_in_part_file: SemiFuzzFailure # `#!/usr/bin/env dart` goes away
diff --git a/tools/VERSION b/tools/VERSION index 4f2a1a3..6f7908c 100644 --- a/tools/VERSION +++ b/tools/VERSION
@@ -27,5 +27,5 @@ MAJOR 3 MINOR 6 PATCH 0 -PRERELEASE 105 +PRERELEASE 106 PRERELEASE_PATCH 0