fix yield from return value on custom iterators (closes #15568)
diff --git a/Lib/test/test_pep380.py b/Lib/test/test_pep380.py
index 658bcb9..9569e10 100644
--- a/Lib/test/test_pep380.py
+++ b/Lib/test/test_pep380.py
@@ -940,6 +940,20 @@
         for stack in spam(eggs(gen())):
             self.assertTrue('spam' in stack and 'eggs' in stack)
 
+    def test_custom_iterator_return(self):
+        # See issue #15568
+        class MyIter:
+            def __iter__(self):
+                return self
+            def __next__(self):
+                raise StopIteration(42)
+        def gen():
+            nonlocal ret
+            ret = yield from MyIter()
+        ret = None
+        list(gen())
+        self.assertEqual(ret, 42)
+
 
 def test_main():
     from test import support
diff --git a/Misc/NEWS b/Misc/NEWS
index 6f7b0fc..d062df4 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@
 Core and Builtins
 -----------------
 
+- Issue #15568: Fix the return value of "yield from" when StopIteration is
+  raised by a custom iterator.
+
 - Issue #13119: sys.stdout and sys.stderr are now using "\r\n" newline on
   Windows, as Python 2.
 
diff --git a/Python/ceval.c b/Python/ceval.c
index 7e9318b..82bfcc6 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1843,7 +1843,7 @@
             } else {
                 _Py_IDENTIFIER(send);
                 if (u == Py_None)
-                    retval = PyIter_Next(x);
+                    retval = Py_TYPE(x)->tp_iternext(x);
                 else
                     retval = _PyObject_CallMethodId(x, &PyId_send, "O", u);
             }