Skip to content

Commit

Permalink
[cfe] Update messages for invalid returns
Browse files Browse the repository at this point in the history
Closes #42527

Change-Id: Ic240dd7a8822c85c550941923bf9ce3b5cfe0dba
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153348
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Erik Ernst <eernst@google.com>
  • Loading branch information
johnniwinther authored and commit-bot@chromium.org committed Jul 8, 2020
1 parent 9ab7a5e commit fd432fe
Show file tree
Hide file tree
Showing 125 changed files with 444 additions and 208 deletions.
78 changes: 78 additions & 0 deletions pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2040,6 +2040,84 @@ Message _withArgumentsInvalidCastTopLevelFunction(
arguments: {'type': _type, 'type2': _type2});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
DartType _type,
DartType _type2,
bool
isNonNullableByDefault)> templateInvalidReturn = const Template<
Message Function(
DartType _type, DartType _type2, bool isNonNullableByDefault)>(
messageTemplate:
r"""A value of type '#type' can't be returned from a function with return type '#type2'.""",
withArguments: _withArgumentsInvalidReturn);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<
Message Function(
DartType _type, DartType _type2, bool isNonNullableByDefault)>
codeInvalidReturn = const Code<
Message Function(
DartType _type, DartType _type2, bool isNonNullableByDefault)>(
"InvalidReturn",
templateInvalidReturn,
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsInvalidReturn(
DartType _type, DartType _type2, bool isNonNullableByDefault) {
TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
List<Object> typeParts = labeler.labelType(_type);
List<Object> type2Parts = labeler.labelType(_type2);
String type = typeParts.join();
String type2 = type2Parts.join();
return new Message(codeInvalidReturn,
message:
"""A value of type '${type}' can't be returned from a function with return type '${type2}'.""" +
labeler.originMessages,
arguments: {'type': _type, 'type2': _type2});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
DartType _type,
DartType _type2,
bool
isNonNullableByDefault)> templateInvalidReturnAsync = const Template<
Message Function(
DartType _type, DartType _type2, bool isNonNullableByDefault)>(
messageTemplate:
r"""A value of type '#type' can't be returned from an async function with return type '#type2'.""",
withArguments: _withArgumentsInvalidReturnAsync);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<
Message Function(
DartType _type, DartType _type2, bool isNonNullableByDefault)>
codeInvalidReturnAsync = const Code<
Message Function(
DartType _type, DartType _type2, bool isNonNullableByDefault)>(
"InvalidReturnAsync",
templateInvalidReturnAsync,
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsInvalidReturnAsync(
DartType _type, DartType _type2, bool isNonNullableByDefault) {
TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
List<Object> typeParts = labeler.labelType(_type);
List<Object> type2Parts = labeler.labelType(_type2);
String type = typeParts.join();
String type2 = type2Parts.join();
return new Message(codeInvalidReturnAsync,
message:
"""A value of type '${type}' can't be returned from an async function with return type '${type2}'.""" +
labeler.originMessages,
arguments: {'type': _type, 'type2': _type2});
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(DartType _type, DartType _type2, DartType _type3,
Expand Down
32 changes: 12 additions & 20 deletions pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,8 @@ class _SyncClosureContext implements ClosureContext {
// nor dynamic, and S is void.
statement.expression = inferrer.helper.wrapInProblem(
statement.expression,
messageVoidExpression,
templateInvalidReturn.withArguments(expressionType,
_declaredReturnType, inferrer.isNonNullableByDefault),
statement.expression.fileOffset,
noLength)
..parent = statement;
Expand All @@ -204,7 +205,9 @@ class _SyncClosureContext implements ClosureContext {
// S is not assignable to T.
Expression expression = inferrer.ensureAssignable(
_returnContext, expressionType, statement.expression,
fileOffset: statement.expression.fileOffset, isVoidAllowed: true);
fileOffset: statement.expression.fileOffset,
isVoidAllowed: true,
errorTemplate: templateInvalidReturn);
statement.expression = expression..parent = statement;
}
}
Expand Down Expand Up @@ -481,7 +484,8 @@ class _AsyncClosureContext implements ClosureContext {
// flatten(S) is neither void, dynamic, Null.
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageReturnFromVoidFunction,
templateInvalidReturnAsync.withArguments(expressionType,
_declaredReturnType, inferrer.isNonNullableByDefault),
statement.expression.fileOffset,
noLength)
..parent = statement;
Expand All @@ -492,25 +496,11 @@ class _AsyncClosureContext implements ClosureContext {
// nor dynamic, and flatten(S) is void.
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageVoidExpression,
templateInvalidReturnAsync.withArguments(expressionType,
_declaredReturnType, inferrer.isNonNullableByDefault),
statement.expression.fileOffset,
noLength)
..parent = statement;
/* } else if (flattenedExpressionType is! VoidType &&
!inferrer.isAssignable(futureValueType, expressionType) &&
!inferrer.typeSchemaEnvironment
.performNullabilityAwareSubtypeCheck(
flattenedExpressionType, futureValueType)
.isSubtypeWhenUsingNullabilities()) {
// It is a compile-time error if s is `return e;`, flatten(S) is not
// void, S is not assignable to T_v, and flatten(S) is not a subtype
// of T_v.
statement.expression = inferrer.helper.wrapInProblem(
new NullLiteral()..fileOffset = statement.fileOffset,
messageReturnWithoutExpressionAsync,
statement.expression.fileOffset,
noLength)
..parent = statement;*/
} else if (flattenedExpressionType is! VoidType &&
!inferrer.typeSchemaEnvironment
.performNullabilityAwareSubtypeCheck(
Expand All @@ -523,7 +513,9 @@ class _AsyncClosureContext implements ClosureContext {
futureValueType, expressionType, statement.expression,
fileOffset: statement.expression.fileOffset,
runtimeCheckedType: _returnContext,
isVoidAllowed: false)
declaredContextType: _declaredReturnType,
isVoidAllowed: false,
errorTemplate: templateInvalidReturnAsync)
..parent = statement;
}
}
Expand Down
25 changes: 20 additions & 5 deletions pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,13 @@ class TypeInferrerImpl implements TypeInferrer {
/// [contextType], and inserts an implicit downcast, inserts a tear-off, or
/// reports an error if appropriate.
///
/// If [declaredContextType] is provided, this is used instead of
/// [contextType] for reporting the type against which [expressionType] isn't
/// assignable. This is used when checking the assignability of return
/// statements in async functions in which the assignability is checked
/// against the future value type but the reporting should refer to the
/// declared return type.
///
/// If [runtimeCheckedType] is provided, this is used for the implicit cast,
/// otherwise [contextType] is used. This is used for return from async
/// where the returned expression is wrapped in a `Future`, if necessary,
Expand All @@ -395,6 +402,7 @@ class TypeInferrerImpl implements TypeInferrer {
Expression ensureAssignable(
DartType contextType, DartType expressionType, Expression expression,
{int fileOffset,
DartType declaredContextType,
DartType runtimeCheckedType,
bool isVoidAllowed: false,
Template<Message Function(DartType, DartType, bool)> errorTemplate}) {
Expand Down Expand Up @@ -444,8 +452,8 @@ class TypeInferrerImpl implements TypeInferrer {
break;
case AssignabilityKind.unassignable:
// Error: not assignable. Perform error recovery.
result = _wrapUnassignableExpression(
expression, expressionType, contextType, errorTemplate);
result = _wrapUnassignableExpression(expression, expressionType,
contextType, declaredContextType, errorTemplate);
break;
case AssignabilityKind.unassignableVoid:
// Error: not assignable. Perform error recovery.
Expand All @@ -465,8 +473,12 @@ class TypeInferrerImpl implements TypeInferrer {
case AssignabilityKind.unassignableTearoff:
TypedTearoff typedTearoff =
_tearOffCall(expression, expressionType, fileOffset);
result = _wrapUnassignableExpression(typedTearoff.tearoff,
typedTearoff.tearoffType, contextType, errorTemplate);
result = _wrapUnassignableExpression(
typedTearoff.tearoff,
typedTearoff.tearoffType,
contextType,
declaredContextType,
errorTemplate);
break;
case AssignabilityKind.unassignableCantTearoff:
result = _wrapTearoffErrorExpression(
Expand Down Expand Up @@ -505,6 +517,7 @@ class TypeInferrerImpl implements TypeInferrer {
Expression expression,
DartType expressionType,
DartType contextType,
DartType declaredContextType,
Template<Message Function(DartType, DartType, bool)> template) {
Expression errorNode = new AsExpression(
expression,
Expand All @@ -520,7 +533,9 @@ class TypeInferrerImpl implements TypeInferrer {
errorNode = helper.wrapInProblem(
errorNode,
(template ?? templateInvalidAssignmentError).withArguments(
expressionType, contextType, isNonNullableByDefault),
expressionType,
declaredContextType ?? contextType,
isNonNullableByDefault),
errorNode.fileOffset,
noLength);
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/front_end/messages.status
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,8 @@ InvalidContinueTarget/example: Fail
InvalidInitializer/example: Fail
InvalidPackageUri/analyzerCode: Fail
InvalidPackageUri/example: Fail
InvalidReturn/analyzerCode: Fail
InvalidReturnAsync/analyzerCode: Fail
InvalidSuperInInitializer/example: Fail
InvalidThisInInitializer/example: Fail
InvalidTypeVariableInSupertype/analyzerCode: Fail
Expand Down
10 changes: 10 additions & 0 deletions pkg/front_end/messages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3413,6 +3413,16 @@ ReturnWithoutExpressionAsync:
configuration: nnbd-strong
declaration: "Future<int> foo() async { return; }"

InvalidReturn:
template: "A value of type '#type' can't be returned from a function with return type '#type2'."
configuration: nnbd-strong
declaration: "int foo() { return true; }"

InvalidReturnAsync:
template: "A value of type '#type' can't be returned from an async function with return type '#type2'."
configuration: nnbd-strong
declaration: "Future<int> foo() async { return true; }"

ImplicitReturnNull:
template: "A non-null value must be returned since the return type '#type' doesn't allow null."
configuration: nnbd-strong
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Class {
@override
noSuchMethod(Object o, {String foo = ''}) => 42;
@override
toString({String foo = ''}) => 'foo';
}

main() {}
test() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Class {
@override
noSuchMethod(Object o, {String foo = ''}) => 42;
@override
toString({String foo = ''}) => 'foo';
}

main() {}
test() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bool Function(T) predicate<T>(bool Function(T) fn) => (T val) => fn(val);
void test() {}
void main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bool Function(T) predicate<T>(bool Function(T) fn) => (T val) => fn(val);
void main() {}
void test() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
void test() {}
main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
main() {}
void test() {}
8 changes: 4 additions & 4 deletions pkg/front_end/testcases/nnbd/issue41437a.dart.strong.expect
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
// ^
Expand Down Expand Up @@ -48,7 +48,7 @@ static method test3() → core::bool
static method test4() → asy::Future<core::bool> async
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
static method test5() → asy::Future<core::bool>
return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
Expand All @@ -66,7 +66,7 @@ static method test() → dynamic async {
function test4() → asy::Future<core::bool> async
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
function test5() → asy::Future<core::bool>
return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
// ^
Expand Down Expand Up @@ -150,7 +150,7 @@ static method test4() → asy::Future<core::bool> /* originally async */ {
return :async_completer.{asy::Completer::future};
}
static method test5() → asy::Future<core::bool>
return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
Expand Down Expand Up @@ -258,7 +258,7 @@ static method test() → dynamic /* originally async */ {
return :async_completer.{asy::Completer::future};
}
function test5() → asy::Future<core::bool>
return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
Expand Down
8 changes: 4 additions & 4 deletions pkg/front_end/testcases/nnbd/issue41437a.dart.weak.expect
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ library /*isNonNullableByDefault*/;
//
// Problems in library:
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
// ^
//
// pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
// pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
// - 'Future' is from 'dart:async'.
// Future<bool> test5() => getFutureNull(); // error
// ^
Expand Down Expand Up @@ -48,7 +48,7 @@ static method test3() → core::bool
static method test4() → asy::Future<core::bool> async
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
static method test5() → asy::Future<core::bool>
return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:18:25: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
Expand All @@ -66,7 +66,7 @@ static method test() → dynamic async {
function test4() → asy::Future<core::bool> async
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
function test5() → asy::Future<core::bool>
return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'Future<bool>'.
return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41437a.dart:27:27: Error: A value of type 'Future<dynamic>' can't be returned from a function with return type 'Future<bool>'.
- 'Future' is from 'dart:async'.
Future<bool> test5() => getFutureNull(); // error
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
Expand Down
Loading

0 comments on commit fd432fe

Please sign in to comment.