@Override
    protected @Nullable CandidateInfo guardedOverloadResolution(@NotNull List<CandidateInfo> conflicts) {
      if (mySignature == null) return null;

      if (conflicts.isEmpty()) return null;
      if (conflicts.size() == 1) return conflicts.get(0);
      final Map<MethodCandidateInfo, PsiSubstitutor> map = FactoryMap.create(key -> key.getSubstitutor(false));

      checkSameSignatures(conflicts, map);
      if (conflicts.size() == 1) return  conflicts.get(0);

      checkAccessStaticLevels(conflicts, true);
      if (conflicts.size() == 1) return  conflicts.get(0);

      PsiType[] argTypes = mySignature.getParameterTypes();
      boolean hasReceiver = PsiMethodReferenceUtil.isSecondSearchPossible(argTypes, myQualifierResolveResult, myReferenceExpression);

      List<CandidateInfo> firstCandidates = new ArrayList<>();
      List<CandidateInfo> secondCandidates = new ArrayList<>();

      for (CandidateInfo conflict : conflicts) {
        if (!(conflict instanceof MethodCandidateInfo)) continue;
        Boolean applicableByFirstSearch = isApplicableByFirstSearch(conflict, argTypes, hasReceiver, myReferenceExpression, myFunctionalMethodVarArgs, myInterfaceMethod);
        if (applicableByFirstSearch != null) {
          (applicableByFirstSearch ? firstCandidates : secondCandidates).add(conflict);
        }
      }

      if (myQualifierResolveResult.isReferenceTypeQualified() && myReferenceExpression.getReferenceNameElement() instanceof PsiIdentifier) {
        int firstApplicability = checkApplicability(firstCandidates);
        ArrayList<CandidateInfo> firstResults = new ArrayList<>(firstCandidates);
        checkSpecifics(firstResults, firstApplicability, map, 0);

        int secondApplicability = checkApplicability(secondCandidates);
        ArrayList<CandidateInfo> secondResults = new ArrayList<>(secondCandidates);
        checkSpecifics(secondResults, secondApplicability, map, 1);

        //If the first search produces a static method, and no non-static method is applicable for the second search, then the result of the first search is the compile-time declaration.
        CandidateInfo candidateInfo = filterStaticCorrectCandidates(firstResults, secondCandidates, true);
        if (candidateInfo != null) {
          return candidateInfo;
        }

        //If the second search produces a non-static method, and no static method is applicable for the first search, then the result of the second search is the compile-time declaration.
        candidateInfo = filterStaticCorrectCandidates(secondResults, firstCandidates, false);
        if (candidateInfo != null) {
          return candidateInfo;
        }

        conflicts.clear();
        conflicts.addAll(firstResults);
        conflicts.addAll(secondResults);

        return null;
      }

      CandidateInfo candidateInfo = resolveConflicts(firstCandidates, secondCandidates, map, MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY);
      if (candidateInfo != null) {
        return candidateInfo;
      }

      candidateInfo = resolveConflicts(firstCandidates, secondCandidates, map, MethodCandidateInfo.ApplicabilityLevel.VARARGS);
      if (candidateInfo != null) {
        return candidateInfo;
      }

      if (firstCandidates.isEmpty() && secondCandidates.isEmpty()) {
        return null;
      }

      conflicts.clear();
      firstCandidates.addAll(secondCandidates);
      conflicts.addAll(firstCandidates);
      return null;
    }
@Override
    protected @Nullable CandidateInfo guardedOverloadResolution(@NotNull List<CandidateInfo> conflicts)