From 6d86b39595b03d72e4489468cb510c96555ac34d Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Wed, 10 Jun 2026 10:29:28 -0700 Subject: [PATCH] Fine. Store formal parameter default values separately from FunctionType(s). A type is just a type, it should not attempt to carry element semantics. Bug: https://github.com/dart-lang/sdk/issues/63555 Change-Id: I9dacc4f5cc4060d862f7e1bb1ececdd9dc1a303c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/510420 Reviewed-by: Johnni Winther Commit-Queue: Konstantin Shcheglov --- .../lib/src/dart/analysis/driver.dart | 2 +- pkg/analyzer/lib/src/fine/manifest_ast.dart | 24 ++++++++++++ pkg/analyzer/lib/src/fine/manifest_item.dart | 38 ++++++++++++++++++- pkg/analyzer/lib/src/fine/manifest_type.dart | 20 +--------- .../test/src/dart/analysis/driver_test.dart | 36 ++++++++++++++++++ .../src/dart/analysis/result_printer.dart | 23 ++++++++--- 6 files changed, 116 insertions(+), 27 deletions(-) diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart index d6a10db4c31..6efb5b26c77 100644 --- a/pkg/analyzer/lib/src/dart/analysis/driver.dart +++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart @@ -109,7 +109,7 @@ testFineAfterLibraryAnalyzerHook; // TODO(scheglov): Clean up the list of implicitly analyzed files. class AnalysisDriver { /// The version of data format, should be incremented on every format change. - static const int DATA_VERSION = 638; + static const int DATA_VERSION = 639; /// The number of exception contexts allowed to write. Once this field is /// zero, we stop writing any new exception contexts in this process. diff --git a/pkg/analyzer/lib/src/fine/manifest_ast.dart b/pkg/analyzer/lib/src/fine/manifest_ast.dart index bdbe8950bdc..6dc7d980fb7 100644 --- a/pkg/analyzer/lib/src/fine/manifest_ast.dart +++ b/pkg/analyzer/lib/src/fine/manifest_ast.dart @@ -203,6 +203,10 @@ class ManifestNode { return reader.readTypedList(() => ManifestNode.read(reader)); } + static List readListOfOptional(BinaryReader reader) { + return reader.readTypedList(() => ManifestNode.readOptional(reader)); + } + static ManifestNode? readOptional(BinaryReader reader) { return reader.readOptionalObject(() => ManifestNode.read(reader)); } @@ -529,6 +533,26 @@ extension ListOfManifestNodeExtension on List { } } +extension ListOfManifestNodeOrNullExtension on List { + bool match(MatchContext context, List nodes) { + if (nodes.length != length) { + return false; + } + for (var i = 0; i < length; i++) { + if (!this[i].match(context, nodes[i])) { + return false; + } + } + return true; + } + + void writeList(BinaryWriter writer) { + writer.writeList(this, (node) { + node.writeOptional(writer); + }); + } +} + extension ManifestNodeOrNullExtension on ManifestNode? { bool match(MatchContext context, AstNode? node) { var self = this; diff --git a/pkg/analyzer/lib/src/fine/manifest_item.dart b/pkg/analyzer/lib/src/fine/manifest_item.dart index 65f74b05c51..49c29b0ab0a 100644 --- a/pkg/analyzer/lib/src/fine/manifest_item.dart +++ b/pkg/analyzer/lib/src/fine/manifest_item.dart @@ -132,6 +132,7 @@ class ConstructorItem extends ExecutableItem { required _ConstructorItemFlags super.flags, required super.metadata, required super.functionType, + required super.formalParameterDefaultValues, required this.constantInitializers, required this.redirectedConstructor, required this.superConstructor, @@ -148,6 +149,8 @@ class ConstructorItem extends ExecutableItem { flags: _ConstructorItemFlags.encode(element), metadata: ManifestMetadata.encode(context, element.metadata), functionType: element.type.encode(context), + formalParameterDefaultValues: element.formalParameters + .encodeDefaultValues(context), constantInitializers: element.constantInitializers .map((initializer) => ManifestNode.encode(context, initializer)) .toFixedList(), @@ -169,6 +172,7 @@ class ConstructorItem extends ExecutableItem { flags: _ConstructorItemFlags.read(reader), metadata: ManifestMetadata.read(reader), functionType: ManifestFunctionType.read(reader), + formalParameterDefaultValues: ManifestNode.readListOfOptional(reader), constantInitializers: ManifestNode.readList(reader), redirectedConstructor: ManifestElement.readOptional(reader), superConstructor: ManifestElement.readOptional(reader), @@ -284,12 +288,14 @@ class EnumItem extends InterfaceItem { sealed class ExecutableItem extends ManifestItem { final ManifestFunctionType functionType; + final List formalParameterDefaultValues; ExecutableItem({ required super.id, required _ExecutableItemFlags super.flags, required super.metadata, required this.functionType, + required this.formalParameterDefaultValues, }); @override @@ -307,13 +313,18 @@ sealed class ExecutableItem flags.isExternal == element.isExternal && flags.isSimplyBounded == element.isSimplyBounded && flags.isStatic == element.isStatic && - functionType.match(context, element.type); + functionType.match(context, element.type) && + formalParameterDefaultValues.match( + context, + element.formalParameters.map((e) => e.constantInitializer).toList(), + ); } @override void write(BinaryWriter writer) { super.write(writer); functionType.writeNoTag(writer); + formalParameterDefaultValues.writeList(writer); } } @@ -564,6 +575,7 @@ class GetterItem extends PropertyAccessorItem { required super.flags, required super.metadata, required super.functionType, + required super.formalParameterDefaultValues, }); factory GetterItem.fromElement({ @@ -579,6 +591,8 @@ class GetterItem extends PropertyAccessorItem { element.thisOrVariableMetadata, ), functionType: element.type.encode(context), + formalParameterDefaultValues: element.formalParameters + .encodeDefaultValues(context), ); } @@ -588,6 +602,7 @@ class GetterItem extends PropertyAccessorItem { flags: _PropertyAccessorItemFlags.read(reader), metadata: ManifestMetadata.read(reader), functionType: ManifestFunctionType.read(reader), + formalParameterDefaultValues: ManifestNode.readListOfOptional(reader), ); } @@ -1226,6 +1241,7 @@ class MethodItem extends ExecutableItem { required _MethodItemFlags super.flags, required super.metadata, required super.functionType, + required super.formalParameterDefaultValues, required this.typeInferenceError, }); @@ -1239,6 +1255,8 @@ class MethodItem extends ExecutableItem { flags: _MethodItemFlags.encode(element), metadata: ManifestMetadata.encode(context, element.metadata), functionType: element.type.encode(context), + formalParameterDefaultValues: element.formalParameters + .encodeDefaultValues(context), typeInferenceError: element.typeInferenceError, ); } @@ -1249,6 +1267,7 @@ class MethodItem extends ExecutableItem { flags: _MethodItemFlags.read(reader), metadata: ManifestMetadata.read(reader), functionType: ManifestFunctionType.read(reader), + formalParameterDefaultValues: ManifestNode.readListOfOptional(reader), typeInferenceError: TopLevelInferenceError.readOptional(reader), ); } @@ -1390,6 +1409,7 @@ sealed class PropertyAccessorItem required _PropertyAccessorItemFlags super.flags, required super.metadata, required super.functionType, + required super.formalParameterDefaultValues, }); @override @@ -1411,6 +1431,7 @@ class SetterItem extends PropertyAccessorItem { required super.flags, required super.metadata, required super.functionType, + required super.formalParameterDefaultValues, }); factory SetterItem.fromElement({ @@ -1426,6 +1447,8 @@ class SetterItem extends PropertyAccessorItem { element.thisOrVariableMetadata, ), functionType: element.type.encode(context), + formalParameterDefaultValues: element.formalParameters + .encodeDefaultValues(context), ); } @@ -1435,6 +1458,7 @@ class SetterItem extends PropertyAccessorItem { flags: _PropertyAccessorItemFlags.read(reader), metadata: ManifestMetadata.read(reader), functionType: ManifestFunctionType.read(reader), + formalParameterDefaultValues: ManifestNode.readListOfOptional(reader), ); } @@ -1452,6 +1476,7 @@ class TopLevelFunctionItem extends ExecutableItem { required _TopLevelFunctionItemFlags super.flags, required super.metadata, required super.functionType, + required super.formalParameterDefaultValues, }); factory TopLevelFunctionItem.fromElement({ @@ -1464,6 +1489,8 @@ class TopLevelFunctionItem extends ExecutableItem { flags: _TopLevelFunctionItemFlags.encode(element), metadata: ManifestMetadata.encode(context, element.metadata), functionType: element.type.encode(context), + formalParameterDefaultValues: element.formalParameters + .encodeDefaultValues(context), ); } @@ -1473,6 +1500,7 @@ class TopLevelFunctionItem extends ExecutableItem { flags: _TopLevelFunctionItemFlags.read(reader), metadata: ManifestMetadata.read(reader), functionType: ManifestFunctionType.read(reader), + formalParameterDefaultValues: ManifestNode.readListOfOptional(reader), ); } @@ -2548,6 +2576,14 @@ extension type _VariableItemFlags._(int _bits) implements _ManifestItemFlags { } } +extension on List { + List encodeDefaultValues(EncodeContext context) { + return map((element) { + return element.constantInitializer?.encode(context); + }).toFixedList(); + } +} + extension BinaryReaderExtension on BinaryReader { Map readLookupNameMap({required V Function() readValue}) { return readMap( diff --git a/pkg/analyzer/lib/src/fine/manifest_type.dart b/pkg/analyzer/lib/src/fine/manifest_type.dart index 3b9def86c6e..7513edd00b7 100644 --- a/pkg/analyzer/lib/src/fine/manifest_type.dart +++ b/pkg/analyzer/lib/src/fine/manifest_type.dart @@ -9,10 +9,8 @@ import 'package:analyzer/dart/element/nullability_suffix.dart'; import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/src/binary/binary_reader.dart'; import 'package:analyzer/src/binary/binary_writer.dart'; -import 'package:analyzer/src/dart/ast/ast.dart'; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/type.dart'; -import 'package:analyzer/src/fine/manifest_ast.dart'; import 'package:analyzer/src/fine/manifest_context.dart'; import 'package:analyzer/src/fine/manifest_item.dart'; import 'package:analyzer/src/utilities/extensions/collection.dart'; @@ -39,7 +37,6 @@ sealed class ManifestFunctionFormalParameter { final bool isCovariant; final FormalParameterDeclarationForm declarationForm; final ManifestType type; - final ManifestNode? defaultValue; ManifestFunctionFormalParameter({ required this.metadata, @@ -47,7 +44,6 @@ sealed class ManifestFunctionFormalParameter { required this.isCovariant, required this.declarationForm, required this.type, - required this.defaultValue, }); bool match(MatchContext context, InternalFormalParameterElement element) { @@ -55,8 +51,7 @@ sealed class ManifestFunctionFormalParameter { element.isRequired == isRequired && element.isCovariant == isCovariant && element.declarationForm == declarationForm && - type.match(context, element.type) && - defaultValue.match(context, element.constantInitializer); + type.match(context, element.type); } void write(BinaryWriter writer) { @@ -65,7 +60,6 @@ sealed class ManifestFunctionFormalParameter { writer.writeBool(isCovariant); writer.writeEnum(declarationForm); type.write(writer); - defaultValue.writeOptional(writer); } } @@ -83,7 +77,6 @@ class ManifestFunctionNamedFormalParameter isCovariant: element.isCovariant, declarationForm: element.declarationForm, type: element.type.encode(context), - defaultValue: element.constantInitializer?.encode(context), name: element.name ?? '', ); } @@ -95,7 +88,6 @@ class ManifestFunctionNamedFormalParameter isCovariant: reader.readBool(), declarationForm: reader.readEnum(FormalParameterDeclarationForm.values), type: ManifestType.read(reader), - defaultValue: ManifestNode.readOptional(reader), name: reader.readStringReference(), ); } @@ -106,7 +98,6 @@ class ManifestFunctionNamedFormalParameter required super.isCovariant, required super.declarationForm, required super.type, - required super.defaultValue, required this.name, }); @@ -136,7 +127,6 @@ class ManifestFunctionPositionalFormalParameter isCovariant: element.isCovariant, declarationForm: element.declarationForm, type: element.type.encode(context), - defaultValue: element.constantInitializer?.encode(context), ); } @@ -147,7 +137,6 @@ class ManifestFunctionPositionalFormalParameter isCovariant: reader.readBool(), declarationForm: reader.readEnum(FormalParameterDeclarationForm.values), type: ManifestType.read(reader), - defaultValue: ManifestNode.readOptional(reader), ); } @@ -157,7 +146,6 @@ class ManifestFunctionPositionalFormalParameter required super.isCovariant, required super.declarationForm, required super.type, - required super.defaultValue, }); @override @@ -762,9 +750,3 @@ extension ManifestTypeOrNullExtension on ManifestType? { writer.writeOptionalObject(this, (x) => x.write(writer)); } } - -extension _AstNodeExtension on AstNode { - ManifestNode encode(EncodeContext context) { - return ManifestNode.encode(context, this); - } -} diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart index 10630d0daf4..e9dba0a2f19 100644 --- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart @@ -95670,6 +95670,42 @@ final b = 1; ); } + test_manifest_topLevelVariable_initializer_functionType_defaultValue() async { + await _runLibraryManifestScenario( + initialCode: r''' +final x = ([int a = 0]) => a; +''', + expectedInitialEvents: r''' +[operation] linkLibraryCycle SDK +[operation] linkLibraryCycle + package:test/test.dart + hashForRequirements: #H0 + declaredGetters + x: #M0 + declaredVariables + x: #M1 + exportMapId: #M2 + exportMap + x: #M0 +''', + updatedCode: r''' +final x = ([int a = 1]) => a; +''', + expectedUpdatedEvents: r''' +[operation] linkLibraryCycle + package:test/test.dart + hashForRequirements: #H0 + declaredGetters + x: #M0 + declaredVariables + x: #M1 + exportMapId: #M2 + exportMap + x: #M0 +''', + ); + } + test_manifest_topLevelVariable_initializer_type() async { await _runLibraryManifestScenario( initialCode: r''' diff --git a/pkg/analyzer/test/src/dart/analysis/result_printer.dart b/pkg/analyzer/test/src/dart/analysis/result_printer.dart index 9b1275c6ab4..43e61fdda87 100644 --- a/pkg/analyzer/test/src/dart/analysis/result_printer.dart +++ b/pkg/analyzer/test/src/dart/analysis/result_printer.dart @@ -1400,6 +1400,17 @@ class LibraryManifestPrinter extends ManifestPrinter { }); } + void _writeFormalParameterDefaultValues(ExecutableItem item) { + if (configuration.withElementManifests) { + var indexed = item.formalParameterDefaultValues.indexed + .where((entry) => entry.$2 != null) + .toList(); + sink.writeElements('formalParameterDefaultValues', indexed, (entry) { + _writeNode('[${entry.$1}]', entry.$2); + }); + } + } + void _writeGetterItem(GetterItem item) { if (configuration.withElementManifests) { sink.withIndent(() { @@ -1411,6 +1422,7 @@ class LibraryManifestPrinter extends ManifestPrinter { }); _writeMetadata(item); _writeNamedType('returnType', item.functionType.returnType); + _writeFormalParameterDefaultValues(item); }); } } @@ -1485,6 +1497,7 @@ class LibraryManifestPrinter extends ManifestPrinter { }); _writeMetadata(item); _writeNamedType('functionType', item.functionType); + _writeFormalParameterDefaultValues(item); }); writeDeclaredItems('declaredMethods', item.declaredMethods, (item) { @@ -1497,6 +1510,7 @@ class LibraryManifestPrinter extends ManifestPrinter { }); _writeMetadata(item); _writeNamedType('functionType', item.functionType); + _writeFormalParameterDefaultValues(item); _writeTopLevelInferenceError('inferenceError', item.typeInferenceError); }); @@ -1515,6 +1529,7 @@ class LibraryManifestPrinter extends ManifestPrinter { }); _writeMetadata(item); _writeNamedType('functionType', item.functionType); + _writeFormalParameterDefaultValues(item); _writelnNamedElement( 'redirectedConstructor', item.redirectedConstructor, @@ -1744,6 +1759,7 @@ class LibraryManifestPrinter extends ManifestPrinter { }); _writeMetadata(item); _writeNamedType('functionType', item.functionType); + _writeFormalParameterDefaultValues(item); }); } } @@ -1758,6 +1774,7 @@ class LibraryManifestPrinter extends ManifestPrinter { }); _writeMetadata(item); _writeNamedType('functionType', item.functionType); + _writeFormalParameterDefaultValues(item); }); } } @@ -1830,18 +1847,12 @@ class LibraryManifestPrinter extends ManifestPrinter { sink.writeIf(field.isRequired, 'required '); writeParameterDeclarationForm(field); _writeType(field.type); - sink.withIndent(() { - _writeNode('defaultValue', field.defaultValue); - }); }); sink.writeElements('named', type.named, (field) { sink.writeWithIndent('${field.name}: '); sink.writeIf(field.isRequired, 'required '); writeParameterDeclarationForm(field); _writeType(field.type); - sink.withIndent(() { - _writeNode('defaultValue', field.defaultValue); - }); }); _writeNamedType('returnType', type.returnType); });