PyType (@Nullable PyType iterableType, @Nullable PyExpression source, @NotNull PsiElement anchor, @NotNull TypeEvalContext context) { if (iterableType instanceof PyTupleType tupleType) { return tupleType.getIteratedItemType(); } else if (iterableType instanceof PyUnionType) { return ((PyUnionType)iterableType).map(member -> getIterationType(member, source, anchor, context)); } else if (iterableType != null && PyABCUtil.isSubtype(iterableType, PyNames.ITERABLE, context)) { final PyFunction iterateMethod = findMethodByName(iterableType, PyNames.ITER, context); if (iterateMethod != null) { final PyType iterateReturnType = getContextSensitiveType(iterateMethod, context, source); return getIteratedItemType(iterateReturnType, source, anchor, context, false); } final Ref<PyType> nextMethodCallType = getNextMethodCallType(iterableType, source, anchor, context, false); if (nextMethodCallType != null) { return nextMethodCallType.get(); } final PyFunction getItem = findMethodByName(iterableType, PyNames.GETITEM, context); if (getItem != null) { return getContextSensitiveType(getItem, context, source); } } else if (iterableType != null && PyABCUtil.isSubtype(iterableType, PyNames.ASYNC_ITERABLE, context)) { final PyFunction iterateMethod = findMethodByName(iterableType, PyNames.AITER, context); if (iterateMethod != null) { final PyType iterateReturnType = getContextSensitiveType(iterateMethod, context, source); return getIteratedItemType(iterateReturnType, source, anchor, context, true); } } return null; }