protected @Nullable CandidateInfo guardedOverloadResolution(@NotNull List<CandidateInfo> conflicts) {
    if (conflicts.isEmpty()) return null;
    if (conflicts.size() == 1) return conflicts.get(0);

    checkStaticMethodsOfInterfaces(conflicts);
    if (conflicts.size() == 1) return conflicts.get(0);

    final Map<MethodCandidateInfo, PsiSubstitutor> map = FactoryMap.create(key -> key.getSubstitutor(false));
    boolean atLeastOneMatch = checkParametersNumber(conflicts, getActualParametersLength(), map, true);
    if (conflicts.size() == 1) return conflicts.get(0);

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

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

    checkParametersNumber(conflicts, getActualParametersLength(), map, false);
    if (conflicts.size() == 1) return conflicts.get(0);

    if (atLeastOneMatch) {
      checkPotentiallyCompatibleMethods(conflicts);
      if (conflicts.size() == 1) return conflicts.get(0);
    }

    final int applicabilityLevel = checkApplicability(conflicts, map);
    if (conflicts.size() == 1) return conflicts.get(0);

    // makes no sense to do further checks, because if no one candidate matches by parameters count
    // then noone can be more specific
    if (!atLeastOneMatch) return null;

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

    checkPrimitiveVarargs(conflicts, getActualParametersLength());
    if (conflicts.size() == 1) return conflicts.get(0);

    Set<CandidateInfo> uniques = new HashSet<>(conflicts);
    if (uniques.size() == 1) return uniques.iterator().next();
    return null;
  }
protected @Nullable CandidateInfo guardedOverloadResolution(@NotNull List<CandidateInfo> conflicts)