Discard parens before deciding whether an invocation argument is a function literal.
This extends the fix for https://github.com/dart-lang/language/issues/731 (improved inference for fold etc.) to cover situations where the function literal passed to an invocation is enclosed in (unnecessary) parentheses. Change-Id: I5eb40cf73336612e241a930122f8ae7b1c25bb2a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241021 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
This commit is contained in:
@@ -528,6 +528,7 @@ class InvocationInferrer<Node extends AstNodeImpl> {
|
||||
value = argument;
|
||||
parameterKey = unnamedArgumentIndex++;
|
||||
}
|
||||
value = value.unParenthesized;
|
||||
parameter = parameterMap[parameterKey];
|
||||
if (resolver.isInferenceUpdate1Enabled &&
|
||||
value is FunctionExpressionImpl) {
|
||||
|
||||
@@ -205,6 +205,58 @@ test() => f(t: 0, g: (x) {});
|
||||
_isEnabled ? 'int' : 'Object?');
|
||||
}
|
||||
|
||||
test_horizontal_inference_simple_parenthesized() async {
|
||||
await assertNoErrorsInCode('''
|
||||
void f<T>(T t, void Function(T) g) {}
|
||||
test() => f(0, ((x) {}));
|
||||
''');
|
||||
assertType(
|
||||
findNode.methodInvocation('f(').typeArgumentTypes!.single, 'int');
|
||||
assertType(findNode.methodInvocation('f(').staticInvokeType,
|
||||
'void Function(int, void Function(int))');
|
||||
assertType(findNode.simpleParameter('x').declaredElement!.type,
|
||||
_isEnabled ? 'int' : 'Object?');
|
||||
}
|
||||
|
||||
test_horizontal_inference_simple_parenthesized_named() async {
|
||||
await assertNoErrorsInCode('''
|
||||
void f<T>({required T t, required void Function(T) g}) {}
|
||||
test() => f(t: 0, g: ((x) {}));
|
||||
''');
|
||||
assertType(
|
||||
findNode.methodInvocation('f(').typeArgumentTypes!.single, 'int');
|
||||
assertType(findNode.methodInvocation('f(').staticInvokeType,
|
||||
'void Function({required void Function(int) g, required int t})');
|
||||
assertType(findNode.simpleParameter('x').declaredElement!.type,
|
||||
_isEnabled ? 'int' : 'Object?');
|
||||
}
|
||||
|
||||
test_horizontal_inference_simple_parenthesized_twice() async {
|
||||
await assertNoErrorsInCode('''
|
||||
void f<T>(T t, void Function(T) g) {}
|
||||
test() => f(0, (((x) {})));
|
||||
''');
|
||||
assertType(
|
||||
findNode.methodInvocation('f(').typeArgumentTypes!.single, 'int');
|
||||
assertType(findNode.methodInvocation('f(').staticInvokeType,
|
||||
'void Function(int, void Function(int))');
|
||||
assertType(findNode.simpleParameter('x').declaredElement!.type,
|
||||
_isEnabled ? 'int' : 'Object?');
|
||||
}
|
||||
|
||||
test_horizontal_inference_simple_parenthesized_twice_named() async {
|
||||
await assertNoErrorsInCode('''
|
||||
void f<T>({required T t, required void Function(T) g}) {}
|
||||
test() => f(t: 0, g: (((x) {})));
|
||||
''');
|
||||
assertType(
|
||||
findNode.methodInvocation('f(').typeArgumentTypes!.single, 'int');
|
||||
assertType(findNode.methodInvocation('f(').staticInvokeType,
|
||||
'void Function({required void Function(int) g, required int t})');
|
||||
assertType(findNode.simpleParameter('x').declaredElement!.type,
|
||||
_isEnabled ? 'int' : 'Object?');
|
||||
}
|
||||
|
||||
test_horizontal_inference_unnecessary_due_to_explicit_parameter_type() async {
|
||||
// In this example, there is no need for horizontal type inference because
|
||||
// the type of `x` is explicit.
|
||||
|
||||
@@ -59,4 +59,34 @@ testUnnecessaryDueToExplicitParameterTypeNamed(
|
||||
a.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
|
||||
testParenthesized(void Function<T>(T, void Function(T)) f) {
|
||||
f(0, ((x) {
|
||||
x.expectStaticType<Exactly<Object?>>();
|
||||
}));
|
||||
}
|
||||
|
||||
testParenthesizedNamed(
|
||||
void Function<T>({required T a, required void Function(T) b}) f) {
|
||||
f(
|
||||
a: 0,
|
||||
b: ((x) {
|
||||
x.expectStaticType<Exactly<Object?>>();
|
||||
}));
|
||||
}
|
||||
|
||||
testParenthesizedTwice(void Function<T>(T, void Function(T)) f) {
|
||||
f(0, (((x) {
|
||||
x.expectStaticType<Exactly<Object?>>();
|
||||
})));
|
||||
}
|
||||
|
||||
testParenthesizedTwiceNamed(
|
||||
void Function<T>({required T a, required void Function(T) b}) f) {
|
||||
f(
|
||||
a: 0,
|
||||
b: (((x) {
|
||||
x.expectStaticType<Exactly<Object?>>();
|
||||
})));
|
||||
}
|
||||
|
||||
main() {}
|
||||
|
||||
@@ -122,4 +122,34 @@ testUnnecessaryDueToExplicitParameterTypeNamed(
|
||||
a.expectStaticType<Exactly<int?>>();
|
||||
}
|
||||
|
||||
testParenthesized(void Function<T>(T, void Function(T)) f) {
|
||||
f(0, ((x) {
|
||||
x.expectStaticType<Exactly<int>>();
|
||||
}));
|
||||
}
|
||||
|
||||
testParenthesizedNamed(
|
||||
void Function<T>({required T a, required void Function(T) b}) f) {
|
||||
f(
|
||||
a: 0,
|
||||
b: ((x) {
|
||||
x.expectStaticType<Exactly<int>>();
|
||||
}));
|
||||
}
|
||||
|
||||
testParenthesizedTwice(void Function<T>(T, void Function(T)) f) {
|
||||
f(0, (((x) {
|
||||
x.expectStaticType<Exactly<int>>();
|
||||
})));
|
||||
}
|
||||
|
||||
testParenthesizedTwiceNamed(
|
||||
void Function<T>({required T a, required void Function(T) b}) f) {
|
||||
f(
|
||||
a: 0,
|
||||
b: (((x) {
|
||||
x.expectStaticType<Exactly<int>>();
|
||||
})));
|
||||
}
|
||||
|
||||
main() {}
|
||||
|
||||
Reference in New Issue
Block a user