Make PyIter_Next() a little smarter (wrt its knowledge of iterator
internals) so clients can be a lot dumber (wrt their knowledge).
diff --git a/Include/abstract.h b/Include/abstract.h
index 1dae5f1..ac9e568 100644
--- a/Include/abstract.h
+++ b/Include/abstract.h
@@ -484,9 +484,8 @@
      DL_IMPORT(PyObject *) PyIter_Next(PyObject *);
      /* Takes an iterator object and calls its tp_iternext slot,
 	returning the next value.  If the iterator is exhausted,
-	this can return NULL without setting an exception, *or*
-	NULL with a StopIteration exception.
-	NULL with any other exception  means an error occurred. */
+	this returns NULL without setting an exception.
+	NULL with an exception means an error occurred. */
 
 /*  Number Protocol:*/
 
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 8ee1e5a..7133867 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1276,17 +1276,9 @@
 	for (i = 0; ; i++) {
 		PyObject *item = PyIter_Next(it);
 		if (item == NULL) {
-			/* We're out of here in any case, but if this is a
-			 * StopIteration exception it's expected, but if
-			 * any other kind of exception it's an error.
-			 */
 			if (PyErr_Occurred()) {
-				if (PyErr_ExceptionMatches(PyExc_StopIteration))
-					PyErr_Clear();
-				else {
-					Py_DECREF(result);
-					result = NULL;
-				}
+				Py_DECREF(result);
+				result = NULL;
 			}
 			break;
 		}
@@ -1796,14 +1788,27 @@
 	}
 }
 
+/* Return next item.
+ * If an error occurs, return NULL.  PyErr_Occurred() will be true.
+ * If the iteration terminates normally, return NULL and clear the
+ * PyExc_StopIteration exception (if it was set).  PyErr_Occurred()
+ * will be false.
+ * Else return the next object.  PyErr_Occurred() will be false.
+ */
 PyObject *
 PyIter_Next(PyObject *iter)
 {
+	PyObject *result;
 	if (!PyIter_Check(iter)) {
 		PyErr_Format(PyExc_TypeError,
 			     "'%.100s' object is not an iterator",
 			     iter->ob_type->tp_name);
 		return NULL;
 	}
-	return (*iter->ob_type->tp_iternext)(iter);
+	result = (*iter->ob_type->tp_iternext)(iter);
+	if (result == NULL &&
+	    PyErr_Occurred() &&
+	    PyErr_ExceptionMatches(PyExc_StopIteration))
+		PyErr_Clear();
+	return result;
 }
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 5209607..4a51ccd 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -164,7 +164,7 @@
 {
 	PyObject *func, *seq, *result, *it;
 	int len;   /* guess for result list size */
-	register int i, j;
+	register int j;
 
 	if (!PyArg_ParseTuple(args, "OO:filter", &func, &seq))
 		return NULL;
@@ -204,22 +204,15 @@
 	}
 
 	/* Build the result list. */
-	for (i = j = 0; ; ++i) {
+	j = 0;
+	for (;;) {
 		PyObject *item, *good;
 		int ok;
 
 		item = PyIter_Next(it);
 		if (item == NULL) {
-			/* We're out of here in any case, but if this is a
-			 * StopIteration exception it's expected, but if
-			 * any other kind of exception it's an error.
-			 */
-			if (PyErr_Occurred()) {
-				if (PyErr_ExceptionMatches(PyExc_StopIteration))
-					PyErr_Clear();
-				else
-					goto Fail_result_it;
-			}
+			if (PyErr_Occurred())
+				goto Fail_result_it;
 			break;
 		}
 
@@ -1030,24 +1023,14 @@
 				if (item)
 					++numactive;
 				else {
-					/* StopIteration is *implied* by a
-					 * NULL return from PyIter_Next() if
-					 * PyErr_Occurred() is false.
-					 */
 					if (PyErr_Occurred()) {
-						if (PyErr_ExceptionMatches(
-						    PyExc_StopIteration))
-							PyErr_Clear();
-						else {
-							Py_XDECREF(alist);
-							goto Fail_1;
-						}
+						Py_XDECREF(alist);
+						goto Fail_1;
 					}
 					Py_INCREF(Py_None);
 					item = Py_None;
 					sqp->saw_StopIteration = 1;
 				}
-
 			}
 			if (alist)
 				PyTuple_SET_ITEM(alist, j, item);
@@ -1445,7 +1428,6 @@
 static PyObject *
 min_max(PyObject *args, int op)
 {
-	int i;
 	PyObject *v, *w, *x, *it;
 
 	if (PyTuple_Size(args) > 1)
@@ -1458,21 +1440,13 @@
 		return NULL;
 
 	w = NULL;  /* the result */
-	for (i = 0; ; i++) {
+	for (;;) {
 		x = PyIter_Next(it);
 		if (x == NULL) {
-			/* We're out of here in any case, but if this is a
-			 * StopIteration exception it's expected, but if
-			 * any other kind of exception it's an error.
-			 */
 			if (PyErr_Occurred()) {
-				if (PyErr_ExceptionMatches(PyExc_StopIteration))
-					PyErr_Clear();
-				else {
-					Py_XDECREF(w);
-					Py_DECREF(it);
-					return NULL;
-				}
+				Py_XDECREF(w);
+				Py_DECREF(it);
+				return NULL;
 			}
 			break;
 		}
@@ -1880,16 +1854,9 @@
 
 		op2 = PyIter_Next(it);
 		if (op2 == NULL) {
-			/* StopIteration is *implied* by a NULL return from
-			 * PyIter_Next() if PyErr_Occurred() is false.
-			 */
-			if (PyErr_Occurred()) {
-				if (PyErr_ExceptionMatches(PyExc_StopIteration))
-					PyErr_Clear();
-				else
-					goto Fail;
-			}
-			break;
+			if (PyErr_Occurred())
+				goto Fail;
+ 			break;
 		}
 
 		if (result == NULL)
diff --git a/Python/ceval.c b/Python/ceval.c
index df160f2..0cdd019 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1894,11 +1894,9 @@
 				PUSH(x);
 				continue;
 			}
-			if (!PyErr_Occurred() ||
-			    PyErr_ExceptionMatches(
-				    PyExc_StopIteration))
-			{
-				x = v = POP();
+			if (!PyErr_Occurred()) {
+				/* iterator ended normally */
+ 				x = v = POP();
 				Py_DECREF(v);
 				JUMPBY(oparg);
 				continue;