mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:00:09 +00:00
Fix RETURN_OF_INVALID_TYPE for anonymous closures
The displayName of an anonymous closure is a blank String, resulting in messages like: [error] The return type 'String' is not a 'int', as defined by the method ''. After this change, an error might instead look like: $ xcodebuild/ReleaseX64/dart-sdk/bin/dartanalyzer --strong 26056.dart Analyzing 26056.dart... error • The return type 'String' isn't a 'int', as defined by anonymouse closure at 26056.dart:6:28 • return_of_invalid_type 1 error found. Bug: https://github.com/dart-lang/sdk/issues/26056 Change-Id: I4003eea22cb23e0b06479482c06d5ce8a936c756 Reviewed-on: https://dart-review.googlesource.com/28382 Commit-Queue: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
ad9ea873c7
commit
b50319ca9f
|
@ -512,6 +512,7 @@ const List<ErrorCode> errorCodeValues = const [
|
|||
StaticTypeWarningCode.NON_NULLABLE_FIELD_NOT_INITIALIZED,
|
||||
StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT,
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
|
||||
StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
|
||||
StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
|
||||
StaticTypeWarningCode.UNDEFINED_ENUM_CONSTANT,
|
||||
|
|
|
@ -2864,6 +2864,19 @@ class StaticTypeWarningCode extends ErrorCode {
|
|||
const StaticTypeWarningCode('RETURN_OF_INVALID_TYPE',
|
||||
"The return type '{0}' isn't a '{1}', as defined by the method '{2}'.");
|
||||
|
||||
/**
|
||||
* 13.11 Return: It is a static type warning if the type of <i>e</i> may not
|
||||
* be assigned to the declared return type of the immediately enclosing
|
||||
* function.
|
||||
*
|
||||
* Parameters:
|
||||
* 0: the return type as declared in the return statement
|
||||
* 1: the expected return type as defined by the method
|
||||
*/
|
||||
static const StaticTypeWarningCode RETURN_OF_INVALID_TYPE_FROM_CLOSURE =
|
||||
const StaticTypeWarningCode('RETURN_OF_INVALID_TYPE_FROM_CLOSURE',
|
||||
"The return type '{0}' isn't a '{1}', as defined by anonymous closure.");
|
||||
|
||||
/**
|
||||
* 12.11 Instance Creation: It is a static type warning if any of the type
|
||||
* arguments to a constructor of a generic type <i>G</i> invoked by a new
|
||||
|
|
|
@ -5632,6 +5632,17 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
|||
return;
|
||||
}
|
||||
DartType staticReturnType = _computeReturnTypeForMethod(returnExpression);
|
||||
String displayName = _enclosingFunction.displayName;
|
||||
|
||||
void reportTypeError() => _errorReporter.reportTypeErrorForNode(
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
|
||||
returnExpression,
|
||||
[staticReturnType, expectedReturnType, displayName]);
|
||||
void reportTypeErrorFromClosure() => _errorReporter.reportTypeErrorForNode(
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE,
|
||||
returnExpression,
|
||||
[staticReturnType, expectedReturnType]);
|
||||
|
||||
if (expectedReturnType.isVoid) {
|
||||
if (isArrowFunction) {
|
||||
// "void f(..) => e" admits all types for "e".
|
||||
|
@ -5643,22 +5654,22 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
|||
staticReturnType.isDartCoreNull) {
|
||||
return;
|
||||
}
|
||||
_errorReporter.reportTypeErrorForNode(
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [
|
||||
staticReturnType,
|
||||
expectedReturnType,
|
||||
_enclosingFunction.displayName
|
||||
]);
|
||||
if (displayName.isEmpty) {
|
||||
reportTypeErrorFromClosure();
|
||||
} else {
|
||||
reportTypeError();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (_expressionIsAssignableAtType(
|
||||
returnExpression, staticReturnType, expectedReturnType)) {
|
||||
return;
|
||||
}
|
||||
_errorReporter.reportTypeErrorForNode(
|
||||
StaticTypeWarningCode.RETURN_OF_INVALID_TYPE,
|
||||
returnExpression,
|
||||
[staticReturnType, expectedReturnType, _enclosingFunction.displayName]);
|
||||
if (displayName.isEmpty) {
|
||||
reportTypeErrorFromClosure();
|
||||
} else {
|
||||
reportTypeError();
|
||||
}
|
||||
|
||||
// TODO(brianwilkerson) Define a hint corresponding to the warning and
|
||||
// report it if appropriate.
|
||||
|
|
|
@ -203,7 +203,7 @@ test1() {
|
|||
main() {
|
||||
String f() => null;
|
||||
var g = f;
|
||||
g = /*info:INFERRED_TYPE_CLOSURE*/() { return /*error:RETURN_OF_INVALID_TYPE*/1; };
|
||||
g = /*info:INFERRED_TYPE_CLOSURE*/() { return /*error:RETURN_OF_INVALID_TYPE_FROM_CLOSURE*/1; };
|
||||
}
|
||||
''');
|
||||
var g = findLocalVariable(unit, 'g');
|
||||
|
@ -1016,14 +1016,14 @@ void main () {
|
|||
Function2<int, String> l1 = (int x) => "hello";
|
||||
Function2<int, String> l2 = /*error:INVALID_ASSIGNMENT*/(String x) => "hello";
|
||||
Function2<int, String> l3 = /*error:INVALID_ASSIGNMENT*/(int x) => 3;
|
||||
Function2<int, String> l4 = /*info:INFERRED_TYPE_CLOSURE*/(int x) {return /*error:RETURN_OF_INVALID_TYPE*/3;};
|
||||
Function2<int, String> l4 = /*info:INFERRED_TYPE_CLOSURE*/(int x) {return /*error:RETURN_OF_INVALID_TYPE_FROM_CLOSURE*/3;};
|
||||
}
|
||||
{
|
||||
Function2<int, String> l0 = /*info:INFERRED_TYPE_CLOSURE*/(x) => null;
|
||||
Function2<int, String> l1 = /*info:INFERRED_TYPE_CLOSURE*/(x) => "hello";
|
||||
Function2<int, String> l2 = /*info:INFERRED_TYPE_CLOSURE, error:INVALID_ASSIGNMENT*/(x) => 3;
|
||||
Function2<int, String> l3 = /*info:INFERRED_TYPE_CLOSURE*/(x) {return /*error:RETURN_OF_INVALID_TYPE*/3;};
|
||||
Function2<int, String> l4 = /*info:INFERRED_TYPE_CLOSURE*/(x) {return /*error:RETURN_OF_INVALID_TYPE*/x;};
|
||||
Function2<int, String> l3 = /*info:INFERRED_TYPE_CLOSURE*/(x) {return /*error:RETURN_OF_INVALID_TYPE_FROM_CLOSURE*/3;};
|
||||
Function2<int, String> l4 = /*info:INFERRED_TYPE_CLOSURE*/(x) {return /*error:RETURN_OF_INVALID_TYPE_FROM_CLOSURE*/x;};
|
||||
}
|
||||
{
|
||||
Function2<int, List<String>> l0 = /*info:INFERRED_TYPE_CLOSURE*/(int x) => null;
|
||||
|
@ -1151,7 +1151,7 @@ void main () {
|
|||
v = <T>(int x) => "hello";
|
||||
v = /*error:INVALID_ASSIGNMENT*/<T>(String x) => "hello";
|
||||
v = /*error:INVALID_ASSIGNMENT*/<T>(int x) => 3;
|
||||
v = /*info:INFERRED_TYPE_CLOSURE*/<T>(int x) {return /*error:RETURN_OF_INVALID_TYPE*/3;};
|
||||
v = /*info:INFERRED_TYPE_CLOSURE*/<T>(int x) {return /*error:RETURN_OF_INVALID_TYPE_FROM_CLOSURE*/3;};
|
||||
}
|
||||
{
|
||||
String f<S>(int x) => null;
|
||||
|
@ -1159,8 +1159,8 @@ void main () {
|
|||
v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/<T>(x) => null;
|
||||
v = /*info:INFERRED_TYPE_CLOSURE*/<T>(x) => "hello";
|
||||
v = /*info:INFERRED_TYPE_CLOSURE, error:INVALID_ASSIGNMENT*/<T>(x) => 3;
|
||||
v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/<T>(x) {return /*error:RETURN_OF_INVALID_TYPE*/3;};
|
||||
v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/<T>(x) {return /*error:RETURN_OF_INVALID_TYPE*/x;};
|
||||
v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/<T>(x) {return /*error:RETURN_OF_INVALID_TYPE_FROM_CLOSURE*/3;};
|
||||
v = /*info:INFERRED_TYPE_CLOSURE, info:INFERRED_TYPE_CLOSURE*/<T>(x) {return /*error:RETURN_OF_INVALID_TYPE_FROM_CLOSURE*/x;};
|
||||
}
|
||||
{
|
||||
List<String> f<S>(int x) => null;
|
||||
|
|
|
@ -24,7 +24,7 @@ Future<CodeBuffer> compileAll(SourceFile sourceFile) {
|
|||
// emitter.
|
||||
full.Emitter fullEmitter = backend.emitter.emitter;
|
||||
// CodeOutput isn't assignable to CodeBuffer.
|
||||
// ignore: RETURN_OF_INVALID_TYPE
|
||||
// ignore: RETURN_OF_INVALID_TYPE_FROM_CLOSURE
|
||||
return fullEmitter
|
||||
.outputBuffers[compiler.backend.outputUnitData.mainOutputUnit];
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue