diff --git a/pkg/analyzer/lib/src/dart/resolver/body_inference_context.dart b/pkg/analyzer/lib/src/dart/resolver/body_inference_context.dart index 3552b09a0b6..53842812bec 100644 --- a/pkg/analyzer/lib/src/dart/resolver/body_inference_context.dart +++ b/pkg/analyzer/lib/src/dart/resolver/body_inference_context.dart @@ -10,6 +10,7 @@ import 'package:analyzer/src/dart/element/type.dart'; import 'package:analyzer/src/dart/element/type_provider.dart'; import 'package:analyzer/src/dart/element/type_system.dart'; +/// See https://github.com/dart-lang/language/blob/main/resources/type-system/inference.md#function-literal-return-type-inference class BodyInferenceContext { final TypeSystemImpl _typeSystem; final bool isAsynchronous; @@ -67,7 +68,12 @@ class BodyInferenceContext { void addReturnExpression(Expression? expression) { if (expression == null) { - _returnTypes.add(_typeProvider.nullType); + // If the enclosing function is not marked `sync*` or `async*`: + // For each `return;` statement in the block, update + // `T` to be `UP(Null, T)`. + if (!isGenerator) { + _returnTypes.add(_typeProvider.nullType); + } } else { var type = expression.typeOrThrow; if (isAsynchronous) { diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart index 58bad93b0f1..c2e24d3a2b5 100644 --- a/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/type_inference/function_expression_test.dart @@ -661,6 +661,55 @@ var v = () async* { _assertReturnType('() async* {', 'Stream'); } + test_noContext_returnType_asyncStar_blockBody_hasReturn_empty() async { + await resolveTestCode(r''' +var v = () async* { + yield 0; + return; +}; +'''); + _assertReturnType('() async* {', 'Stream'); + } + + test_noContext_returnType_asyncStar_blockBody_hasReturn_noYield() async { + await resolveTestCode(r''' +var v = () async* { + return; +}; +'''); + _assertReturnType('() async* {', 'Stream'); + } + + test_noContext_returnType_asyncStar_blockBody_lubNum() async { + await resolveTestCode(r''' +var v = () async* { + yield 0; + yield 1.1; +}; +'''); + _assertReturnType('() async* {', 'Stream'); + } + + test_noContext_returnType_asyncStar_blockBody_lubObject() async { + await resolveTestCode(r''' +var v = () async* { + yield 0; + yield ''; +}; +'''); + _assertReturnType('() async* {', 'Stream'); + } + + test_noContext_returnType_asyncStar_blockBody_lubWithNull() async { + await resolveTestCode(r''' +var v = () async* { + yield 0; + yield null; +}; +'''); + _assertReturnType('() async* {', 'Stream'); + } + test_noContext_returnType_sync_blockBody() async { await resolveTestCode(''' var v = () { @@ -875,6 +924,55 @@ var v = () sync* { _assertReturnType('() sync* {', 'Iterable'); } + test_noContext_returnType_syncStar_blockBody_hasReturn_empty() async { + await resolveTestCode(r''' +var v = () sync* { + yield 0; + return; +}; +'''); + _assertReturnType('() sync* {', 'Iterable'); + } + + test_noContext_returnType_syncStar_blockBody_hasReturn_noYield() async { + await resolveTestCode(r''' +var v = () sync* { + return; +}; +'''); + _assertReturnType('() sync* {', 'Iterable'); + } + + test_noContext_returnType_syncStar_blockBody_lubNum() async { + await resolveTestCode(r''' +var v = () sync* { + yield 0; + yield 1.1; +}; +'''); + _assertReturnType('() sync* {', 'Iterable'); + } + + test_noContext_returnType_syncStar_blockBody_lubObject() async { + await resolveTestCode(r''' +var v = () sync* { + yield 0; + yield ''; +}; +'''); + _assertReturnType('() sync* {', 'Iterable'); + } + + test_noContext_returnType_syncStar_blockBody_lubWithNull() async { + await resolveTestCode(r''' +var v = () sync* { + yield 0; + yield null; +}; +'''); + _assertReturnType('() sync* {', 'Iterable'); + } + test_targetBoundedByFunctionType_argumentTypeMismatch() async { await assertErrorsInCode( r'''