@Override
  public void visitForeachStatement(@NotNull PsiForeachStatement statement) {
    super.visitForeachStatement(statement);
    final PsiExpression value = statement.getIteratedValue();
    final PsiParameter psiParameter = statement.getIterationParameter();
    if (value != null) {
      final TypeView typeView = new TypeView(value);
      PsiType psiType = typeView.getType();
      if (psiType instanceof PsiArrayType) {
        psiType = ((PsiArrayType)psiType).getComponentType();
      }
      else if (psiType instanceof PsiClassType) {
        final PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)psiType).resolveGenerics();
        final PsiClass psiClass = resolveResult.getElement();
        if (psiClass == null) return;
        final PsiType targetTypeParameter = getTargetTypeParameter(psiClass, value, typeView);
        if (targetTypeParameter == null) return;
        psiType = resolveResult.getSubstitutor().substitute(targetTypeParameter);
        if (psiType instanceof PsiWildcardType) {
          psiType = ((PsiWildcardType)psiType).getExtendsBound();
        }
      }
      else {
        myLabeler.markFailedConversion(typeView.getType(), value);
        return;
      }
      final TypeView left = new TypeView(psiParameter, null, null);
      if (TypeInfection.getInfection(left, typeView) == TypeInfection.LEFT_INFECTED) {
        PsiType iterableType;
        final PsiType typeViewType = typeView.getType();
        if (typeViewType instanceof PsiArrayType) {
          iterableType = left.getType().createArrayType();
        } else {
          final PsiClass iterableClass = PsiUtil.resolveClassInType(typeViewType);
          LOG.assertTrue(iterableClass != null);

          final PsiType targetType = getTargetTypeParameter(iterableClass, value, typeView);
          final PsiClass typeParam = PsiUtil.resolveClassInClassTypeOnly(targetType);
          if (!(typeParam instanceof PsiTypeParameter)) return;

          final Map<PsiTypeParameter, PsiType> substMap = Collections.singletonMap(((PsiTypeParameter)typeParam), left.getType());

          final PsiElementFactory factory = JavaPsiFacade.getElementFactory(iterableClass.getProject());
          iterableType = factory.createType(iterableClass, factory.createSubstitutor(substMap));
        }
        myLabeler.migrateExpressionType(value, iterableType, myStatement, TypeConversionUtil.isAssignable(iterableType, typeViewType), true);
      } else {
        processVariable(psiParameter, value, psiType, null, null, false);
      }
    }
  }
@Override
  public void visitForeachStatement(@NotNull PsiForeachStatement statement)