private void doInfer(PsiParameter @Nullable [] parameters,
                       PsiExpression @Nullable [] args,
                       @Nullable PsiElement parent,
                       @Nullable MethodCandidateInfo properties,
                       @NotNull PsiSubstitutor initialSubstitutor) {
    if (!repeatInferencePhases()) {
      return;
    }

    PsiExpressionList argumentList = getArgumentList(parent);
    if (properties != null && argumentList != null && !MethodCandidateInfo.isOverloadCheck(argumentList)) {
      final PsiMethod method = properties.getElement();
      if (parent instanceof PsiCallExpression && PsiPolyExpressionUtil.isMethodCallPolyExpression((PsiExpression)parent, method)) {
        final PsiType returnType = method.getReturnType();
        if (!PsiTypes.voidType().equals(returnType) && returnType != null) {
          final Ref<String> errorMessage = new Ref<>();
          final PsiType targetType = getTargetTypeFromParent(parent, errorMessage, false);
          if (targetType == null && errorMessage.get() != null) {
            return;
          }

          if (targetType != null && !PsiTypes.voidType().equals(targetType)) {
            PsiType actualType = PsiUtil.isRawSubstitutor(method, mySiteSubstitutor) ? returnType : mySiteSubstitutor.substitute(returnType);
            registerReturnTypeConstraints(actualType, targetType, myContext);
          }
        }
      }

      if (!repeatInferencePhases()) {
        if (isPertinentToApplicabilityCheckOnContainingCall(parent)) {
          return;
        }
      }
      //proceed to B3 constraints
      else if (parameters != null && parameters.length > 0 && args != null && !isPertinentToApplicabilityCheckOnContainingCall(parent)) {
        final Set<ConstraintFormula> additionalConstraints = new LinkedHashSet<>();
        final HashSet<ConstraintFormula> ignoredConstraints = new HashSet<>();
        collectAdditionalConstraints(parameters, args, method, mySiteSubstitutor, additionalConstraints,
                                     ignoredConstraints, properties.isVarargs(), initialSubstitutor);

        proceedWithAdditionalConstraints(additionalConstraints, ignoredConstraints);
      }
    }

    resolveBounds(myInferenceVariables, initialSubstitutor);
  }
private void doInfer(PsiParameter @Nullable [] parameters,
                       PsiExpression @Nullable [] args,
                       @Nullable PsiElement parent,
                       @Nullable MethodCandidateInfo properties,
                       @NotNull PsiSubstitutor initialSubstitutor)