mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 16:26:38 +00:00
Fix strict-inference for function expressions which can properly infer
Change-Id: I881476f78e9c76650cb576c321ecb0959dce5882 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/118909 Commit-Queue: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
c49d3c3486
commit
9c8de83ced
|
@ -272,6 +272,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
}
|
||||
_checkStrictInferenceInParameters(node.parameters);
|
||||
super.visitConstructorDeclaration(node);
|
||||
}
|
||||
|
||||
|
@ -316,6 +317,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
|
|||
if (node.parent is CompilationUnit) {
|
||||
_checkStrictInferenceReturnType(node.returnType, node, node.name.name);
|
||||
}
|
||||
_checkStrictInferenceInParameters(node.functionExpression.parameters);
|
||||
super.visitFunctionDeclaration(node);
|
||||
} finally {
|
||||
_inDeprecatedMember = wasInDeprecatedMember;
|
||||
|
@ -334,6 +336,10 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
|
|||
if (node.parent is! FunctionDeclaration) {
|
||||
_checkForMissingReturn(null, node.body, node.declaredElement, node);
|
||||
}
|
||||
DartType functionType = InferenceContext.getContext(node);
|
||||
if (functionType is! FunctionType) {
|
||||
_checkStrictInferenceInParameters(node.parameters);
|
||||
}
|
||||
super.visitFunctionExpression(node);
|
||||
}
|
||||
|
||||
|
@ -341,6 +347,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
|
|||
void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
|
||||
_checkStrictInferenceReturnType(
|
||||
node.returnType, node, node.identifier.name);
|
||||
_checkStrictInferenceInParameters(node.parameters);
|
||||
super.visitFunctionTypedFormalParameter(node);
|
||||
}
|
||||
|
||||
|
@ -386,6 +393,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
|
|||
_checkForMissingReturn(node.returnType, node.body, element, node);
|
||||
_checkForUnnecessaryNoSuchMethod(node);
|
||||
_checkStrictInferenceReturnType(node.returnType, node, node.name.name);
|
||||
_checkStrictInferenceInParameters(node.parameters);
|
||||
super.visitMethodDeclaration(node);
|
||||
} finally {
|
||||
_inDeprecatedMember = wasInDeprecatedMember;
|
||||
|
@ -1136,7 +1144,35 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
/// In "strict-inference" mode, check that [returnNode]'s return type is specified.
|
||||
/// In "strict-inference" mode, check that each of the [parameters]' type is
|
||||
/// specified.
|
||||
_checkStrictInferenceInParameters(FormalParameterList parameters) {
|
||||
void checkParameterTypeIsKnown(SimpleFormalParameter parameter) {
|
||||
if (parameter.type == null) {
|
||||
ParameterElement element = parameter.declaredElement;
|
||||
_errorReporter.reportTypeErrorForNode(
|
||||
HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER,
|
||||
parameter,
|
||||
[element.displayName],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (_strictInference && parameters != null) {
|
||||
for (FormalParameter parameter in parameters.parameters) {
|
||||
if (parameter is SimpleFormalParameter) {
|
||||
checkParameterTypeIsKnown(parameter);
|
||||
} else if (parameter is DefaultFormalParameter) {
|
||||
if (parameter.parameter is SimpleFormalParameter) {
|
||||
checkParameterTypeIsKnown(parameter.parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// In "strict-inference" mode, check that [returnNode]'s return type is
|
||||
/// specified.
|
||||
void _checkStrictInferenceReturnType(
|
||||
AstNode returnType, AstNode reportNode, String displayName) {
|
||||
if (!_strictInference) {
|
||||
|
|
|
@ -117,8 +117,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<void> {
|
|||
/**
|
||||
* Given a formal parameter list and a function type use the function type
|
||||
* to infer types for any of the parameters which have implicit (missing)
|
||||
* types. Only infers types in strong mode. Returns true if inference
|
||||
* has occurred.
|
||||
* types. Returns true if inference has occurred.
|
||||
*/
|
||||
bool inferFormalParameterList(
|
||||
FormalParameterList node, DartType functionType) {
|
||||
|
@ -525,34 +524,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<void> {
|
|||
_resolver.extensionResolver.resolveOverride(node);
|
||||
}
|
||||
|
||||
/// No inference is performed here; just static checking for the
|
||||
/// "strict-inference" static analysis mode.
|
||||
@override
|
||||
void visitFormalParameterList(FormalParameterList node) {
|
||||
void checkParameterTypeIsKnown(SimpleFormalParameter parameter) {
|
||||
ParameterElement element = parameter.declaredElement;
|
||||
if (parameter.type == null) {
|
||||
_resolver.errorReporter.reportTypeErrorForNode(
|
||||
HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER,
|
||||
parameter,
|
||||
[element.displayName],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (_strictInference) {
|
||||
for (FormalParameter parameter in node.parameters) {
|
||||
if (parameter is SimpleFormalParameter) {
|
||||
checkParameterTypeIsKnown(parameter);
|
||||
} else if (parameter is DefaultFormalParameter) {
|
||||
if (parameter.parameter is SimpleFormalParameter) {
|
||||
checkParameterTypeIsKnown(parameter.parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitFunctionDeclaration(FunctionDeclaration node) {
|
||||
FunctionExpression function = node.functionExpression;
|
||||
|
|
|
@ -32,13 +32,13 @@ class C {
|
|||
''');
|
||||
}
|
||||
|
||||
test_functionTypeParameter_withType() async {
|
||||
test_functionTypedFormalParameter_withType() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void fn(String cb(int x)) => print(cb(7));
|
||||
''');
|
||||
}
|
||||
|
||||
test_functionTypeParameter_withVar() async {
|
||||
test_functionTypedFormalParameter_withVar() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void fn(String cb(var x)) => print(cb(7));
|
||||
''', [
|
||||
|
@ -97,6 +97,24 @@ void fn() {
|
|||
]);
|
||||
}
|
||||
|
||||
test_parameter_inFunctionLiteral_inferredType() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void fn() {
|
||||
g((a, b) => print('$a$b'));
|
||||
}
|
||||
|
||||
void g(void cb(int a, dynamic b)) => cb(7, "x");
|
||||
''');
|
||||
}
|
||||
|
||||
test_parameter_inFunctionLiteral_inferredType_viaReturn() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void Function(int, dynamic) fn() {
|
||||
return (a, b) => print('$a$b');
|
||||
}
|
||||
''');
|
||||
}
|
||||
|
||||
test_parameter_inFunctionLiteral_withType() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void fn() {
|
||||
|
@ -191,6 +209,14 @@ typedef cb = void Function(int a);
|
|||
''');
|
||||
}
|
||||
|
||||
test_parameter_withoutKeyword() async {
|
||||
await assertErrorsInCode(r'''
|
||||
void fn(a) => print(a);
|
||||
''', [
|
||||
error(HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER, 8, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_parameter_withType() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
void fn(int a) => print(a);
|
||||
|
|
Loading…
Reference in a new issue