@NotNull
  PsiSubstitutor performGuardedInference(PsiParameter @Nullable [] parameters,
                                         PsiExpression @Nullable [] args,
                                         @Nullable PsiElement parent,
                                         @Nullable MethodCandidateInfo currentMethod,
                                         @NotNull PsiSubstitutor initialSubstitutor,
                                         boolean prohibitCaching) {
    if (!prohibitCaching) {
      prohibitCaching = MethodCandidateInfo.isOverloadCheck() ||
                        !(parent instanceof PsiMethodCallExpression &&
                          ((PsiMethodCallExpression)parent).getMethodExpression().multiResolve(false).length == 1);
    }
    return ThreadLocalTypes.performWithTypes(types -> {
      myTempTypes = types;
      try {
        doInfer(parameters, args, parent, currentMethod, initialSubstitutor);
        return prepareSubstitution();
      }
      finally {
        if (currentMethod != null) {
          if (myErrorMessages != null) {
            currentMethod.setApplicabilityError(StringUtil.join(myErrorMessages, "\n"));
          }
          if (myErased) {
            currentMethod.setErased();
          }
        }
        myTempTypes = null;
      }
    }, prohibitCaching);
  }
@NotNull
  PsiSubstitutor performGuardedInference(PsiParameter @Nullable [] parameters,
                                         PsiExpression @Nullable [] args,
                                         @Nullable PsiElement parent,
                                         @Nullable MethodCandidateInfo currentMethod,
                                         @NotNull PsiSubstitutor initialSubstitutor,
                                         boolean prohibitCaching)