Issue 40538. Revert YieldStatement changes after reverting language spec decision.

Bug: https://github.com/dart-lang/sdk/issues/40538
Change-Id: Idd563a15dc1e17e1271f823c33d015c73f720874
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136814
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
index f810900..9928a16 100644
--- a/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
@@ -17,11 +17,6 @@
 class YieldStatementResolver {
   final ResolverVisitor _resolver;
 
-  /// The element type required by the declared return type of the enclosing
-  /// function. Note, that for function expressions the declared return type
-  /// can be obtained by means of type inference.
-  DartType _elementType;
-
   YieldStatementResolver({
     @required ResolverVisitor resolver,
   }) : _resolver = resolver;
@@ -75,66 +70,62 @@
   ///
   /// This method should only be called in generator functions.
   void _checkForYieldOfInvalidType(YieldStatement node, bool isYieldEach) {
-    var expressionType = node.expression.staticType;
+    var declaredReturnType = _enclosingFunction.returnType;
 
-    if (node.star == null) {
-      if (!_typeSystem.isAssignableTo2(expressionType, _elementType)) {
-        _errorReporter.reportErrorForNode(
-          StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
-          node.expression,
-          [expressionType, _elementType],
-        );
-      }
-      return;
+    var expression = node.expression;
+    var expressionType = expression.staticType;
+
+    DartType impliedReturnType;
+    if (isYieldEach) {
+      impliedReturnType = expressionType;
+    } else if (_enclosingFunction.isSynchronous) {
+      impliedReturnType = _typeProvider.iterableType2(expressionType);
+    } else {
+      impliedReturnType = _typeProvider.streamType2(expressionType);
     }
 
-    DartType yieldElementType;
-    if (expressionType is InterfaceTypeImpl) {
-      var sequenceType = expressionType.asInstanceOf(
-        _typeProvider.iterableElement,
-      );
-      sequenceType ??= expressionType.asInstanceOf(
-        _typeProvider.streamElement,
-      );
-      if (sequenceType != null) {
-        yieldElementType = sequenceType.typeArguments[0];
-      }
-    }
-
-    if (yieldElementType == null) {
-      if (_typeSystem.isTop(expressionType) || expressionType.isDartCoreNull) {
-        yieldElementType = DynamicTypeImpl.instance;
-      } else {
+    if (declaredReturnType != null) {
+      if (!_typeSystem.isAssignableTo2(impliedReturnType, declaredReturnType)) {
         _errorReporter.reportErrorForNode(
           StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
-          node.expression,
-          [expressionType, _elementType],
+          expression,
+          [impliedReturnType, declaredReturnType],
         );
         return;
       }
     }
 
-    if (!_typeSystem.isAssignableTo2(yieldElementType, _elementType)) {
-      _errorReporter.reportErrorForNode(
-        StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
-        node.expression,
-        [yieldElementType, _elementType],
-      );
+    if (isYieldEach) {
+      // Since the declared return type might have been "dynamic", we need to
+      // also check that the implied return type is assignable to generic
+      // Iterable/Stream.
+      DartType requiredReturnType;
+      if (_enclosingFunction.isSynchronous) {
+        requiredReturnType = _typeProvider.iterableDynamicType;
+      } else {
+        requiredReturnType = _typeProvider.streamDynamicType;
+      }
+
+      if (!_typeSystem.isAssignableTo2(impliedReturnType, requiredReturnType)) {
+        _errorReporter.reportErrorForNode(
+          StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
+          expression,
+          [impliedReturnType, requiredReturnType],
+        );
+      }
     }
   }
 
   void _computeElementType(YieldStatement node) {
-    _elementType = _resolver.inferenceContext.returnContext;
-    if (_elementType != null) {
-      var contextType = _elementType;
+    var elementType = _resolver.inferenceContext.returnContext;
+    if (elementType != null) {
+      var contextType = elementType;
       if (node.star != null) {
         contextType = _enclosingFunction.isSynchronous
-            ? _typeProvider.iterableType2(_elementType)
-            : _typeProvider.streamType2(_elementType);
+            ? _typeProvider.iterableType2(elementType)
+            : _typeProvider.streamType2(elementType);
       }
       InferenceContext.setType(node.expression, contextType);
-    } else {
-      _elementType ??= DynamicTypeImpl.instance;
     }
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart
index 7892e62..8963c73 100644
--- a/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart
@@ -19,14 +19,18 @@
 @reflectiveTest
 class YieldOfInvalidTypeTest extends DriverResolutionTest {
   test_none_asyncStar_dynamic_to_streamInt() async {
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode(
+        '''
 import 'dart:async';
 
 Stream<int> f() async* {
   dynamic a = 0;
   yield a;
 }
-''');
+''',
+        expectedErrorsByNullability(nullable: [
+          error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 72, 1),
+        ], legacy: []));
   }
 
   test_none_asyncStar_int_to_basic() async {
@@ -36,6 +40,7 @@
 }
 ''', [
       error(StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 0, 3),
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 25, 1),
     ]);
   }
 
@@ -99,12 +104,16 @@
   }
 
   test_none_syncStar_dynamic_to_iterableInt() async {
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode(
+        '''
 Iterable<int> f() sync* {
   dynamic a = 0;
   yield a;
 }
-''');
+''',
+        expectedErrorsByNullability(nullable: [
+          error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 51, 1),
+        ], legacy: []));
   }
 
   test_none_syncStar_int_to_basic() async {
@@ -114,6 +123,7 @@
 }
 ''', [
       error(StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, 0, 3),
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 24, 1),
     ]);
   }
 
@@ -217,23 +227,27 @@
   }
 
   test_star_asyncStar_iterableInt_to_dynamic() async {
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode('''
 f() async* {
   var a = <int>[];
   yield* a;
 }
-''');
+''', [
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 41, 1),
+    ]);
   }
 
   test_star_asyncStar_iterableInt_to_streamInt() async {
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode('''
 import 'dart:async';
 
 Stream<int> f() async* {
   var a = <int>[];
   yield* a;
 }
-''');
+''', [
+      error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 75, 1),
+    ]);
   }
 
   test_star_asyncStar_iterableString_to_streamInt() async {
@@ -262,7 +276,8 @@
   }
 
   test_star_asyncStar_streamDynamic_to_streamInt() async {
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode(
+        '''
 import 'dart:async';
 
 Stream<int> f() async* {
@@ -270,7 +285,10 @@
 }
 
 Stream g() => throw 0;
-''');
+''',
+        expectedErrorsByNullability(nullable: [
+          error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 56, 3),
+        ], legacy: []));
   }
 
   test_star_asyncStar_streamInt_to_dynamic() async {
@@ -375,13 +393,17 @@
   }
 
   test_star_syncStar_iterableDynamic_to_iterableInt() async {
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode(
+        '''
 Iterable<int> f() sync* {
   yield* g();
 }
 
 Iterable g() => throw 0;
-''');
+''',
+        expectedErrorsByNullability(nullable: [
+          error(StaticTypeWarningCode.YIELD_OF_INVALID_TYPE, 35, 3),
+        ], legacy: []));
   }
 
   test_star_syncStar_iterableInt_to_dynamic() async {
@@ -423,4 +445,7 @@
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
     ..contextFeatures = FeatureSet.forTesting(
         sdkVersion: '2.7.0', additionalFeatures: [Feature.non_nullable]);
+
+  @override
+  bool get typeToStringWithNullability => true;
 }