Resolve generic function default parameter values
Change-Id: I060ee8f61b8cb74482b92d4057e4183f1e4ca269
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/96701
Commit-Queue: Mike Fairhurst <mfairhurst@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Auto-Submit: Mike Fairhurst <mfairhurst@google.com>
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index e07a7e5..8dfa18b 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3042,6 +3042,9 @@
}
@override
+ ParameterElement get declaredElement => _parameter.declaredElement;
+
+ @override
Token get beginToken => _parameter.beginToken;
@override
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index d685fda..523b409 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -4246,6 +4246,7 @@
resolutionMap.elementDeclaredByFormalParameter(node.parameter)?.type);
super.visitDefaultFormalParameter(node);
ParameterElement element = node.declaredElement;
+
if (element.initializer != null && node.defaultValue != null) {
(element.initializer as FunctionElementImpl).returnType =
node.defaultValue.staticType;
@@ -4513,9 +4514,6 @@
}
@override
- void visitGenericFunctionType(GenericFunctionType node) {}
-
- @override
void visitGenericTypeAliasInFunctionScope(GenericTypeAlias node) {
super.visitGenericTypeAliasInFunctionScope(node);
safelyVisitComment(node.documentationComment);
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index 895f8e3..4a4f04d 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -1418,7 +1418,6 @@
await computeAnalysisResult(source);
assertErrors(source, [
ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
- StrongModeCode.INVALID_CAST_LITERAL_MAP
]);
verify([source]);
}
@@ -1430,7 +1429,6 @@
await computeAnalysisResult(source);
assertErrors(source, [
ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
- StrongModeCode.INVALID_CAST_LITERAL_MAP
]);
verify([source]);
}
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 62edcda..4a44fac 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -14,6 +14,8 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(CompileTimeErrorCodeTest);
+ defineReflectiveTests(CompileTimeErrorCodeTest_WithUIAsCode);
+ defineReflectiveTests(ConstSetElementTypeImplementsEqualsTest);
defineReflectiveTests(ControlFlowCollectionsTest);
defineReflectiveTests(InvalidTypeArgumentInConstSetTest);
defineReflectiveTests(NonConstSetElementFromDeferredLibraryTest);
@@ -100,6 +102,141 @@
}
@reflectiveTest
+class CompileTimeErrorCodeTest_WithUIAsCode extends ResolverTestCase {
+ @override
+ List<String> get enabledExperiments =>
+ [EnableString.control_flow_collections, EnableString.spread_collections];
+
+ @override
+ bool get enableNewAnalysisDriver => true;
+
+ test_defaultValueInFunctionTypeAlias_new_named() async {
+ // This test used to fail with UI as code enabled. Test the fix here.
+ Source source = addSource('''
+typedef F = int Function({Map<String, String> m: const {}});
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [
+ ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+ ]);
+ verify([source]);
+ }
+
+ test_defaultValueInFunctionTypeAlias_new_named_ambiguous() async {
+ // Strong checker asserts isSet || isMap. Prove that assertion holds.
+ Source source = addSource('''
+typedef F = int Function({Object m: const {1, 2: 3}});
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source, [
+ ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+ CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
+ ]);
+ verify([source]);
+ }
+}
+
+@reflectiveTest
+class ConstSetElementTypeImplementsEqualsTest extends ResolverTestCase {
+ @override
+ bool get enableNewAnalysisDriver => true;
+
+ test_constField() async {
+ Source source = addSource(r'''
+class A {
+ static const a = const A();
+ const A();
+ operator ==(other) => false;
+}
+main() {
+ const {A.a};
+}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source,
+ [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ verify([source]);
+ }
+
+ test_direct() async {
+ Source source = addSource(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+main() {
+ const {const A()};
+}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source,
+ [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ verify([source]);
+ }
+
+ test_dynamic() async {
+ // Note: static type of B.a is "dynamic", but actual type of the const
+ // object is A. We need to make sure we examine the actual type when
+ // deciding whether there is a problem with operator==.
+ Source source = addSource(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+class B {
+ static const a = const A();
+}
+main() {
+ const {B.a};
+}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source,
+ [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ verify([source]);
+ }
+
+ test_factory() async {
+ Source source = addSource(r'''
+class A { const factory A() = B; }
+
+class B implements A {
+ const B();
+
+ operator ==(o) => true;
+}
+
+main() {
+ var m = const {const A()};
+}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source,
+ [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ verify([source]);
+ }
+
+ test_super() async {
+ Source source = addSource(r'''
+class A {
+ const A();
+ operator ==(other) => false;
+}
+class B extends A {
+ const B();
+}
+main() {
+ const {const B()};
+}
+''');
+ await computeAnalysisResult(source);
+ assertErrors(source,
+ [CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS]);
+ verify([source]);
+ }
+}
+
+@reflectiveTest
class ControlFlowCollectionsTest extends ResolverTestCase {
@override
List<String> get enabledExperiments =>
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index b47fb50..f5bb3d3 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -2114,7 +2114,6 @@
var fTypeParameter = fType.normalParameterTypes[0] as TypeParameterType;
expect(fTypeParameter.element, same(fTypeTypeParameter));
var tRef = findNode.simple('T>');
- assertType(tRef, null);
var functionTypeNode = tRef.parent.parent.parent as GenericFunctionType;
var functionType = functionTypeNode.type as FunctionType;
assertElement(tRef, functionType.typeFormals[0]);