sdk
sdk copied to clipboard
Analyzer fails to propery type check invocations of complex expressions whose type is a type parameter
This code is (correctly) rejected by both the analyzer and the CFE:
int test<T extends int Function(int)>(T Function() createT) {
var tValue = createT();
return tValue(''); // ERROR: 'String' not assignable to 'int'
}
This code is equivalent (the only difference is that the local variable tValue has been inlined), so it should be rejected too. It is correctly rejected by the CFE, but it is accepted by the analyzer:
int test<T extends int Function(int)>(T Function() createT) {
return createT()('');
}
Summary: The analyzer incorrectly accepts code with an inlined function call where the type parameter is a function type, leading to a type error when the function is invoked with an incorrect argument. The CFE correctly rejects both code examples.
I believe the problem in the second example is that the analyzer's FunctionExpressionInvocationResolver doesn't properly resolve the type of the "function" (createT() in this case) from a type parameter type (T) to its bound (int Function(int)), so it treats it as a dynamic invocation and fails to check the argument ''.
The reason the problem doesn't show up in the first example is that the analyzer parses tValue('') as a MethodInvocation rather than a FunctionExpressionInvocation, so its first step in trying to resolve it is to use the MethodInvocationResolver, which does resolve the type of tValue to its bound.
I found this bug in the process of trying to do some other refactoring to MethodInvocationResolver and FunctionExpressionInvocationResolver, so I'll work on a fix in order to avoid blocking that work.