Skip to content

Commit 759d5a5

Browse files
scheglovCommit Queue
authored and
Commit Queue
committed
Extension types. Report when await of not Future subtype.
Change-Id: I51b825c1d48b55866d8112ab6421c7937a0c7575 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/318024 Reviewed-by: Phil Quitslund <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent ce71644 commit 759d5a5

File tree

7 files changed

+74
-0
lines changed

7 files changed

+74
-0
lines changed

pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ CompileTimeErrorCode.AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER:
212212
The fix is to remove the `late` modifier.
213213
CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT:
214214
status: hasFix
215+
CompileTimeErrorCode.AWAIT_OF_EXTENSION_TYPE_NOT_FUTURE:
216+
status: noFix
215217
CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY:
216218
status: noFix
217219
notes: |-

pkg/analyzer/lib/src/error/codes.g.dart

+8
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,14 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
232232
"Try marking the function body with either 'async' or 'async*'.",
233233
);
234234

235+
static const CompileTimeErrorCode AWAIT_OF_EXTENSION_TYPE_NOT_FUTURE =
236+
CompileTimeErrorCode(
237+
'AWAIT_OF_EXTENSION_TYPE_NOT_FUTURE',
238+
"The 'await' expression can't be used for an expression with an extension "
239+
"type that is not a subtype of 'Future'.",
240+
correctionMessage: "Try updating the extension type to implement 'Future'.",
241+
);
242+
235243
/// Parameters:
236244
/// 0: the name of the base class being implemented
237245
static const CompileTimeErrorCode BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY =

pkg/analyzer/lib/src/error/error_code_values.g.dart

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const List<ErrorCode> errorCodeValues = [
6363
CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT,
6464
CompileTimeErrorCode.AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER,
6565
CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT,
66+
CompileTimeErrorCode.AWAIT_OF_EXTENSION_TYPE_NOT_FUTURE,
6667
CompileTimeErrorCode.BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY,
6768
CompileTimeErrorCode.BASE_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY,
6869
CompileTimeErrorCode.BODY_MIGHT_COMPLETE_NORMALLY,

pkg/analyzer/lib/src/generated/error_verifier.dart

+18
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,9 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
354354
if (_isNonNullableByDefault) {
355355
checkForUseOfVoidResult(node.expression);
356356
}
357+
357358
_checkForAwaitInLateLocalVariableInitializer(node);
359+
_checkForAwaitOfExtensionTypeNotFuture(node);
358360
super.visitAwaitExpression(node);
359361
}
360362

@@ -1784,6 +1786,22 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
17841786
}
17851787
}
17861788

1789+
void _checkForAwaitOfExtensionTypeNotFuture(AwaitExpression node) {
1790+
final expression = node.expression;
1791+
final expressionType = expression.typeOrThrow;
1792+
if (expressionType.element is ExtensionTypeElement) {
1793+
final anyFuture = typeSystem.typeProvider.futureType(
1794+
typeSystem.objectQuestion,
1795+
);
1796+
if (!typeSystem.isSubtypeOf(expressionType, anyFuture)) {
1797+
errorReporter.reportErrorForToken(
1798+
CompileTimeErrorCode.AWAIT_OF_EXTENSION_TYPE_NOT_FUTURE,
1799+
node.awaitKeyword,
1800+
);
1801+
}
1802+
}
1803+
}
1804+
17871805
/// Verifies that the nodes don't reference `Function` from `dart:core`.
17881806
void _checkForBadFunctionUse({
17891807
required NamedType? superclass,

pkg/analyzer/messages.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,9 @@ CompileTimeErrorCode:
11271127
16.30 Await Expressions: It is a compile-time error if the function
11281128
immediately enclosing _a_ is not declared asynchronous. (Where _a_ is the
11291129
await expression.)
1130+
AWAIT_OF_EXTENSION_TYPE_NOT_FUTURE:
1131+
problemMessage: "The 'await' expression can't be used for an expression with an extension type that is not a subtype of 'Future'."
1132+
correctionMessage: Try updating the extension type to implement 'Future'.
11301133
BASE_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY:
11311134
sharedName: INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
11321135
problemMessage: "The class '{0}' can't be implemented outside of its library because it's a base class."
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:analyzer/src/error/codes.dart';
6+
import 'package:test_reflective_loader/test_reflective_loader.dart';
7+
8+
import '../dart/resolution/context_collection_resolution.dart';
9+
10+
main() {
11+
defineReflectiveSuite(() {
12+
defineReflectiveTests(AwaitOfExtensionTypeNotFutureTest);
13+
});
14+
}
15+
16+
@reflectiveTest
17+
class AwaitOfExtensionTypeNotFutureTest extends PubPackageResolutionTest {
18+
test_hasError() async {
19+
await assertErrorsInCode(r'''
20+
extension type A(int it) {}
21+
22+
void f(A a) async {
23+
await a;
24+
}
25+
''', [
26+
error(CompileTimeErrorCode.AWAIT_OF_EXTENSION_TYPE_NOT_FUTURE, 51, 5),
27+
]);
28+
}
29+
30+
test_noError() async {
31+
await assertNoErrorsInCode(r'''
32+
extension type A(Future<int> it) implements Future<int> {}
33+
34+
void f(A a) async {
35+
await a;
36+
}
37+
''');
38+
}
39+
}

pkg/analyzer/test/src/diagnostics/test_all.dart

+3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ import 'async_keyword_used_as_identifier_test.dart'
4141
import 'await_in_late_local_variable_initializer_test.dart'
4242
as await_in_late_local_variable_initializer;
4343
import 'await_in_wrong_context_test.dart' as await_in_wrong_context;
44+
import 'await_of_extension_type_not_future_test.dart'
45+
as await_of_extension_type_not_future;
4446
import 'base_class_implemented_outside_of_library_test.dart'
4547
as base_class_implemented_outside_of_library;
4648
import 'base_mixin_implemented_outside_of_library_test.dart'
@@ -901,6 +903,7 @@ main() {
901903
async_keyword_used_as_identifier.main();
902904
await_in_late_local_variable_initializer.main();
903905
await_in_wrong_context.main();
906+
await_of_extension_type_not_future.main();
904907
base_class_implemented_outside_of_library.main();
905908
base_mixin_implemented_outside_of_library.main();
906909
binary_operator_written_out.main();

0 commit comments

Comments
 (0)