Set<PyClass> (@NotNull PyClass pyClass, @NotNull TypeEvalContext context, @NotNull Map<PyClass, Set<PyClass>> ancestorsCache) { final Set<PyClass> ancestors = ancestorsCache.get(pyClass); if (ancestors != null) { return ancestors; } // Sentinel value to prevent infinite recursion ancestorsCache.put(pyClass, Collections.emptySet()); final Set<PyClass> result = new HashSet<>(); try { for (final PyClassLikeType baseType : pyClass.getSuperClassTypes(context)) { if (!(baseType instanceof PyClassType)) { continue; } final PyClass baseClass = ((PyClassType)baseType).getPyClass(); result.add(baseClass); result.addAll(getAncestorClassesFast(baseClass, context, ancestorsCache)); } } finally { // May happen in case of cyclic inheritance result.remove(pyClass); ancestorsCache.put(pyClass, Collections.unmodifiableSet(result)); } return result; }