private static void collectGenerics(@Nullable PyType type,
                                      @NotNull TypeEvalContext context,
                                      @NotNull Generics generics,
                                      @NotNull Set<? super PyType> visited) {
    if (type instanceof PyTypeParameterType typeParameter) {
      generics.allTypeParameters.add(typeParameter);
    }
    if (visited.contains(type)) {
      return;
    }
    visited.add(type);
    if (type instanceof PyTypeVarType typeVarType) {
      generics.typeVars.add(typeVarType);
    }
    if (type instanceof PyTypeVarTupleType typeVarTupleType) {
      generics.typeVarTuples.add(typeVarTupleType);
    }
    // TODO Filter out PyParamSpecTypes representing actual lists of parameters, not type parameters declared via ParamSpec
    if (type instanceof PyParamSpecType) {
      generics.paramSpecs.add((PyParamSpecType)type);
    }
    // TODO These are not type parameters at all
    if (type instanceof PyConcatenateType) {
      generics.concatenates.add((PyConcatenateType)type);
    }
    if (type instanceof PySelfType) {
      generics.self = (PySelfType)type;
    }
    else if (type instanceof PyUnionType union) {
      for (PyType t : union.getMembers()) {
        collectGenerics(t, context, generics, visited);
      }
    }
    else if (type instanceof PyTupleType tuple) {
      final int n = tuple.isHomogeneous() ? 1 : tuple.getElementCount();
      for (int i = 0; i < n; i++) {
        collectGenerics(tuple.getElementType(i), context, generics, visited);
      }
    }
    else if (type instanceof PyCollectionType collection) {
      for (PyType elementType : collection.getElementTypes()) {
        collectGenerics(elementType, context, generics, visited);
      }
    }
    else if (type instanceof PyCallableType callable && !(type instanceof PyClassLikeType)) {
      final List<PyCallableParameter> parameters = callable.getParameters(context);
      if (parameters != null) {
        for (PyCallableParameter parameter : parameters) {
          if (parameter != null) {
            collectGenerics(parameter.getType(context), context, generics, visited);
          }
        }
      }
      collectGenerics(callable.getReturnType(context), context, generics, visited);
    }
    else if (type instanceof PyUnpackedTupleType unpackedTupleType) {
      for (PyType elementType : unpackedTupleType.getElementTypes()) {
        collectGenerics(elementType, context, generics, visited);
      }
    }
  }
private static void collectGenerics(@Nullable PyType type,
                                      @NotNull TypeEvalContext context,
                                      @NotNull Generics generics,
                                      @NotNull Set<? super PyType> visited)