Skip to content

Commit fd432fe

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Update messages for invalid returns
Closes #42527 Change-Id: Ic240dd7a8822c85c550941923bf9ce3b5cfe0dba Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153348 Commit-Queue: Johnni Winther <[email protected]> Reviewed-by: Erik Ernst <[email protected]>
1 parent 9ab7a5e commit fd432fe

File tree

125 files changed

+444
-208
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+444
-208
lines changed

pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,6 +2040,84 @@ Message _withArgumentsInvalidCastTopLevelFunction(
20402040
arguments: {'type': _type, 'type2': _type2});
20412041
}
20422042

2043+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2044+
const Template<
2045+
Message Function(
2046+
DartType _type,
2047+
DartType _type2,
2048+
bool
2049+
isNonNullableByDefault)> templateInvalidReturn = const Template<
2050+
Message Function(
2051+
DartType _type, DartType _type2, bool isNonNullableByDefault)>(
2052+
messageTemplate:
2053+
r"""A value of type '#type' can't be returned from a function with return type '#type2'.""",
2054+
withArguments: _withArgumentsInvalidReturn);
2055+
2056+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2057+
const Code<
2058+
Message Function(
2059+
DartType _type, DartType _type2, bool isNonNullableByDefault)>
2060+
codeInvalidReturn = const Code<
2061+
Message Function(
2062+
DartType _type, DartType _type2, bool isNonNullableByDefault)>(
2063+
"InvalidReturn",
2064+
templateInvalidReturn,
2065+
);
2066+
2067+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2068+
Message _withArgumentsInvalidReturn(
2069+
DartType _type, DartType _type2, bool isNonNullableByDefault) {
2070+
TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
2071+
List<Object> typeParts = labeler.labelType(_type);
2072+
List<Object> type2Parts = labeler.labelType(_type2);
2073+
String type = typeParts.join();
2074+
String type2 = type2Parts.join();
2075+
return new Message(codeInvalidReturn,
2076+
message:
2077+
"""A value of type '${type}' can't be returned from a function with return type '${type2}'.""" +
2078+
labeler.originMessages,
2079+
arguments: {'type': _type, 'type2': _type2});
2080+
}
2081+
2082+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2083+
const Template<
2084+
Message Function(
2085+
DartType _type,
2086+
DartType _type2,
2087+
bool
2088+
isNonNullableByDefault)> templateInvalidReturnAsync = const Template<
2089+
Message Function(
2090+
DartType _type, DartType _type2, bool isNonNullableByDefault)>(
2091+
messageTemplate:
2092+
r"""A value of type '#type' can't be returned from an async function with return type '#type2'.""",
2093+
withArguments: _withArgumentsInvalidReturnAsync);
2094+
2095+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2096+
const Code<
2097+
Message Function(
2098+
DartType _type, DartType _type2, bool isNonNullableByDefault)>
2099+
codeInvalidReturnAsync = const Code<
2100+
Message Function(
2101+
DartType _type, DartType _type2, bool isNonNullableByDefault)>(
2102+
"InvalidReturnAsync",
2103+
templateInvalidReturnAsync,
2104+
);
2105+
2106+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2107+
Message _withArgumentsInvalidReturnAsync(
2108+
DartType _type, DartType _type2, bool isNonNullableByDefault) {
2109+
TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
2110+
List<Object> typeParts = labeler.labelType(_type);
2111+
List<Object> type2Parts = labeler.labelType(_type2);
2112+
String type = typeParts.join();
2113+
String type2 = type2Parts.join();
2114+
return new Message(codeInvalidReturnAsync,
2115+
message:
2116+
"""A value of type '${type}' can't be returned from an async function with return type '${type2}'.""" +
2117+
labeler.originMessages,
2118+
arguments: {'type': _type, 'type2': _type2});
2119+
}
2120+
20432121
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
20442122
const Template<
20452123
Message Function(DartType _type, DartType _type2, DartType _type3,

pkg/front_end/lib/src/fasta/type_inference/closure_context.dart

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,8 @@ class _SyncClosureContext implements ClosureContext {
195195
// nor dynamic, and S is void.
196196
statement.expression = inferrer.helper.wrapInProblem(
197197
statement.expression,
198-
messageVoidExpression,
198+
templateInvalidReturn.withArguments(expressionType,
199+
_declaredReturnType, inferrer.isNonNullableByDefault),
199200
statement.expression.fileOffset,
200201
noLength)
201202
..parent = statement;
@@ -204,7 +205,9 @@ class _SyncClosureContext implements ClosureContext {
204205
// S is not assignable to T.
205206
Expression expression = inferrer.ensureAssignable(
206207
_returnContext, expressionType, statement.expression,
207-
fileOffset: statement.expression.fileOffset, isVoidAllowed: true);
208+
fileOffset: statement.expression.fileOffset,
209+
isVoidAllowed: true,
210+
errorTemplate: templateInvalidReturn);
208211
statement.expression = expression..parent = statement;
209212
}
210213
}
@@ -481,7 +484,8 @@ class _AsyncClosureContext implements ClosureContext {
481484
// flatten(S) is neither void, dynamic, Null.
482485
statement.expression = inferrer.helper.wrapInProblem(
483486
new NullLiteral()..fileOffset = statement.fileOffset,
484-
messageReturnFromVoidFunction,
487+
templateInvalidReturnAsync.withArguments(expressionType,
488+
_declaredReturnType, inferrer.isNonNullableByDefault),
485489
statement.expression.fileOffset,
486490
noLength)
487491
..parent = statement;
@@ -492,25 +496,11 @@ class _AsyncClosureContext implements ClosureContext {
492496
// nor dynamic, and flatten(S) is void.
493497
statement.expression = inferrer.helper.wrapInProblem(
494498
new NullLiteral()..fileOffset = statement.fileOffset,
495-
messageVoidExpression,
499+
templateInvalidReturnAsync.withArguments(expressionType,
500+
_declaredReturnType, inferrer.isNonNullableByDefault),
496501
statement.expression.fileOffset,
497502
noLength)
498503
..parent = statement;
499-
/* } else if (flattenedExpressionType is! VoidType &&
500-
!inferrer.isAssignable(futureValueType, expressionType) &&
501-
!inferrer.typeSchemaEnvironment
502-
.performNullabilityAwareSubtypeCheck(
503-
flattenedExpressionType, futureValueType)
504-
.isSubtypeWhenUsingNullabilities()) {
505-
// It is a compile-time error if s is `return e;`, flatten(S) is not
506-
// void, S is not assignable to T_v, and flatten(S) is not a subtype
507-
// of T_v.
508-
statement.expression = inferrer.helper.wrapInProblem(
509-
new NullLiteral()..fileOffset = statement.fileOffset,
510-
messageReturnWithoutExpressionAsync,
511-
statement.expression.fileOffset,
512-
noLength)
513-
..parent = statement;*/
514504
} else if (flattenedExpressionType is! VoidType &&
515505
!inferrer.typeSchemaEnvironment
516506
.performNullabilityAwareSubtypeCheck(
@@ -523,7 +513,9 @@ class _AsyncClosureContext implements ClosureContext {
523513
futureValueType, expressionType, statement.expression,
524514
fileOffset: statement.expression.fileOffset,
525515
runtimeCheckedType: _returnContext,
526-
isVoidAllowed: false)
516+
declaredContextType: _declaredReturnType,
517+
isVoidAllowed: false,
518+
errorTemplate: templateInvalidReturnAsync)
527519
..parent = statement;
528520
}
529521
}

pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,13 @@ class TypeInferrerImpl implements TypeInferrer {
387387
/// [contextType], and inserts an implicit downcast, inserts a tear-off, or
388388
/// reports an error if appropriate.
389389
///
390+
/// If [declaredContextType] is provided, this is used instead of
391+
/// [contextType] for reporting the type against which [expressionType] isn't
392+
/// assignable. This is used when checking the assignability of return
393+
/// statements in async functions in which the assignability is checked
394+
/// against the future value type but the reporting should refer to the
395+
/// declared return type.
396+
///
390397
/// If [runtimeCheckedType] is provided, this is used for the implicit cast,
391398
/// otherwise [contextType] is used. This is used for return from async
392399
/// where the returned expression is wrapped in a `Future`, if necessary,
@@ -395,6 +402,7 @@ class TypeInferrerImpl implements TypeInferrer {
395402
Expression ensureAssignable(
396403
DartType contextType, DartType expressionType, Expression expression,
397404
{int fileOffset,
405+
DartType declaredContextType,
398406
DartType runtimeCheckedType,
399407
bool isVoidAllowed: false,
400408
Template<Message Function(DartType, DartType, bool)> errorTemplate}) {
@@ -444,8 +452,8 @@ class TypeInferrerImpl implements TypeInferrer {
444452
break;
445453
case AssignabilityKind.unassignable:
446454
// Error: not assignable. Perform error recovery.
447-
result = _wrapUnassignableExpression(
448-
expression, expressionType, contextType, errorTemplate);
455+
result = _wrapUnassignableExpression(expression, expressionType,
456+
contextType, declaredContextType, errorTemplate);
449457
break;
450458
case AssignabilityKind.unassignableVoid:
451459
// Error: not assignable. Perform error recovery.
@@ -465,8 +473,12 @@ class TypeInferrerImpl implements TypeInferrer {
465473
case AssignabilityKind.unassignableTearoff:
466474
TypedTearoff typedTearoff =
467475
_tearOffCall(expression, expressionType, fileOffset);
468-
result = _wrapUnassignableExpression(typedTearoff.tearoff,
469-
typedTearoff.tearoffType, contextType, errorTemplate);
476+
result = _wrapUnassignableExpression(
477+
typedTearoff.tearoff,
478+
typedTearoff.tearoffType,
479+
contextType,
480+
declaredContextType,
481+
errorTemplate);
470482
break;
471483
case AssignabilityKind.unassignableCantTearoff:
472484
result = _wrapTearoffErrorExpression(
@@ -505,6 +517,7 @@ class TypeInferrerImpl implements TypeInferrer {
505517
Expression expression,
506518
DartType expressionType,
507519
DartType contextType,
520+
DartType declaredContextType,
508521
Template<Message Function(DartType, DartType, bool)> template) {
509522
Expression errorNode = new AsExpression(
510523
expression,
@@ -520,7 +533,9 @@ class TypeInferrerImpl implements TypeInferrer {
520533
errorNode = helper.wrapInProblem(
521534
errorNode,
522535
(template ?? templateInvalidAssignmentError).withArguments(
523-
expressionType, contextType, isNonNullableByDefault),
536+
expressionType,
537+
declaredContextType ?? contextType,
538+
isNonNullableByDefault),
524539
errorNode.fileOffset,
525540
noLength);
526541
}

pkg/front_end/messages.status

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,8 @@ InvalidContinueTarget/example: Fail
415415
InvalidInitializer/example: Fail
416416
InvalidPackageUri/analyzerCode: Fail
417417
InvalidPackageUri/example: Fail
418+
InvalidReturn/analyzerCode: Fail
419+
InvalidReturnAsync/analyzerCode: Fail
418420
InvalidSuperInInitializer/example: Fail
419421
InvalidThisInInitializer/example: Fail
420422
InvalidTypeVariableInSupertype/analyzerCode: Fail

pkg/front_end/messages.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3413,6 +3413,16 @@ ReturnWithoutExpressionAsync:
34133413
configuration: nnbd-strong
34143414
declaration: "Future<int> foo() async { return; }"
34153415

3416+
InvalidReturn:
3417+
template: "A value of type '#type' can't be returned from a function with return type '#type2'."
3418+
configuration: nnbd-strong
3419+
declaration: "int foo() { return true; }"
3420+
3421+
InvalidReturnAsync:
3422+
template: "A value of type '#type' can't be returned from an async function with return type '#type2'."
3423+
configuration: nnbd-strong
3424+
declaration: "Future<int> foo() async { return true; }"
3425+
34163426
ImplicitReturnNull:
34173427
template: "A non-null value must be returned since the return type '#type' doesn't allow null."
34183428
configuration: nnbd-strong
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class Class {
2+
@override
3+
noSuchMethod(Object o, {String foo = ''}) => 42;
4+
@override
5+
toString({String foo = ''}) => 'foo';
6+
}
7+
8+
main() {}
9+
test() {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class Class {
2+
@override
3+
noSuchMethod(Object o, {String foo = ''}) => 42;
4+
@override
5+
toString({String foo = ''}) => 'foo';
6+
}
7+
8+
main() {}
9+
test() {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bool Function(T) predicate<T>(bool Function(T) fn) => (T val) => fn(val);
2+
void test() {}
3+
void main() {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bool Function(T) predicate<T>(bool Function(T) fn) => (T val) => fn(val);
2+
void main() {}
3+
void test() {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
void test() {}
2+
main() {}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
main() {}
2+
void test() {}

pkg/front_end/testcases/nnbd/issue41437a.dart.strong.expect

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ library /*isNonNullableByDefault*/;
22
//
33
// Problems in library:
44
//
5-
// 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>'.
5+
// 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>'.
66
// - 'Future' is from 'dart:async'.
77
// Future<bool> test5() => getFutureNull(); // error
88
// ^
99
//
10-
// 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>'.
10+
// 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>'.
1111
// - 'Future' is from 'dart:async'.
1212
// Future<bool> test5() => getFutureNull(); // error
1313
// ^
@@ -48,7 +48,7 @@ static method test3() → core::bool
4848
static method test4() → asy::Future<core::bool> async
4949
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
5050
static method test5() → asy::Future<core::bool>
51-
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>'.
51+
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>'.
5252
- 'Future' is from 'dart:async'.
5353
Future<bool> test5() => getFutureNull(); // error
5454
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -66,7 +66,7 @@ static method test() → dynamic async {
6666
function test4() → asy::Future<core::bool> async
6767
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
6868
function test5() → asy::Future<core::bool>
69-
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>'.
69+
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>'.
7070
- 'Future' is from 'dart:async'.
7171
Future<bool> test5() => getFutureNull(); // error
7272
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;

pkg/front_end/testcases/nnbd/issue41437a.dart.strong.transformed.expect

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ library /*isNonNullableByDefault*/;
22
//
33
// Problems in library:
44
//
5-
// 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>'.
5+
// 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>'.
66
// - 'Future' is from 'dart:async'.
77
// Future<bool> test5() => getFutureNull(); // error
88
// ^
99
//
10-
// 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>'.
10+
// 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>'.
1111
// - 'Future' is from 'dart:async'.
1212
// Future<bool> test5() => getFutureNull(); // error
1313
// ^
@@ -150,7 +150,7 @@ static method test4() → asy::Future<core::bool> /* originally async */ {
150150
return :async_completer.{asy::Completer::future};
151151
}
152152
static method test5() → asy::Future<core::bool>
153-
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>'.
153+
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>'.
154154
- 'Future' is from 'dart:async'.
155155
Future<bool> test5() => getFutureNull(); // error
156156
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -258,7 +258,7 @@ static method test() → dynamic /* originally async */ {
258258
return :async_completer.{asy::Completer::future};
259259
}
260260
function test5() → asy::Future<core::bool>
261-
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>'.
261+
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>'.
262262
- 'Future' is from 'dart:async'.
263263
Future<bool> test5() => getFutureNull(); // error
264264
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;

pkg/front_end/testcases/nnbd/issue41437a.dart.weak.expect

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ library /*isNonNullableByDefault*/;
22
//
33
// Problems in library:
44
//
5-
// 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>'.
5+
// 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>'.
66
// - 'Future' is from 'dart:async'.
77
// Future<bool> test5() => getFutureNull(); // error
88
// ^
99
//
10-
// 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>'.
10+
// 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>'.
1111
// - 'Future' is from 'dart:async'.
1212
// Future<bool> test5() => getFutureNull(); // error
1313
// ^
@@ -48,7 +48,7 @@ static method test3() → core::bool
4848
static method test4() → asy::Future<core::bool> async
4949
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
5050
static method test5() → asy::Future<core::bool>
51-
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>'.
51+
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>'.
5252
- 'Future' is from 'dart:async'.
5353
Future<bool> test5() => getFutureNull(); // error
5454
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;
@@ -66,7 +66,7 @@ static method test() → dynamic async {
6666
function test4() → asy::Future<core::bool> async
6767
return await self::getFutureNull() as{TypeError,ForDynamic,ForNonNullableByDefault} FutureOr<core::bool>;
6868
function test5() → asy::Future<core::bool>
69-
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>'.
69+
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>'.
7070
- 'Future' is from 'dart:async'.
7171
Future<bool> test5() => getFutureNull(); // error
7272
^" in self::getFutureNull() as{TypeError,ForNonNullableByDefault} asy::Future<core::bool>;

0 commit comments

Comments
 (0)