private static boolean isFunctionalTypeMoreSpecific(PsiExpression expr, PsiType sType, PsiType tType) {
    if (expr instanceof PsiParenthesizedExpression) {
      return isFunctionalTypeMoreSpecific(((PsiParenthesizedExpression)expr).getExpression(), sType, tType);
    }

    if (expr instanceof PsiConditionalExpression) {
      return isFunctionalTypeMoreSpecific(((PsiConditionalExpression)expr).getThenExpression(), sType, tType) &&
             isFunctionalTypeMoreSpecific(((PsiConditionalExpression)expr).getElseExpression(), sType, tType);
    }

    if (expr instanceof PsiSwitchExpression) {
      return PsiUtil.getSwitchResultExpressions((PsiSwitchExpression)expr).stream().allMatch(resultExpr -> isFunctionalTypeMoreSpecific(resultExpr, sType, tType));
    }

    if (expr instanceof PsiFunctionalExpression) {

      if (expr instanceof PsiLambdaExpression && !((PsiLambdaExpression)expr).hasFormalParameterTypes()) {
        return false;
      }
      if (expr instanceof PsiMethodReferenceExpression && !((PsiMethodReferenceExpression)expr).isExact()) {
        return false;
      }

      if (LambdaUtil.isFunctionalType(sType) && LambdaUtil.isFunctionalType(tType) &&
          !TypeConversionUtil.erasure(tType).isAssignableFrom(sType) &&
          !TypeConversionUtil.erasure(sType).isAssignableFrom(tType)) {
        return InferenceSession.isFunctionalTypeMoreSpecificOnExpression(sType, tType, expr);
      }
    }
    return false;
  }
private static boolean isFunctionalTypeMoreSpecific(PsiExpression expr, PsiType sType, PsiType tType)