docs: private static ClassNode parameterizeLowestUpperBound(final ClassNode lub, final ClassNode a, final ClassNode b, final ClassNode fallback) {
          if (!lub.isUsingGenerics()) return lub;
          // a common super type exists, all we have to do is to parameterize
          // it according to the types provided by the two class nodes
          ClassNode holderForA = findGenericsTypeHolderForClass(a, lub);
          ClassNode holderForB = findGenericsTypeHolderForClass(b, lub);
          // let's compare their generics type
          GenericsType[] agt = holderForA == null ? null : holderForA.getGenericsTypes();
          GenericsType[] bgt = holderForB == null ? null : holderForB.getGenericsTypes();
          if (agt==null || bgt==null || agt.length!=bgt.length) {
              return lub;
          }
          GenericsType[] lubgt = new GenericsType[agt.length];
          for (int i = 0; i < agt.length; i++) {
              ClassNode t1 = agt[i].getType();
              ClassNode t2 = bgt[i].getType();
              ClassNode basicType;
              if (areEqualWithGenerics(t1, a) && areEqualWithGenerics(t2,b)) {
                  // we are facing a self referencing type !
                  basicType = fallback;
              } else {
                   basicType = lowestUpperBound(t1, t2);
              }
              if (t1.equals(t2)) {
                  lubgt[i] = new GenericsType(basicType);
              } else {
                  lubgt[i] = GenericsUtils.buildWildcardType(basicType);
              }
          }
          ClassNode plain = lub.getPlainNodeReference();
          plain.setGenericsTypes(lubgt);
          return plain;
      }