boolean (Set<ConstraintFormula> additionalConstraints, Set<ConstraintFormula> ignoredConstraints) { //empty substitutor should be used to resolve input variables: //all types in additional constraints are already substituted during collecting phase, //recursive site substitutors (T -> List<T>) would make additional constraints work with multiple times substituted types, which is incorrect. //at the same time, recursive substitutions should not appear during inference but appear rather on site, //so the problem should not influence consequence substitution of additional constraints final PsiSubstitutor siteSubstitutor = PsiSubstitutor.EMPTY; while (!additionalConstraints.isEmpty()) { //extract subset of constraints final Set<ConstraintFormula> subset = buildSubset(additionalConstraints, ignoredConstraints); //collect all input variables of selection final Set<InferenceVariable> varsToResolve = new LinkedHashSet<>(); for (ConstraintFormula formula : subset) { if (formula instanceof InputOutputConstraintFormula) { collectVarsToResolve(varsToResolve, (InputOutputConstraintFormula)formula); } } final PsiSubstitutor substitutor = resolveSubsetOrdered(varsToResolve, siteSubstitutor); for (ConstraintFormula formula : subset) { if (!processOneConstraint(formula, additionalConstraints, substitutor, ignoredConstraints)) return false; } } return true; }