private static boolean areTypesEqual(@Nullable PsiType type, @Nullable PsiType bound){
    if (type == null || bound == null) return false;
    PsiType typeErasure = TypeConversionUtil.erasure(type);
    PsiType boundErasure = TypeConversionUtil.erasure(bound);
    if(!typeErasure.equals(boundErasure)) return false;
    if (!(type instanceof PsiClassType classType && bound instanceof PsiClassType boundClassType)) return true;
    PsiType[] typeParameters = classType.getParameters();
    PsiType[] boundParameters = boundClassType.getParameters();
    if (typeParameters.length != boundParameters.length) return false;
    for (int i = 0; i < typeParameters.length; i++) {
      if (!areTypesEqual(typeParameters[i], boundParameters[i])) return false;
    }
    return true;
  }
private static boolean areTypesEqual(@Nullable PsiType type, @Nullable PsiType bound)