analyzer: Fix instantiated type parameter in function reference error
This fixes language/const/instantiated_function_constant_test
Change-Id: I06f42480f8a55de1c6d75b2b5845bcefb769fa78
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/218540
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 468934b..dc0030a 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -447,7 +447,7 @@
final Map<String, DartObjectImpl>? _lexicalEnvironment;
/// A mapping of type parameter names to runtime values (types).
- final Map<String, DartType>? _lexicalTypeEnvironment;
+ final Map<TypeParameterElement, DartType>? _lexicalTypeEnvironment;
final Substitution? _substitution;
@@ -471,7 +471,7 @@
this._library,
this._errorReporter, {
Map<String, DartObjectImpl>? lexicalEnvironment,
- Map<String, DartType>? lexicalTypeEnvironment,
+ Map<TypeParameterElement, DartType>? lexicalTypeEnvironment,
Substitution? substitution,
}) : _lexicalEnvironment = lexicalEnvironment,
_lexicalTypeEnvironment = lexicalTypeEnvironment,
@@ -687,9 +687,20 @@
// type parameter. If, however, `node.typeArguments` is not `null`, then
// any type parameters contained therein are reported as non-constant in
// [ConstantVerifier].
- if (node.typeArguments == null &&
- (node.typeArgumentTypes?.any(hasTypeParameterReference) ?? false)) {
- _error(node, null);
+ if (node.typeArguments == null) {
+ var typeArgumentTypes = node.typeArgumentTypes;
+ if (typeArgumentTypes != null) {
+ var instantiatedTypeArgumentTypes = typeArgumentTypes.map((type) {
+ if (type is TypeParameterType) {
+ return _lexicalTypeEnvironment?[type.element] ?? type;
+ } else {
+ return type;
+ }
+ });
+ if (instantiatedTypeArgumentTypes.any(hasTypeParameterReference)) {
+ _error(node, null);
+ }
+ }
}
var typeArgumentList = node.typeArguments;
@@ -1300,7 +1311,7 @@
// Constants may refer to type parameters only if the constructor-tearoffs
// feature is enabled.
if (_library.featureSet.isEnabled(Feature.constructor_tearoffs)) {
- var typeArgument = _lexicalTypeEnvironment?[identifier.name];
+ var typeArgument = _lexicalTypeEnvironment?[identifier.staticElement];
if (typeArgument != null) {
return DartObjectImpl(
typeSystem,
@@ -2029,7 +2040,7 @@
final List<DartObjectImpl> _argumentValues;
- final Map<String, DartType> _typeParameterMap = HashMap();
+ final Map<TypeParameterElement, DartType> _typeParameterMap = HashMap();
final Map<String, DartObjectImpl> _parameterMap = HashMap();
@@ -2435,7 +2446,7 @@
for (int i = 0; i < typeParameters.length; i++) {
var typeParameter = typeParameters[i];
var typeArgument = typeArguments[i];
- _typeParameterMap[typeParameter.name] = typeArgument;
+ _typeParameterMap[typeParameter] = typeArgument;
}
}
}
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index dddec74..f544ef9 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -1954,6 +1954,29 @@
);
}
+ test_fieldInitializer_functionReference_withTypeParameter() async {
+ await resolveTestCode('''
+void g<U>(U a) {}
+class A<T> {
+ final void Function(T) f;
+ const A(): f = g;
+}
+const a = const A<int>();
+''');
+ var result = _evaluateConstant('a');
+ var aElement = findElement.class_('A');
+ var expectedType = aElement.instantiate(
+ typeArguments: [typeProvider.intType],
+ nullabilitySuffix: NullabilitySuffix.none);
+ expect(result.type, expectedType);
+
+ var fField = result.fields!['f']!;
+ var gElement = findElement.topFunction('g');
+ var expectedFunctionType =
+ gElement.type.instantiate([typeProvider.intType]);
+ expect(fField.type, expectedFunctionType);
+ }
+
test_fieldInitializer_typeParameter() async {
await resolveTestCode('''
class A<T> {