Fine. Issue 63417. Fix indexing TypeParameterElement(s) inside GenericFunctionType inside constants.

Bug: https://github.com/dart-lang/sdk/issues/63417
Change-Id: Ia50094e8c39c5bce2e01639d8dc950e881305b4b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/505180
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
This commit is contained in:
Konstantin Shcheglov
2026-05-21 11:03:38 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent 9bc1a1015b
commit eda0e21e25
3 changed files with 227 additions and 3 deletions
@@ -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 = 634;
static const int DATA_VERSION = 636;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
+34 -2
View File
@@ -215,6 +215,7 @@ class _ElementCollector extends GeneralizingAstVisitor<void> {
bool isValid = true;
final int Function(TypeParameterElementImpl) indexOfTypeParameter;
final int Function(FormalParameterElementImpl) indexOfFormalParameter;
final List<TypeParameterElement> _localTypeParameters = [];
final Map<Element, int> map = Map.identity();
final List<int> elementIndexList = [];
@@ -289,7 +290,22 @@ class _ElementCollector extends GeneralizingAstVisitor<void> {
@override
void visitGenericFunctionType(GenericFunctionType node) {
node.visitChildren(this);
var localTypeParameters = <TypeParameterElement>[];
if (node.typeParameters case var typeParameters?) {
for (var typeParameter in typeParameters.typeParameters) {
var element = typeParameter.declaredFragment!.element;
localTypeParameters.add(element);
}
}
_localTypeParameters.addAll(localTypeParameters);
try {
node.visitChildren(this);
} finally {
for (var i = 0; i < localTypeParameters.length; i++) {
_localTypeParameters.removeLast();
}
}
}
@override
@@ -433,6 +449,16 @@ class _ElementCollector extends GeneralizingAstVisitor<void> {
node.visitChildren(this);
}
@override
void visitTypeParameter(TypeParameter node) {
node.visitChildren(this);
}
@override
void visitTypeParameterList(TypeParameterList node) {
node.visitChildren(this);
}
void _addElement(Element? element) {
ManifestAstElementKind kind;
int rawIndex;
@@ -454,7 +480,13 @@ class _ElementCollector extends GeneralizingAstVisitor<void> {
rawIndex = indexOfFormalParameter(element);
case TypeParameterElementImpl():
kind = ManifestAstElementKind.typeParameter;
rawIndex = indexOfTypeParameter(element);
var localIndex = _localTypeParameters.lastIndexOf(element);
if (localIndex != -1) {
rawIndex = _localTypeParameters.length - 1 - localIndex;
} else {
rawIndex =
_localTypeParameters.length + indexOfTypeParameter(element);
}
case PrefixElement():
kind = ManifestAstElementKind.importPrefix;
rawIndex = 0;
@@ -85272,6 +85272,198 @@ int get a => 0;
);
}
test_manifest_metadata_genericFunctionType() async {
configuration.withElementManifests = true;
await _runLibraryManifestScenario(
initialCode: r'''
class A {
const A(a);
}
@A(<void Function<T>(T)>[])
void foo() {}
''',
expectedInitialEvents: r'''
[operation] linkLibraryCycle SDK
[operation] linkLibraryCycle
package:test/test.dart
hashForRequirements: #H0
declaredClasses
A: #M0
flags: isSimplyBounded
supertype: Object @ dart:core
interface: #M1
declaredFunctions
foo: #M2
flags: isOriginDeclaration isSimplyBounded isStatic
metadata
[0]
tokenBuffer: @A(<voidFunction<T>(T)>[])
tokenLengthList: [1, 1, 1, 1, 4, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
elements
[0] (package:test/test.dart, class_, A) <null>
[1] (package:test/test.dart, interfaceConstructor, A, new) <null>
elementIndexList
7 = element 0
0 = null
6 = typeParameter 0
23 = element 1
functionType: FunctionType
returnType: void
exportMapId: #M3
exportMap
A: #M0
foo: #M2
''',
updatedCode: r'''
class A {
const A(a);
}
@A(<void Function<T>(T)>[])
void foo() {}
final b = 0;
''',
expectedUpdatedEvents: r'''
[operation] linkLibraryCycle
package:test/test.dart
hashForRequirements: #H1
declaredClasses
A: #M0
flags: isSimplyBounded
supertype: Object @ dart:core
interface: #M1
declaredGetters
b: #M4
flags: isOriginVariable isSimplyBounded isStatic
returnType: int @ dart:core
declaredFunctions
foo: #M2
flags: isOriginDeclaration isSimplyBounded isStatic
metadata
[0]
tokenBuffer: @A(<voidFunction<T>(T)>[])
tokenLengthList: [1, 1, 1, 1, 4, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
elements
[0] (package:test/test.dart, class_, A) <null>
[1] (package:test/test.dart, interfaceConstructor, A, new) <null>
elementIndexList
7 = element 0
0 = null
6 = typeParameter 0
23 = element 1
functionType: FunctionType
returnType: void
declaredVariables
b: #M5
flags: hasImplicitType hasInitializer isFinal isOriginDeclaration isStatic isTypeInferredFromInitializer
type: int @ dart:core
exportMapId: #M6
exportMap
A: #M0
b: #M4
foo: #M2
''',
);
}
test_manifest_metadata_genericFunctionType_nested() async {
configuration.withElementManifests = true;
await _runLibraryManifestScenario(
initialCode: r'''
class A {
const A(a);
}
@A(<void Function<T>(void Function<U extends T>(T, U))>[])
void foo() {}
''',
expectedInitialEvents: r'''
[operation] linkLibraryCycle SDK
[operation] linkLibraryCycle
package:test/test.dart
hashForRequirements: #H0
declaredClasses
A: #M0
flags: isSimplyBounded
supertype: Object @ dart:core
interface: #M1
declaredFunctions
foo: #M2
flags: isOriginDeclaration isSimplyBounded isStatic
metadata
[0]
tokenBuffer: @A(<voidFunction<T>(voidFunction<UextendsT>(T,U))>[])
tokenLengthList: [1, 1, 1, 1, 4, 8, 1, 1, 1, 1, 4, 8, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
elements
[0] (package:test/test.dart, class_, A) <null>
[1] (package:test/test.dart, interfaceConstructor, A, new) <null>
elementIndexList
7 = element 0
0 = null
0 = null
22 = typeParameter 1
22 = typeParameter 1
6 = typeParameter 0
23 = element 1
functionType: FunctionType
returnType: void
exportMapId: #M3
exportMap
A: #M0
foo: #M2
''',
updatedCode: r'''
class A {
const A(a);
}
@A(<void Function<T>(void Function<U extends T>(T, U))>[])
void foo() {}
final b = 0;
''',
expectedUpdatedEvents: r'''
[operation] linkLibraryCycle
package:test/test.dart
hashForRequirements: #H1
declaredClasses
A: #M0
flags: isSimplyBounded
supertype: Object @ dart:core
interface: #M1
declaredGetters
b: #M4
flags: isOriginVariable isSimplyBounded isStatic
returnType: int @ dart:core
declaredFunctions
foo: #M2
flags: isOriginDeclaration isSimplyBounded isStatic
metadata
[0]
tokenBuffer: @A(<voidFunction<T>(voidFunction<UextendsT>(T,U))>[])
tokenLengthList: [1, 1, 1, 1, 4, 8, 1, 1, 1, 1, 4, 8, 1, 1, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
elements
[0] (package:test/test.dart, class_, A) <null>
[1] (package:test/test.dart, interfaceConstructor, A, new) <null>
elementIndexList
7 = element 0
0 = null
0 = null
22 = typeParameter 1
22 = typeParameter 1
6 = typeParameter 0
23 = element 1
functionType: FunctionType
returnType: void
declaredVariables
b: #M5
flags: hasImplicitType hasInitializer isFinal isOriginDeclaration isStatic isTypeInferredFromInitializer
type: int @ dart:core
exportMapId: #M6
exportMap
A: #M0
b: #M4
foo: #M2
''',
);
}
test_manifest_metadata_remove() async {
await _runLibraryManifestScenario(
initialCode: r'''