@Override
  public boolean reduce(InferenceSession session, List<? super ConstraintFormula> constraints) {
    PsiType myT = getCurrentType();
    if (!PsiPolyExpressionUtil.isPolyExpression(myExpression)) {

      PsiType exprType = myExpression.getType();

      if (session.isProperType(myT)) {
        final boolean assignmentCompatible = exprType == null || TypeConversionUtil.isAssignable(myT, exprType);
        if (!assignmentCompatible) {
          final PsiType type = myExpression.getType();
          session.registerIncompatibleErrorMessage(
            JavaPsiBundle.message("error.incompatible.type", type != null ? type.getPresentableText() : myExpression.getText(), session.getPresentableText(myT)));
        }
        else if (TypeCompatibilityConstraint.isUncheckedConversion(myT, exprType, session) && !JavaGenericsUtil.isReifiableType(myT)) {
          session.setErased();
        }
        return assignmentCompatible;
      }

      if (exprType instanceof PsiLambdaParameterType) {
        return false;
      }

      if (exprType instanceof PsiClassType) {
        if (((PsiClassType)exprType).resolve() == null) {
          return true;
        }
      }

      if (exprType != null && exprType != PsiTypes.nullType()) {
        if (exprType instanceof PsiDisjunctionType) {
          exprType = ((PsiDisjunctionType)exprType).getLeastUpperBound();
        }

        constraints.add(new TypeCompatibilityConstraint(myT, exprType));
      }
      return true;
    }
    if (myExpression instanceof PsiParenthesizedExpression) {
      final PsiExpression expression = ((PsiParenthesizedExpression)myExpression).getExpression();
      if (expression != null && !InferenceSession.ignoreLambdaConstraintTree(expression)) {
        constraints.add(new ExpressionCompatibilityConstraint(expression, myT));
        return true;
      }
    }

    if (myExpression instanceof PsiConditionalExpression) {
      final PsiExpression thenExpression = ((PsiConditionalExpression)myExpression).getThenExpression();
      if (thenExpression != null && !InferenceSession.ignoreLambdaConstraintTree(thenExpression)) {
        constraints.add(new ExpressionCompatibilityConstraint(thenExpression, myT));
      }

      final PsiExpression elseExpression = ((PsiConditionalExpression)myExpression).getElseExpression();
      if (elseExpression != null && !InferenceSession.ignoreLambdaConstraintTree(elseExpression)) {
        constraints.add(new ExpressionCompatibilityConstraint(elseExpression, myT));
      }
      return true;
    }

    if (myExpression instanceof PsiSwitchExpression) {
      PsiUtil.getSwitchResultExpressions((PsiSwitchExpression)myExpression).forEach(expression -> {
        if (!InferenceSession.ignoreLambdaConstraintTree(expression)) {
          constraints.add(new ExpressionCompatibilityConstraint(expression, myT));
        }
      });
      return true;
    }

    if (myExpression instanceof PsiCall) {
      final InferenceSession callSession = reduceExpressionCompatibilityConstraint(session, myExpression, myT, true);
      if (callSession == null) {
        return false;
      }
      if (callSession != session) {
        session.getInferenceSessionContainer().registerNestedSession(callSession);
        session.propagateVariables(callSession);
        for (Pair<InferenceVariable[], PsiClassType> pair : callSession.myIncorporationPhase.getCaptures()) {
          session.myIncorporationPhase.addCapture(pair.first, pair.second);
        }
        final MethodCandidateInfo currentMethod = session.getCurrentMethod(((PsiCall)myExpression).getArgumentList());
        final JavaResolveResult resolveResult = currentMethod != null ? currentMethod : PsiDiamondType.getDiamondsAwareResolveResult((PsiCall)myExpression);
        if (resolveResult instanceof MethodCandidateInfo && callSession.isErased()) {
          ((MethodCandidateInfo)resolveResult).setErased();
        }
      }
      return true;
    }

    if (myExpression instanceof PsiMethodReferenceExpression) {
      constraints.add(new PsiMethodReferenceCompatibilityConstraint((PsiMethodReferenceExpression)myExpression, myT));
      return true;
    }

    if (myExpression instanceof PsiLambdaExpression) {
      constraints.add(new LambdaExpressionCompatibilityConstraint((PsiLambdaExpression)myExpression, myT));
      return true;
    }


    return true;
  }
@Override
  public boolean reduce(InferenceSession session, List<? super ConstraintFormula> constraints)