void () { final Set<PsiTypeVariable> nodes = new HashSet<>(); final Set<Constraint> candidates = new HashSet<>(); final Map<PsiTypeVariable, Set<PsiTypeVariable>> ins = new HashMap<>(); final Map<PsiTypeVariable, Set<PsiTypeVariable>> outs = new HashMap<>(); for (final Constraint constraint : myConstraints) { final PsiType left = constraint.getLeft(); final PsiType right = constraint.getRight(); if (left instanceof PsiTypeVariable leftVar && right instanceof PsiTypeVariable rightVar) { candidates.add(constraint); nodes.add(leftVar); nodes.add(rightVar); Set<PsiTypeVariable> in = ins.get(leftVar); Set<PsiTypeVariable> out = outs.get(rightVar); if (in == null) { final Set<PsiTypeVariable> newIn = new HashSet<>(); newIn.add(rightVar); ins.put(leftVar, newIn); } else { in.add(rightVar); } if (out == null) { final Set<PsiTypeVariable> newOut = new HashSet<>(); newOut.add(leftVar); outs.put(rightVar, newOut); } else { out.add(leftVar); } } } final DFSTBuilder<PsiTypeVariable> dfstBuilder = new DFSTBuilder<>(new Graph<>() { @NotNull @Override public Collection<PsiTypeVariable> getNodes() { return nodes; } @NotNull @Override public Iterator<PsiTypeVariable> getIn(final PsiTypeVariable n) { final Set<PsiTypeVariable> in = ins.get(n); if (in == null) { return Collections.emptyIterator(); } return in.iterator(); } @NotNull @Override public Iterator<PsiTypeVariable> getOut(final PsiTypeVariable n) { final Set<PsiTypeVariable> out = outs.get(n); if (out == null) { return Collections.emptyIterator(); } return out.iterator(); } }); IntList sccs = dfstBuilder.getSCCs(); Object2IntMap<PsiTypeVariable> index = new Object2IntOpenHashMap<>(); int tNumber = 0; for (IntListIterator iterator = sccs.iterator(); iterator.hasNext(); ) { int size = iterator.nextInt(); for (int j = 0; j < size; j++) { index.put(dfstBuilder.getNodeByTNumber(tNumber + j), tNumber); } tNumber += size; } for (Constraint constraint : candidates) { if (index.getInt(constraint.getLeft()) == index.getInt(constraint.getRight())) { myConstraints.remove(constraint); } } Binding binding = myBindingFactory.create(); for (PsiTypeVariable fromVar : index.keySet()) { PsiTypeVariable toVar = dfstBuilder.getNodeByNNumber(index.getInt(fromVar)); if (!fromVar.equals(toVar)) { binding = binding.compose(myBindingFactory.create(fromVar, toVar)); if (binding == null) { break; } } } if (binding != null && binding.nonEmpty()) { myCurrentBinding = myCurrentBinding.compose(binding); myConstraints = apply(binding); } }