docs: public static boolean isEqual(Type type1, Type type2)
    {
      if(type1 == null) {
        return type2 == null;
      }
      if(type2 == null) {
        return type1 == null;
      }
      if(!(type1 instanceof ParameterizedType)) {
        return type1.equals(type2);
      }
  
      // handle parameterized types
  
      if(!(type2 instanceof ParameterizedType)) {
        return false;
      }
      ParameterizedType ptype1 = (ParameterizedType)type1;
      ParameterizedType ptype2 = (ParameterizedType)type2;
      if(!ptype1.getRawType().equals(ptype2.getRawType())) {
        return false;
      }
      Type[] atype1 = ptype1.getActualTypeArguments();
      Type[] atype2 = ptype2.getActualTypeArguments();
      if(atype1.length != atype2.length) {
        return false;
      }
      for(int i = 0; i < atype1.length; ++i) {
        if(!isEqual(atype1[i], atype2[i])) {
          return false;
        }
      }
      return true;
    }