docs: private static boolean typesEquivalent(ParameterizedType typeToMatch, ParameterizedType type, ResolutionContext ctx) {
          if (!typeToMatch.getRawType().equals(type.getRawType())) {
              return false;
          }
  
          Type[] typesA = typeToMatch.getActualTypeArguments();
          Type[] typesB = type.getActualTypeArguments();
  
          if (typesA.length != typesB.length) {
              return false;
          }
  
          for (int i = 0; i < typesA.length; i++) {
              if (!typesEquivalent(typesA[i], ctx.resolve(typesB[i]), ctx)) {
                  return false;
              }
          }
  
          return true;
      }